我尝试使用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生成的数据密钥加密数据的建议方法是什么?
答案 0 :(得分:3)
@Viccari是正确的,但听起来围绕这些结构的预期用途的某些上下文有助于解释原因。
除非您要构建自定义加密材料管理器,否则不应创建EncryptionMaterials
;客户和管理组件会为您解决这个问题。
客户端向加密材料管理员询问每次加密调用的加密资料。根据加密材料管理器的不同,接下来可能会发生什么不同。
在DefaulCryptoMaterialsManager
的情况下,它然后要求提供的主密钥提供者使用所有主密钥,然后使用这些主密钥生成和加密数据密钥(一个用于生成和加密,任何其他用于加密)。
在CachingCryptoMaterialsManager
的情况下,它在客户端和另一个加密材料管理器之间添加了一个缓存层。
如果您想将AWS加密SDK与AWS KMS一起使用,建议的方法是简单地提供KmsMasterKey
或KmsMasterKeyProvider
的实例,或最终使用其中一个的加密材料管理器,在加密调用中。所有细节都由客户处理。
如果您对如何将这些概念融合在一起的更多细节感兴趣,我们的概念文档[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
。它提供了诸如确保数据密钥不被无限次使用的保证。