### Question:
DirectKmsMaterialProvider implements EncryptionMaterialsProvider { @Override public EncryptionMaterials getEncryptionMaterials(EncryptionContext context) { final Map<String, String> ec = new HashMap<>(); ec.put("*" + CONTENT_KEY_ALGORITHM + "*", dataKeyDesc); ec.put("*" + SIGNING_KEY_ALGORITHM + "*", sigKeyDesc); populateKmsEcFromEc(context, ec); final String keyId = selectEncryptionKeyId(context); if (StringUtils.isNullOrEmpty(keyId)) { throw new DynamoDBMappingException("Encryption key id is empty."); } final GenerateDataKeyRequest req = appendUserAgent(new GenerateDataKeyRequest()); req.setKeyId(keyId); req.setNumberOfBytes(256 / 8); req.setEncryptionContext(ec); final GenerateDataKeyResult dataKeyResult = generateDataKey(req, context); final Map<String, String> materialDescription = new HashMap<>(); materialDescription.putAll(description); materialDescription.put(COVERED_ATTR_CTX_KEY, KEY_COVERAGE); materialDescription.put(KEY_WRAPPING_ALGORITHM, "kms"); materialDescription.put(CONTENT_KEY_ALGORITHM, dataKeyDesc); materialDescription.put(SIGNING_KEY_ALGORITHM, sigKeyDesc); materialDescription.put(ENVELOPE_KEY, Base64.encodeToString(toArray(dataKeyResult.getCiphertextBlob()))); final Hkdf kdf; try { kdf = Hkdf.getInstance(KDF_ALG); } catch (NoSuchAlgorithmException e) { throw new DynamoDBMappingException(e); } kdf.init(toArray(dataKeyResult.getPlaintext())); final SecretKey encryptionKey = new SecretKeySpec(kdf.deriveKey(KDF_ENC_INFO, dataKeyLength / 8), dataKeyAlg); final SecretKey signatureKey = new SecretKeySpec(kdf.deriveKey(KDF_SIG_INFO, sigKeyLength / 8), sigKeyAlg); return new SymmetricRawMaterials(encryptionKey, signatureKey, materialDescription); } DirectKmsMaterialProvider(AWSKMS kms);  DirectKmsMaterialProvider(AWSKMS kms, String encryptionKeyId, Map<String, String> materialDescription);  DirectKmsMaterialProvider(AWSKMS kms, String encryptionKeyId); @Override DecryptionMaterials getDecryptionMaterials(EncryptionContext context); @Override EncryptionMaterials getEncryptionMaterials(EncryptionContext context); @Override void refresh();  }### Answer:
@Test public void randomEnvelopeKeys() throws GeneralSecurityException { DirectKmsMaterialProvider prov = new DirectKmsMaterialProvider(kms, keyId); EncryptionMaterials eMat = prov.getEncryptionMaterials(ctx); SecretKey encryptionKey = eMat.getEncryptionKey(); assertNotNull(encryptionKey); EncryptionMaterials eMat2 = prov.getEncryptionMaterials(ctx); SecretKey encryptionKey2 = eMat2.getEncryptionKey(); assertFalse("Envelope keys must be different", encryptionKey.equals(encryptionKey2)); }
@Test(expectedExceptions = DynamoDBMappingException.class) public void missingEncryptionKeyId() throws GeneralSecurityException { ExtendedKmsMaterialProvider prov = new ExtendedKmsMaterialProvider(kms, keyId, "encryptionKeyId"); Map<String, AttributeValue> attrVals = new HashMap<>(); attrVals.put("hk", new AttributeValue().withN("10")); attrVals.put("rk", new AttributeValue().withN("20")); ctx = new EncryptionContext.Builder().withHashKeyName("hk").withRangeKeyName("rk") .withTableName("KmsTableName").withAttributeValues(attrVals).build(); prov.getEncryptionMaterials(ctx); }