0

有没有人使用 Google 的 HSM 和 KMS 服务实现加密消息语法?

很难判断此功能是否内置在Tink库中。

没有适用于 OpenSSL 或 BoringSSL 的 Google 引擎(如果不是这种情况,希望得到纠正)并且由于引擎需要用 clang 编写,我想包含 tink.so 库相当困难?

如果有人有任何关于在 Google 的 KMS 服务上执行这些类型的操作的信息,将不胜感激。

4

2 回答 2

3

目前,这需要相当多的自定义代码,尽管这在技术上是可行的。此功能未内置在 Tink 中,也没有可用于 OpenSSL 或 BoringSSL 的 Cloud KMS 引擎。

可能最简单的方法是在 Bouncycastle 中使用具有 CMS 支持的 Cloud KMS Java 客户端,但我不确定 Java 是否适合您的用例。如果您认为它有用,我可以写一个如何做到这一点的示例。

于 2019-02-12T00:34:37.950 回答
0

感谢@bdhess 的指导!

我为那些有兴趣尝试类似功能的人提供了一些代码片段。需要注意的主要类是ContentSignerFactory.javaAPI 魔法发生的地方。

bouncycastle 有一个非常有用的 pdf:https ://www.bouncycastle.org/fips-java/BCFipsIn100.pdf

注意:我不是 java 程序员

Cms.java

public class Cms {
    public static byte[] signDataKms(
            String credentialsKeyPath,
            String keyName,
            X509Certificate signingCert,
            byte data[]) throws Exception {

        List<X509Certificate> certList = new ArrayList<>();
        certList.add(signingCert);
        Store certs = new JcaCertStore(certList);

        CMSTypedData cmsData = new CMSProcessableByteArray(data);

        DigestCalculatorProvider digProvider =
                new JcaDigestCalculatorProviderBuilder().setProvider("BC").build();
        JcaSignerInfoGeneratorBuilder signerInfoGeneratorBuilder =
                new JcaSignerInfoGeneratorBuilder(digProvider);

        //SignedHash is a base64-encoded PKCS1 block.
        ContentSigner sha1Signer = ContentSignerFactory.getContentSigner((stream) -> {
            try {
                return Kms.signAsymmetric(credentialsKeyPath, keyName, stream.toByteArray());
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return new byte[0];
        }, "SHA256WITHRSA");

        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();

        gen.addSignerInfoGenerator(signerInfoGeneratorBuilder.build(sha1Signer, signingCert));
        gen.addCertificates(certs);
        CMSSignedData cms = gen.generate(cmsData, true);

        return cms.toASN1Structure().getEncoded(ASN1Encoding.DER);
    }
}

ContentSignerFactory.java

public class ContentSignerFactory {

    public static ContentSigner getContentSigner(Function<ByteArrayOutputStream, byte[]> lambda, String algorithm) {
        return new ContentSigner() {
            //This is to ensure that signature is created using the right data.
            ByteArrayOutputStream stream = new ByteArrayOutputStream();

            @Override
            public byte[] getSignature() {
                //Calling HSM here instead, the stream is the AttributeMap
                byte[] data = lambda.apply(stream);
                return data;
            }

            //Perhaps called by BouncyCastle library to provide the content
            @Override
            public OutputStream getOutputStream() {
                return stream;
            }

            @Override
            public AlgorithmIdentifier getAlgorithmIdentifier() {
                return new DefaultSignatureAlgorithmIdentifierFinder().find(algorithm);
            }
        };
    }
}

Kms.java

public class Kms {
    public static byte[] signAsymmetric(String credentialsKeyPath, String keyName, byte[] message)
            throws IOException, NoSuchAlgorithmException {
        // Create the Cloud KMS client.
        try (KeyManagementServiceClient client
                     = KeyManagementServiceClient.create(getKeyManagementServiceSettings(credentialsKeyPath))) {

            // Note: some key algorithms will require a different hash function
            // For example, EC_SIGN_P384_SHA384 requires SHA-384
            byte[] messageHash = MessageDigest.getInstance("SHA-256").digest(message);

            AsymmetricSignRequest request = AsymmetricSignRequest.newBuilder()
                    .setName(keyName)
                    .setDigest(Digest.newBuilder().setSha256(ByteString.copyFrom(messageHash)))
                    .build();

            AsymmetricSignResponse response = client.asymmetricSign(request);
            return response.getSignature().toByteArray();
        }
    }
}
于 2019-03-11T12:35:13.983 回答