google-cloud-kms PKCS7加密消息语法

时间:2019-02-11 20:28:28

标签: openssl google-cloud-kms tink

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

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

没有适用于OpenSSL或BoringSSL的Google引擎(如果不是这种情况,请予以纠正),并且由于该引擎需要用clang编写,我想添加tink.so库相当困难?

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

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

感谢@bdhess的方向!

我为有兴趣尝试类似功能的用户提供了一些代码段。要注意的主要类是ContentSignerFactory.java,这是API魔术发生的地方。

有一个关于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();
        }
    }
}