in src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKey.java [148:205]
public DataKey<AwsKmsMrkAwareMasterKey> generateDataKey(
final CryptoAlgorithm algorithm, final Map<String, String> encryptionContext) {
// = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
// # This
// # master key MUST use the configured AWS KMS client to make an AWS KMS
// # GenerateDatakey (https://docs.aws.amazon.com/kms/latest/APIReference/
// # API_GenerateDataKey.html) request constructed as follows:
final GenerateDataKeyResponse gdkResponse =
kmsClient_.generateDataKey(
GenerateDataKeyRequest.builder()
.overrideConfiguration(API_NAME_INTERCEPTOR)
.keyId(awsKmsIdentifier_)
.numberOfBytes(algorithm.getDataKeyLength())
.encryptionContext(encryptionContext)
.grantTokens(grantTokens_)
.build());
final ByteBuffer plaintextBuffer = gdkResponse.plaintext().asByteBuffer();
// = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
// # If the call succeeds the AWS KMS Generate Data Key response's
// # "Plaintext" MUST match the key derivation input length specified by
// # the algorithm suite included in the input.
if (plaintextBuffer.limit() != algorithm.getDataKeyLength()) {
throw new IllegalStateException("Received an unexpected number of bytes from KMS");
}
final byte[] rawKey = new byte[algorithm.getDataKeyLength()];
plaintextBuffer.get(rawKey);
// = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
// # The response's "KeyId"
// # MUST be valid.
final String gdkResponseKeyId = gdkResponse.keyId();
/* Exceptional Postcondition: Must have an AWS KMS ARN from AWS KMS generateDataKey. */
if (parseInfoFromKeyArn(gdkResponseKeyId) == null) {
throw new IllegalStateException("Received an empty or invalid keyId from KMS");
}
final ByteBuffer ciphertextBlobBuffer = gdkResponse.ciphertextBlob().asByteBuffer();
final byte[] encryptedKey = new byte[ciphertextBlobBuffer.remaining()];
ciphertextBlobBuffer.get(encryptedKey);
final SecretKeySpec key = new SecretKeySpec(rawKey, algorithm.getDataKeyAlgo());
// = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
// # The output MUST be the same as the Master Key Generate Data Key
// # (../master-key-interface.md#generate-data-key) interface.
return new DataKey<>(
// = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
// # The response's "Plaintext" MUST be the plaintext in
// # the output.
key,
// = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
// # The response's cipher text blob MUST be used as the
// # returned as the ciphertext for the encrypted data key in the output.
encryptedKey,
gdkResponseKeyId.getBytes(StandardCharsets.UTF_8),
this);
}