AWS Encryption SDK使用数据密钥加密/解密

时间:2018-01-24 01:00:10

标签: java amazon-web-services encryption aws-kms

我尝试使用KMS和AWS加密SDK加密数据。查看AWS documentation中提供的示例,似乎无处可明确设置数据密钥。

我找到了EncryptionMaterialsRequest类的API文档,它允许您使用关联的构建器类EncryptionMaterialsRequest.Builder设置明文密钥,并且此类有一个返回实例的方法EncryptionMaterials。在执行加密操作时,我无法在任何地方找到EncryptionMaterials实例。

这是我到目前为止的代码。请注意,EncryptionMaterials实例未在请求中使用。

public static void encryptData(String dataToEncrypt, String keyID) {
    final KmsMasterKeyProvider prov = new KmsMasterKeyProvider(keyID);
    DefaultCryptoMaterialsManager manager = new DefaultCryptoMaterialsManager(prov);

    byte[] plaintextKey = generateDataKey(keyID);
    EncryptionMaterialsRequest request = EncryptionMaterialsRequest
        .newBuilder()
        .setPlaintext(plaintextKey)
        .build();

    EncryptionMaterials materials = manager.getMaterialsForEncrypt(request);
    AwsCrypto crypto = new AwsCrypto();
    String encryptedString = crypto.encryptString(manager, dataToEncrypt).getResult();
}

public byte[] generateDataKey(String keyID) {
    GenerateDataKeyRequest dataKeyRequest = new GenerateDataKeyRequest();
    dataKeyRequest.setKeyId(keyID);
    dataKeyRequest.setKeySpec(DataKeySpec.AES_256);
    GenerateDataKeyResult dataKeyResult = kmsClient.generateDataKey(dataKeyRequest);
    ByteBuffer encryptedKey = dataKeyResult.getCiphertextBlob();
    byte[] arr = new byte[encryptedKey.remaining()];
    encryptedKey.get(arr);
    return arr;
}

使用AWS Encryption SDK使用KMS生成的数据密钥加密数据的建议方法是什么?

2 个答案:

答案 0 :(得分:3)

@Viccari是正确的,但听起来围绕这些结构的预期用途的某些上下文有助于解释原因。

除非您要构建自定义加密材料管理器,否则不应创建EncryptionMaterials;客户和管理组件会为您解决这个问题。

客户端向加密材料管理员询问每次加密调用的加密资料。根据加密材料管理器的不同,接下来可能会发生什么不同。

DefaulCryptoMaterialsManager的情况下,它然后要求提供的主密钥提供者使用所有主密钥,然后使用这些主密钥生成和加密数据密钥(一个用于生成和加密,任何其他用于加密)。

CachingCryptoMaterialsManager的情况下,它在客户端和另一个加密材料管理器之间添加了一个缓存层。

如果您想将AWS加密SDK与AWS KMS一起使用,建议的方法是简单地提供KmsMasterKeyKmsMasterKeyProvider的实例,或最终使用其中一个的加密材料管理器,在加密调用中。所有细节都由客户处理。

如果您对如何将这些概念融合在一起的更多细节感兴趣,我们的概念文档[1]将是一个很好的起点。

[1] https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html

答案 1 :(得分:2)

我的问题是:为什么不使用DefaultCryptoMaterialsManager,它应该为每个加密操作从主密钥生成一个新的数据密钥?你为什么要重用数据键?从安全角度来看,这听起来并不像是一种合理的方式。

但是如果你想这样做,你需要提供CryptoMaterialsManager接口的实现。

不是使用DefaultCryptoMaterialsManager,而是创建一个新类,比如MyCryptoMaterialsManager,它实现了上面的接口。

这样的事情可以做到:

public static void encryptData(String dataToEncrypt, String keyID) {
    // not sure whether you need this or where you're getting the data key from.
    final KmsMasterKeyProvider prov = new KmsMasterKeyProvider(keyID);
    MyCryptoMaterialsManager manager = new MyCryptoMaterialsManager(prov);

    byte[] plaintextKey = generateDataKey(keyID);
    EncryptionMaterialsRequest request = EncryptionMaterialsRequest
        .newBuilder()
        .setPlaintext(plaintextKey)
        .build();

    // this, you told you know how to do:
    EncryptionMaterials materials = manager.getMaterialsForEncrypt(request);
    AwsCrypto crypto = new AwsCrypto();
    String encryptedString = crypto.encryptString(manager, dataToEncrypt).getResult();
}

public byte[] generateDataKey(String keyID) {
    GenerateDataKeyRequest dataKeyRequest = new GenerateDataKeyRequest();
    dataKeyRequest.setKeyId(keyID);
    dataKeyRequest.setKeySpec(DataKeySpec.AES_256);
    GenerateDataKeyResult dataKeyResult = kmsClient.generateDataKey(dataKeyRequest);
    ByteBuffer encryptedKey = dataKeyResult.getCiphertextBlob();
    byte[] arr = new byte[encryptedKey.remaining()];
    encryptedKey.get(arr);
    return arr;
}

如果需要关注KMS的费用或次数,您也可以使用CachingCryptoMaterialsManager。它提供了诸如确保数据密钥不被无限次使用的保证。