public DataKey generateDataKey()

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