4

我正在尝试使用 KMS 和 AWS 加密 SDK 加密数据。查看AWS 文档中提供的示例,似乎没有明确设置数据键的地方。

我找到了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 加密 SDK 和 KMS 生成的数据密钥加密数据的推荐方法是什么?

4

2 回答 2

3

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

除非您正在构建自定义加密材料管理器,否则您不应该创建EncryptionMaterials;客户端和管理组件会为您处理这些问题。

客户端在每次加密调用时向加密材料管理器询问加密材料。根据加密材料管理器的不同,接下来发生的事情可能会有所不同。

在 的情况下DefaulCryptoMaterialsManager,它会向提供的主密钥提供者询问所有要使用的主密钥,然后使用这些主密钥生成和加密数据密钥(一个用于生成和加密,任何额外的用于加密)。

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

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

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

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

于 2018-02-15T23:00:34.217 回答
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改用。它提供了保证,例如确保数据密钥不会被无限次使用。

于 2018-01-24T16:15:02.637 回答