4

I'm attempting to encrypt data using KMS and the AWS Encryption SDK. Looking at the example provided in the AWS documentation, it appears that there is nowhere to explicitly set the data key.

I've found API documentation for the EncryptionMaterialsRequest class that allows you to set the plaintext key using the associated builder class, EncryptionMaterialsRequest.Builder, and this class has a method that returns an instance of EncryptionMaterials. I can't find anywhere to use the EncryptionMaterials instance when executing the encrypt operation.

Here is the code I have so far. Note that the EncryptionMaterials instance isn't used in the request.

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;
}

What is the recommended approach encrypting data using the AWS Encryption SDK with a data key generated by KMS?

Weston Sankey
  • 301
  • 4
  • 18
  • 1
    Does this example help (https://github.com/SergiiShapoval/AWS-KMS-encryption-example/blob/master/src/main/java/com/amazonaws/samples/KMSEncryptionSample.java)? – jarmod Jan 24 '18 at 01:18
  • That doesn't use the data key, and it only uses the KMS API. I'm trying to encrypt my data with the AWS Encryption SDK using a data key provided by the KMS API. – Weston Sankey Jan 26 '18 at 21:08

2 Answers2

3

@Viccari is correct, but it sounds like some context around the intended use of these constructs would help explain why.

Unless you are building a custom cryptographic materials manager you should not be creating EncryptionMaterials; the client and management components take care of that for you.

The client asks the cryptographic materials manager for encryption materials on every encrypt call. Depending on the cryptographic materials manager, what exactly happens next might be different.

In the case of the DefaulCryptoMaterialsManager, it then asks the provided master key provider for all of the master keys to use, then uses those master keys to generate and encrypt the data key (one is used to generate and encrypt, any additional are used to encrypt).

In the case of the CachingCryptoMaterialsManager, it adds a caching layer between the client and another cryptographic materials manager.

If you want to use the AWS Encryption SDK with AWS KMS, the recommended approach is to simply provide an instance of KmsMasterKey or KmsMasterKeyProvider, or a cryptographic materials manager that ultimately uses one of those, in the encrypt call. All of the details are taken care of by the client.

If you're interested in more details about how these concepts fit together, our concepts documentation[1] would be a good place to start.

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

mattsb42-aws
  • 276
  • 1
  • 4
2

My question for you would be: why not using the DefaultCryptoMaterialsManager, which should generate a new data key from the master key for each encryption operation? Why are you going to reuse the data keys? This does not sound like a sound approach from the security perspective.

But if you want to do that, you need to provide an implementation of the CryptoMaterialsManager interface.

Instead of using DefaultCryptoMaterialsManager, create a new class, let's say, MyCryptoMaterialsManager, that implements the interface above.

Something like this would do it:

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;
}

If cost or number of calls to KMS is a concern, you could also use the CachingCryptoMaterialsManager instead. It provides guarantees like making sure that a data key is not used an indefinite number of times.

Viccari
  • 9,029
  • 4
  • 43
  • 77
  • Is creating an implementation of `CryptoMaterialsManager` that handles data keys in a custom way the only way to implement envelope encryption using the AWS Encryption SDK? – Weston Sankey Feb 05 '18 at 14:09
  • @Viccari Use cases and security considerations surrounding data key caching (versus generating new data key for each operation) are dealt with in Encryption SDK docs here: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/data-key-caching.html – Daniel B. Feb 09 '18 at 10:21