From 72f7ce6b89d44d3fc7495351b2c43447536b0b16 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Wed, 11 Mar 2026 22:31:14 -0700 Subject: [PATCH 01/16] Add hash only test --- .../dynamodbv2/datamodeling/sdkv2/HolisticIT.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java index 8e7f600b20..fdafee1dd0 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java @@ -1123,8 +1123,18 @@ private void assertVersionCompatibility( assertTrue( new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decryptedRecord) ); + + // Atleast decrypt one item with only hash key. + EncryptionContext hashOnlyContext = EncryptionContext + .builder() + .tableName("HashKeyOnly") + .hashKeyName("hashKey") + .build(); + Map> hashOnlyActions = new HashMap<>(); + hashOnlyActions.put("hashKey", signOnly); - assertEquals("Foo", getItems(hashKey1, "HashKeyOnly").get("hashKey").s()); + Map decryptedHashOnlyRecord = encryptor.decryptRecord(getItems(hashKey1, "HashKeyOnly"), hashOnlyActions, hashOnlyContext); + assertEquals("Foo", decryptedHashOnlyRecord.get("hashKey").s()); assertEquals("Bar", getItems(hashKey2, "HashKeyOnly").get("hashKey").s()); assertEquals("Baz", getItems(hashKey3, "HashKeyOnly").get("hashKey").s()); From b2c464fea84d18ffe4d09d6f98d475b0a41e1ddd Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 12 Mar 2026 11:00:11 -0700 Subject: [PATCH 02/16] ec test --- .../datamodeling/sdkv2/HolisticIT.java | 219 +++++++++++++++++- 1 file changed, 218 insertions(+), 1 deletion(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java index fdafee1dd0..a3608c9ec8 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java @@ -16,7 +16,10 @@ import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.encryption.providers.WrappedMaterialsProvider; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.encryption.providers.store.MetaStore; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.encryption.providers.store.ProviderStore; -import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.*; +import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.LocalDynamoDb; +import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.ScenarioManifest; +import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.DdbRecordMatcher; +import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.AttributeValueDeserializer; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.ScenarioManifest.KeyData; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.ScenarioManifest.Keys; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.ScenarioManifest.Scenario; @@ -535,6 +538,220 @@ public static Object[][] getDecryptTestVectors() throws IOException { .toArray(Object[][]::new); } + @Test + public void generateNullTableNameVector() throws Exception { + localDynamoDb.start(); + client = localDynamoDb.createLimitedWrappedClient(); + createCiphertextTables(client); + + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext ctx = EncryptionContext.builder() + .tableName(null) + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); + + Map> actions = new HashMap<>(); + for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { + switch (attr) { + case "hashKey": case "rangeKey": case "version": + actions.put(attr, signOnly); break; + default: + actions.put(attr, encryptAndSign); break; + } + } + + Map encrypted = + encryptor.encryptRecord(ENCRYPTED_TEST_VALUE, actions, ctx); + + printJSON(encrypted); + + client.close(); + localDynamoDb.stop(); + } + + @Test + public void generateNonBmpHashKeyVector() throws Exception { + localDynamoDb.start(); + client = localDynamoDb.createLimitedWrappedClient(); + createCiphertextTables(client); + + ScenarioManifest scenarioManifest = getManifestFromFile( + SCENARIO_MANIFEST_PATH, new TypeReference() {}); + loadKeyData(scenarioManifest.keyDataPath); + + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( + new DirectKmsMaterialsProvider(kmsClient, keyDataMap.get("awsKmsUsWest2").keyId)); + EncryptionContext ctx = EncryptionContext.builder() + .tableName("HashKeyOnly") + .hashKeyName("hashKey") + .build(); + + String nonBmpKey = "test\uD83D\uDE00\u03A8key"; + Map item = new HashMap<>(); + item.put("hashKey", AttributeValue.builder().s(nonBmpKey).build()); + + Map> actions = new HashMap<>(); + actions.put("hashKey", signOnly); + + Map encrypted = encryptor.encryptRecord(item, actions, ctx); + + printJSON(encrypted); + + client.close(); + localDynamoDb.stop(); + } + + @Test + public void generateNonAsciiTableNameVector() throws Exception { + localDynamoDb.start(); + client = localDynamoDb.createLimitedWrappedClient(); + createCiphertextTables(client); + + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext ctx = EncryptionContext.builder() + .tableName("テーブル\uD83D\uDE00") + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); + + Map> actions = new HashMap<>(); + for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { + switch (attr) { + case "hashKey": case "rangeKey": case "version": + actions.put(attr, signOnly); break; + default: + actions.put(attr, encryptAndSign); break; + } + } + + Map encrypted = encryptor.encryptRecord(ENCRYPTED_TEST_VALUE, actions, ctx); + + printJSON(encrypted); + + client.close(); + localDynamoDb.stop(); + } + + public void printJSON(Map encrypted) { + StringBuilder sb = new StringBuilder(); + sb.append("{\n \"TableName\": [\n {\n"); + for (Map.Entry e : encrypted.entrySet()) { + AttributeValue v = e.getValue(); + sb.append(" \"").append(e.getKey()).append("\": {\n"); + if (v.n() != null) { + sb.append(" \"N\": \"").append(v.n()).append("\"\n"); + } else if (v.b() != null) { + sb.append(" \"B\": \"").append(Base64.encodeAsString(v.b().asByteArray())).append("\"\n"); + } else if (v.s() != null) { + sb.append(" \"S\": \"").append(v.s()).append("\"\n"); + } + sb.append(" },\n"); + } + sb.append(" }\n ]\n}"); + System.out.println(sb); + } + + // This test configures EC with various combination. This is different from other tests as other test run in same hardcoded EC. + @Test + public void decryptWithECConfigTest() throws IOException, GeneralSecurityException { + final String nullTableNameInECCipherFile = "file://ciphertext/java/static-aes-hmac-null-table-1.json"; + final String nonBMPinECCipherFile = "file://ciphertext/java/kms-nonbmp-hashkey-1.json"; + final String nonAsciiTableInECCipherFile = "file://ciphertext/java/static-aes-hmac-nonascii-table-1.json"; + + localDynamoDb.start(); + client = localDynamoDb.createLimitedWrappedClient(); + createCiphertextTables(client); + decryptNullTableNameInEC(nullTableNameInECCipherFile); + decryptNonBmpHashKeyVector(nonBMPinECCipherFile); + decryptNonAsciiTableNameVector(nonAsciiTableInECCipherFile); + + client.close(); + localDynamoDb.stop(); + } + + public void decryptNullTableNameInEC(String nullTableNameInECCipherFile) throws IOException, GeneralSecurityException { + putDataFromFile(client, nullTableNameInECCipherFile); + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext ctx = EncryptionContext.builder() + .tableName(null) + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); + + Map> actions = new HashMap<>(); + for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { + switch (attr) { + case "hashKey": case "rangeKey": case "version": + actions.put(attr, signOnly); break; + default: + actions.put(attr, encryptAndSign); break; + } + } + + HashMap key = new HashMap<>(); + key.put("hashKey", ENCRYPTED_TEST_VALUE.get("hashKey")); + key.put("rangeKey", ENCRYPTED_TEST_VALUE.get("rangeKey")); + Map response = getItems(key, tableName); + Map decrypted = + encryptor.decryptRecord(response, actions, ctx); + assertTrue(new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted)); + } + + public void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) throws IOException, GeneralSecurityException { + ScenarioManifest scenarioManifest = getManifestFromFile( + SCENARIO_MANIFEST_PATH, new TypeReference() {}); + loadKeyData(scenarioManifest.keyDataPath); + + putDataFromFile(client, nonBMPinECCipherFile); + + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( + new DirectKmsMaterialsProvider(kmsClient, keyDataMap.get("awsKmsUsWest2").keyId)); + EncryptionContext ctx = EncryptionContext.builder() + .tableName("HashKeyOnly") + .hashKeyName("hashKey") + .build(); + + Map> actions = new HashMap<>(); + actions.put("hashKey", signOnly); + + String nonBmpKey = "test\uD83D\uDE00Ψkey"; + HashMap key = new HashMap<>(); + key.put("hashKey", AttributeValue.builder().s(nonBmpKey).build()); + + Map response = getItems(key, "HashKeyOnly"); + Map decrypted = encryptor.decryptRecord(response, actions, ctx); + assertEquals(nonBmpKey, decrypted.get("hashKey").s()); + } + + public void decryptNonAsciiTableNameVector(String nonAsciiTableInECCipherFile) throws IOException, GeneralSecurityException { + putDataFromFile(client, nonAsciiTableInECCipherFile); + + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext ctx = EncryptionContext.builder() + .tableName("テーブル\uD83D\uDE00") + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); + + Map> actions = new HashMap<>(); + for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { + switch (attr) { + case "hashKey": case "rangeKey": case "version": + actions.put(attr, signOnly); break; + default: + actions.put(attr, encryptAndSign); break; + } + } + + HashMap key = new HashMap<>(); + key.put("hashKey", ENCRYPTED_TEST_VALUE.get("hashKey")); + key.put("rangeKey", ENCRYPTED_TEST_VALUE.get("rangeKey")); + Map response = getItems(key, tableName); + Map decrypted = encryptor.decryptRecord(response, actions, ctx); + assertTrue(new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted)); + } + @Test(dataProvider = "getDecryptTestVectors") public void decryptTestVector(Scenario scenario) throws IOException, GeneralSecurityException { From 40d075a7e4d772b1c80368fd5d010aefdb091316 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 12 Mar 2026 12:17:30 -0700 Subject: [PATCH 03/16] refactoring --- .../datamodeling/sdkv2/HolisticIT.java | 63 ++++++++----------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java index a3608c9ec8..7f700234bf 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java @@ -671,40 +671,32 @@ public void decryptWithECConfigTest() throws IOException, GeneralSecurityExcepti } public void decryptNullTableNameInEC(String nullTableNameInECCipherFile) throws IOException, GeneralSecurityException { - putDataFromFile(client, nullTableNameInECCipherFile); DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); EncryptionContext ctx = EncryptionContext.builder() - .tableName(null) - .hashKeyName("hashKey") - .rangeKeyName("rangeKey") - .build(); + .tableName(null) + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); Map> actions = new HashMap<>(); for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { - switch (attr) { - case "hashKey": case "rangeKey": case "version": - actions.put(attr, signOnly); break; - default: - actions.put(attr, encryptAndSign); break; - } + switch (attr) { + case "hashKey": case "rangeKey": case "version": + actions.put(attr, signOnly); break; + default: + actions.put(attr, encryptAndSign); break; + } } - HashMap key = new HashMap<>(); - key.put("hashKey", ENCRYPTED_TEST_VALUE.get("hashKey")); - key.put("rangeKey", ENCRYPTED_TEST_VALUE.get("rangeKey")); - Map response = getItems(key, tableName); - Map decrypted = - encryptor.decryptRecord(response, actions, ctx); - assertTrue(new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted)); + Map>> manifest = + getCiphertextManifestFromFile(nullTableNameInECCipherFile); + for (Map encryptedItem : manifest.get(tableName)) { + Map decrypted = encryptor.decryptRecord(encryptedItem, actions, ctx); + assertTrue(new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted)); + } } public void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) throws IOException, GeneralSecurityException { - ScenarioManifest scenarioManifest = getManifestFromFile( - SCENARIO_MANIFEST_PATH, new TypeReference() {}); - loadKeyData(scenarioManifest.keyDataPath); - - putDataFromFile(client, nonBMPinECCipherFile); - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( new DirectKmsMaterialsProvider(kmsClient, keyDataMap.get("awsKmsUsWest2").keyId)); EncryptionContext ctx = EncryptionContext.builder() @@ -716,17 +708,16 @@ public void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) throws IOExc actions.put("hashKey", signOnly); String nonBmpKey = "test\uD83D\uDE00Ψkey"; - HashMap key = new HashMap<>(); - key.put("hashKey", AttributeValue.builder().s(nonBmpKey).build()); - Map response = getItems(key, "HashKeyOnly"); - Map decrypted = encryptor.decryptRecord(response, actions, ctx); - assertEquals(nonBmpKey, decrypted.get("hashKey").s()); + Map>> manifest = + getCiphertextManifestFromFile(nonBMPinECCipherFile); + for (Map encryptedItem : manifest.get(tableName)) { + Map decrypted = encryptor.decryptRecord(encryptedItem, actions, ctx); + assertEquals(nonBmpKey, decrypted.get("hashKey").s()); + } } public void decryptNonAsciiTableNameVector(String nonAsciiTableInECCipherFile) throws IOException, GeneralSecurityException { - putDataFromFile(client, nonAsciiTableInECCipherFile); - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); EncryptionContext ctx = EncryptionContext.builder() .tableName("テーブル\uD83D\uDE00") @@ -744,12 +735,12 @@ public void decryptNonAsciiTableNameVector(String nonAsciiTableInECCipherFile) t } } - HashMap key = new HashMap<>(); - key.put("hashKey", ENCRYPTED_TEST_VALUE.get("hashKey")); - key.put("rangeKey", ENCRYPTED_TEST_VALUE.get("rangeKey")); - Map response = getItems(key, tableName); - Map decrypted = encryptor.decryptRecord(response, actions, ctx); + Map>> manifest = + getCiphertextManifestFromFile(nonAsciiTableInECCipherFile); + for (Map encryptedItem : manifest.get(tableName)) { + Map decrypted = encryptor.decryptRecord(encryptedItem, actions, ctx); assertTrue(new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted)); + } } @Test(dataProvider = "getDecryptTestVectors") From e8e816ac3826da3cb8a0d940a27e554677b06f14 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 12 Mar 2026 14:30:28 -0700 Subject: [PATCH 04/16] m --- .../ciphertext/java/kms-nonbmp-hashkey-1.json | 15 +++ .../static-aes-hmac-nonascii-table-1.json | 36 +++++++ .../java/static-aes-hmac-null-table-1.json | 36 +++++++ .../datamodeling/TransformerHolisticIT.java | 100 ++++++++++++++++++ .../datamodeling/sdkv2/HolisticIT.java | 10 +- 5 files changed, 191 insertions(+), 6 deletions(-) create mode 100644 DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/kms-nonbmp-hashkey-1.json create mode 100644 DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-nonascii-table-1.json create mode 100644 DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-null-table-1.json diff --git a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/kms-nonbmp-hashkey-1.json b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/kms-nonbmp-hashkey-1.json new file mode 100644 index 0000000000..ad124268e8 --- /dev/null +++ b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/kms-nonbmp-hashkey-1.json @@ -0,0 +1,15 @@ +{ + "TableName": [ + { + "hashKey": { + "S": "test😀Ψkey" + }, + "*amzn-ddb-map-desc*": { + "B": "AAAAAAAAABBhbXpuLWRkYi1lbnYta2V5AAAA4EFRRUJBSGhBODR3blhqRUpkQmJCQnlsUlVGY1paSzJqN3h3aDZVeUxvTDI4blErMEZBQUFBSDR3ZkFZSktvWklodmNOQVFjR29HOHdiUUlCQURCb0Jna3Foa2lHOXcwQkJ3RXdIZ1lKWUlaSUFXVURCQUV1TUJFRUREWlBYZGxDVHY2VlBCVUNFZ0lCRUlBN045Q1RjRHowSzd1RVNUUGxxU3MxdjRZQTVEU2tJQmVWc0lpN2FQTllVeW9xMm4xazZJUUlINnZGc3pmeFZSeFdLdUhxejZ0MkNtV1BlUFU9AAAAD2F3cy1rbXMtZWMtYXR0cgAAAAYqa2V5cyoAAAAQYW16bi1kZGItZW52LWFsZwAAAAdBRVMvMjU2AAAAEGFtem4tZGRiLXNpZy1hbGcAAAAOSG1hY1NIQTI1Ni8yNTYAAAARYW16bi1kZGItd3JhcC1hbGcAAAADa21zAAAAFWFtem4tZGRiLW1hcC1zeW0tbW9kZQAAABEvQ0JDL1BLQ1M1UGFkZGluZw==" + }, + "*amzn-ddb-map-sig*": { + "B": "+01tpVk8ZvuIFh+ZA02PkhFhEBs2vYePEgcM/qZ6JFw=" + } + } + ] +} \ No newline at end of file diff --git a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-nonascii-table-1.json b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-nonascii-table-1.json new file mode 100644 index 0000000000..126ce9588c --- /dev/null +++ b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-nonascii-table-1.json @@ -0,0 +1,36 @@ +{ + "TableName": [ + { + "rangeKey": { + "N": "7" + }, + "hashKey": { + "N": "5" + }, + "stringValue": { + "B": "leseMgRescbtfi/CZCmfW0Lk1jkv6Md5cqAtBTEP1AQyTB25+xVF7UjWR1DbeA8Y" + }, + "*amzn-ddb-map-desc*": { + "B": "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" + }, + "intSet": { + "B": "rf/00OwnLb/FlqMWDjvcdiX1AqzRQfLOuSSaTDZX7nSQrkDyqyxHxKYPWGnZOPOI3P2fOjVvYV0BSlmCIvP5kQ==" + }, + "byteArrayValue": { + "B": "DwzxA9QJrucdFE8nPIEaiAdggInKUH4CvumuBNZxcQc=" + }, + "intValue": { + "B": "b6tg6Vm7pzdcmlT0pc/4q/cecHZaiENJG/Hv+IU+6Lg=" + }, + "stringSet": { + "B": "HHIUXDDb2gMeGMfUs9cW0CtvPohceTRyOQ1GI/voY6vImFe1AJKNCy5Shx/PmMYH+rEzjryVsd8EVmcCco0PGA==" + }, + "version": { + "N": "0" + }, + "*amzn-ddb-map-sig*": { + "B": "EQXY4c3O2NSyRpPPuR9RzZ+CnLxn7jgb12RRmivNYZA=" + } + } + ] +} \ No newline at end of file diff --git a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-null-table-1.json b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-null-table-1.json new file mode 100644 index 0000000000..b233607f48 --- /dev/null +++ b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-null-table-1.json @@ -0,0 +1,36 @@ +{ + "TableName": [ + { + "rangeKey": { + "N": "7" + }, + "hashKey": { + "N": "5" + }, + "stringValue": { + "B": "6Z0SJgkzw3Ij0RNpHzrdH5o9+3tGJVVr3G66OL4+q7nfh/7AEg3wHnRuBiO2z3F/" + }, + "*amzn-ddb-map-desc*": { + "B": "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" + }, + "intSet": { + "B": "E2PmJ8DFDYXCYlAssQzJCFPkeoZqyDDpXI0qJe5iXIIkGE1Ltn+J++OzKDZ+Gvkvno1eNERWplptL22HH2+kjQ==" + }, + "byteArrayValue": { + "B": "263KRNe2DxnFKltNMXgxr95crOtbOziyqaI2rVdiUco=" + }, + "intValue": { + "B": "5rYFQHJpwVusKp4zIcJkNgQpzrz3Gwk+sb3aQsmJWRs=" + }, + "stringSet": { + "B": "Yii7PxCMKEefXMIEXeLl20YMm7WhKxxNlCJzv18QCLhmrVEL15xvTzAkcPMXVud7YIJFx1XzcVTjK0wwn5htSw==" + }, + "version": { + "N": "0" + }, + "*amzn-ddb-map-sig*": { + "B": "I/fHzON+4U01BsJA8hU6ebKn+TftiuaVAGDsn/ykAO8=" + } + } + ] + } \ No newline at end of file diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java index c37fdf9643..e90bcf582c 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 package com.amazonaws.services.dynamodbv2.datamodeling; +import static com.amazonaws.services.dynamodbv2.datamodeling.LegacyTestVectors.baseClassToV1AttrMap; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertNull; @@ -11,6 +12,8 @@ import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.SaveBehavior; import com.amazonaws.services.dynamodbv2.datamodeling.encryption.DynamoDBEncryptor; +import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext; +import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags; import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.AsymmetricStaticProvider; import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.CachingMostRecentProvider; import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.DirectKmsMaterialProvider; @@ -33,6 +36,7 @@ import com.amazonaws.services.dynamodbv2.testing.types.Mixed; import com.amazonaws.services.dynamodbv2.testing.types.SignOnly; import com.amazonaws.services.dynamodbv2.testing.types.Untouched; +import com.amazonaws.services.dynamodbv2.testing.DdbRecordMatcher; import com.amazonaws.services.kms.AWSKMS; import com.amazonaws.services.kms.AWSKMSClientBuilder; import com.amazonaws.util.Base64; @@ -326,6 +330,102 @@ public void setUp() { createCiphertextTables(client); } + // This test configures EC with various combination. This is different from other tests as other test run in same hardcoded EC. + @Test + public void decryptWithECConfigTest() throws IOException, GeneralSecurityException { + final String nullTableNameInECCipherFile = "file://ciphertext/java/static-aes-hmac-null-table-1.json"; + final String nonBMPinECCipherFile = "file://ciphertext/java/kms-nonbmp-hashkey-1.json"; + final String nonAsciiTableInECCipherFile = "file://ciphertext/java/static-aes-hmac-nonascii-table-1.json"; + + decryptNullTableNameInEC(nullTableNameInECCipherFile); + decryptNonBmpHashKeyVector(nonBMPinECCipherFile); + decryptNonAsciiTableNameVector(nonAsciiTableInECCipherFile); + } + + private void decryptNullTableNameInEC(String nullTableNameInECCipherFile) throws IOException, GeneralSecurityException { + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext ctx = + new EncryptionContext.Builder() + .withTableName(null) + .withHashKeyName("hashKey") + .withRangeKeyName("rangeKey") + .build(); + + Map expectedAttrMap = baseClassToV1AttrMap(ENCRYPTED_TEST_VALUE); + Map> actions = new HashMap<>(); + for (String attr : expectedAttrMap.keySet()) { + switch (attr) { + case "hashKey": case "rangeKey": case "version": + actions.put(attr, EnumSet.of(EncryptionFlags.SIGN)); break; + default: + actions.put(attr, EnumSet.of(EncryptionFlags.ENCRYPT, + EncryptionFlags.SIGN)); break; + } + } + + Map>> manifest = + getCiphertextManifestFromFile(nullTableNameInECCipherFile); + + for (Map encryptedItem : manifest.get(BASE_CLASS_TABLE_NAME)) { + Map decrypted = encryptor.decryptRecord(encryptedItem, actions, ctx); + assertTrue(new DdbRecordMatcher(expectedAttrMap, false).matches(decrypted)); + } + } + + private void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) throws IOException, GeneralSecurityException { + ScenarioManifest scenarioManifest = getManifestFromFile( + SCENARIO_MANIFEST_PATH, new TypeReference() {}); + loadKeyData(scenarioManifest.keyDataPath); + + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( + new DirectKmsMaterialProvider(kmsClient, keyDataMap.get("awsKmsUsWest2").keyId)); + EncryptionContext ctx = + new EncryptionContext.Builder() + .withTableName("HashKeyOnly") + .withHashKeyName("hashKey") + .build(); + + Map> actions = new HashMap<>(); + actions.put("hashKey", EnumSet.of(EncryptionFlags.SIGN)); + + String nonBmpKey = "test\uD83D\uDE00Ψkey"; + Map>> manifest = + getCiphertextManifestFromFile(nonBMPinECCipherFile); + for (Map encryptedItem : manifest.get(BASE_CLASS_TABLE_NAME)) { + Map decrypted = encryptor.decryptRecord(encryptedItem, actions, ctx); + assertEquals(nonBmpKey, decrypted.get("hashKey").getS()); + } + } + + private void decryptNonAsciiTableNameVector(String nonAsciiTableInECCipherFile) throws IOException, GeneralSecurityException { + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext ctx = + new com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext.Builder() + .withTableName("テーブル\uD83D\uDE00") + .withHashKeyName("hashKey") + .withRangeKeyName("rangeKey") + .build(); + + Map expectedAttrMap = baseClassToV1AttrMap(ENCRYPTED_TEST_VALUE); + Map> actions = new HashMap<>(); + for (String attr : expectedAttrMap.keySet()) { + switch (attr) { + case "hashKey": case "rangeKey": case "version": + actions.put(attr, EnumSet.of(com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN)); break; + default: + actions.put(attr, EnumSet.of(com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.ENCRYPT, + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN)); break; + } + } + + Map>> manifest = + getCiphertextManifestFromFile(nonAsciiTableInECCipherFile); + for (Map encryptedItem : manifest.get(BASE_CLASS_TABLE_NAME)) { + Map decrypted = encryptor.decryptRecord(encryptedItem, actions, ctx); + assertTrue(new DdbRecordMatcher(expectedAttrMap, false).matches(decrypted)); + } + } + @Test(dataProvider = "getDecryptTestVectors") public void decryptTestVector(Scenario scenario) throws IOException { client = DynamoDBEmbedded.create().amazonDynamoDB(); diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java index 7f700234bf..8567154b9d 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java @@ -659,15 +659,9 @@ public void decryptWithECConfigTest() throws IOException, GeneralSecurityExcepti final String nonBMPinECCipherFile = "file://ciphertext/java/kms-nonbmp-hashkey-1.json"; final String nonAsciiTableInECCipherFile = "file://ciphertext/java/static-aes-hmac-nonascii-table-1.json"; - localDynamoDb.start(); - client = localDynamoDb.createLimitedWrappedClient(); - createCiphertextTables(client); decryptNullTableNameInEC(nullTableNameInECCipherFile); decryptNonBmpHashKeyVector(nonBMPinECCipherFile); decryptNonAsciiTableNameVector(nonAsciiTableInECCipherFile); - - client.close(); - localDynamoDb.stop(); } public void decryptNullTableNameInEC(String nullTableNameInECCipherFile) throws IOException, GeneralSecurityException { @@ -697,6 +691,10 @@ public void decryptNullTableNameInEC(String nullTableNameInECCipherFile) throws } public void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) throws IOException, GeneralSecurityException { + ScenarioManifest scenarioManifest = getManifestFromFile( + SCENARIO_MANIFEST_PATH, new TypeReference() {}); + loadKeyData(scenarioManifest.keyDataPath); + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( new DirectKmsMaterialsProvider(kmsClient, keyDataMap.get("awsKmsUsWest2").keyId)); EncryptionContext ctx = EncryptionContext.builder() From 872c66992cd0367150ebc7bfa735bde0d3e1167f Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 12 Mar 2026 14:38:49 -0700 Subject: [PATCH 05/16] formatting --- .../ciphertext/java/kms-nonbmp-hashkey-1.json | 28 +- .../static-aes-hmac-nonascii-table-1.json | 46 +-- .../java/static-aes-hmac-null-table-1.json | 46 +-- .../datamodeling/LegacyTestVectors.java | 41 +++ .../datamodeling/TransformerHolisticIT.java | 165 ++++++--- .../datamodeling/sdkv2/HolisticIT.java | 341 +++++++++++------- 6 files changed, 424 insertions(+), 243 deletions(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/kms-nonbmp-hashkey-1.json b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/kms-nonbmp-hashkey-1.json index ad124268e8..773f9bbe92 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/kms-nonbmp-hashkey-1.json +++ b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/kms-nonbmp-hashkey-1.json @@ -1,15 +1,15 @@ { - "TableName": [ - { - "hashKey": { - "S": "test😀Ψkey" - }, - "*amzn-ddb-map-desc*": { - "B": "AAAAAAAAABBhbXpuLWRkYi1lbnYta2V5AAAA4EFRRUJBSGhBODR3blhqRUpkQmJCQnlsUlVGY1paSzJqN3h3aDZVeUxvTDI4blErMEZBQUFBSDR3ZkFZSktvWklodmNOQVFjR29HOHdiUUlCQURCb0Jna3Foa2lHOXcwQkJ3RXdIZ1lKWUlaSUFXVURCQUV1TUJFRUREWlBYZGxDVHY2VlBCVUNFZ0lCRUlBN045Q1RjRHowSzd1RVNUUGxxU3MxdjRZQTVEU2tJQmVWc0lpN2FQTllVeW9xMm4xazZJUUlINnZGc3pmeFZSeFdLdUhxejZ0MkNtV1BlUFU9AAAAD2F3cy1rbXMtZWMtYXR0cgAAAAYqa2V5cyoAAAAQYW16bi1kZGItZW52LWFsZwAAAAdBRVMvMjU2AAAAEGFtem4tZGRiLXNpZy1hbGcAAAAOSG1hY1NIQTI1Ni8yNTYAAAARYW16bi1kZGItd3JhcC1hbGcAAAADa21zAAAAFWFtem4tZGRiLW1hcC1zeW0tbW9kZQAAABEvQ0JDL1BLQ1M1UGFkZGluZw==" - }, - "*amzn-ddb-map-sig*": { - "B": "+01tpVk8ZvuIFh+ZA02PkhFhEBs2vYePEgcM/qZ6JFw=" - } - } - ] -} \ No newline at end of file + "TableName": [ + { + "hashKey": { + "S": "test😀Ψkey" + }, + "*amzn-ddb-map-desc*": { + "B": "AAAAAAAAABBhbXpuLWRkYi1lbnYta2V5AAAA4EFRRUJBSGhBODR3blhqRUpkQmJCQnlsUlVGY1paSzJqN3h3aDZVeUxvTDI4blErMEZBQUFBSDR3ZkFZSktvWklodmNOQVFjR29HOHdiUUlCQURCb0Jna3Foa2lHOXcwQkJ3RXdIZ1lKWUlaSUFXVURCQUV1TUJFRUREWlBYZGxDVHY2VlBCVUNFZ0lCRUlBN045Q1RjRHowSzd1RVNUUGxxU3MxdjRZQTVEU2tJQmVWc0lpN2FQTllVeW9xMm4xazZJUUlINnZGc3pmeFZSeFdLdUhxejZ0MkNtV1BlUFU9AAAAD2F3cy1rbXMtZWMtYXR0cgAAAAYqa2V5cyoAAAAQYW16bi1kZGItZW52LWFsZwAAAAdBRVMvMjU2AAAAEGFtem4tZGRiLXNpZy1hbGcAAAAOSG1hY1NIQTI1Ni8yNTYAAAARYW16bi1kZGItd3JhcC1hbGcAAAADa21zAAAAFWFtem4tZGRiLW1hcC1zeW0tbW9kZQAAABEvQ0JDL1BLQ1M1UGFkZGluZw==" + }, + "*amzn-ddb-map-sig*": { + "B": "+01tpVk8ZvuIFh+ZA02PkhFhEBs2vYePEgcM/qZ6JFw=" + } + } + ] +} diff --git a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-nonascii-table-1.json b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-nonascii-table-1.json index 126ce9588c..ce9c3d7026 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-nonascii-table-1.json +++ b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-nonascii-table-1.json @@ -1,36 +1,36 @@ { - "TableName": [ + "TableName": [ { - "rangeKey": { + "rangeKey": { "N": "7" - }, - "hashKey": { + }, + "hashKey": { "N": "5" - }, - "stringValue": { + }, + "stringValue": { "B": "leseMgRescbtfi/CZCmfW0Lk1jkv6Md5cqAtBTEP1AQyTB25+xVF7UjWR1DbeA8Y" - }, - "*amzn-ddb-map-desc*": { + }, + "*amzn-ddb-map-desc*": { "B": "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" - }, - "intSet": { + }, + "intSet": { "B": "rf/00OwnLb/FlqMWDjvcdiX1AqzRQfLOuSSaTDZX7nSQrkDyqyxHxKYPWGnZOPOI3P2fOjVvYV0BSlmCIvP5kQ==" - }, - "byteArrayValue": { + }, + "byteArrayValue": { "B": "DwzxA9QJrucdFE8nPIEaiAdggInKUH4CvumuBNZxcQc=" - }, - "intValue": { + }, + "intValue": { "B": "b6tg6Vm7pzdcmlT0pc/4q/cecHZaiENJG/Hv+IU+6Lg=" - }, - "stringSet": { + }, + "stringSet": { "B": "HHIUXDDb2gMeGMfUs9cW0CtvPohceTRyOQ1GI/voY6vImFe1AJKNCy5Shx/PmMYH+rEzjryVsd8EVmcCco0PGA==" - }, - "version": { + }, + "version": { "N": "0" - }, - "*amzn-ddb-map-sig*": { + }, + "*amzn-ddb-map-sig*": { "B": "EQXY4c3O2NSyRpPPuR9RzZ+CnLxn7jgb12RRmivNYZA=" - } + } } - ] -} \ No newline at end of file + ] +} diff --git a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-null-table-1.json b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-null-table-1.json index b233607f48..328f4b1c64 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-null-table-1.json +++ b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-null-table-1.json @@ -1,36 +1,36 @@ { - "TableName": [ + "TableName": [ { - "rangeKey": { + "rangeKey": { "N": "7" - }, - "hashKey": { + }, + "hashKey": { "N": "5" - }, - "stringValue": { + }, + "stringValue": { "B": "6Z0SJgkzw3Ij0RNpHzrdH5o9+3tGJVVr3G66OL4+q7nfh/7AEg3wHnRuBiO2z3F/" - }, - "*amzn-ddb-map-desc*": { + }, + "*amzn-ddb-map-desc*": { "B": "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" - }, - "intSet": { + }, + "intSet": { "B": "E2PmJ8DFDYXCYlAssQzJCFPkeoZqyDDpXI0qJe5iXIIkGE1Ltn+J++OzKDZ+Gvkvno1eNERWplptL22HH2+kjQ==" - }, - "byteArrayValue": { + }, + "byteArrayValue": { "B": "263KRNe2DxnFKltNMXgxr95crOtbOziyqaI2rVdiUco=" - }, - "intValue": { + }, + "intValue": { "B": "5rYFQHJpwVusKp4zIcJkNgQpzrz3Gwk+sb3aQsmJWRs=" - }, - "stringSet": { + }, + "stringSet": { "B": "Yii7PxCMKEefXMIEXeLl20YMm7WhKxxNlCJzv18QCLhmrVEL15xvTzAkcPMXVud7YIJFx1XzcVTjK0wwn5htSw==" - }, - "version": { + }, + "version": { "N": "0" - }, - "*amzn-ddb-map-sig*": { + }, + "*amzn-ddb-map-sig*": { "B": "I/fHzON+4U01BsJA8hU6ebKn+TftiuaVAGDsn/ykAO8=" - } + } } - ] - } \ No newline at end of file + ] +} diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/LegacyTestVectors.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/LegacyTestVectors.java index aebb82e414..7bab27e430 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/LegacyTestVectors.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/LegacyTestVectors.java @@ -397,6 +397,47 @@ public static BaseClass attributeMapToBaseClass( return value; } + public static Map baseClassToV1AttrMap( + BaseClass obj + ) { + Map map = new HashMap<>(); + map.put( + HASH_KEY, + new AttributeValue().withN(String.valueOf(obj.getHashKey())) + ); + map.put( + RANGE_KEY, + new AttributeValue().withN(String.valueOf(obj.getRangeKey())) + ); + map.put( + "version", + new AttributeValue().withN(String.valueOf(obj.getVersion())) + ); + map.put( + "intValue", + new AttributeValue().withN(String.valueOf(obj.getIntValue())) + ); + map.put("stringValue", new AttributeValue().withS(obj.getStringValue())); + map.put( + "byteArrayValue", + new AttributeValue() + .withB(java.nio.ByteBuffer.wrap(obj.getByteArrayValue())) + ); + map.put("stringSet", new AttributeValue().withSS(obj.getStringSet())); + map.put( + "intSet", + new AttributeValue() + .withNS( + obj + .getIntSet() + .stream() + .map(String::valueOf) + .collect(java.util.stream.Collectors.toList()) + ) + ); + return map; + } + public static Map< String, software.amazon.awssdk.services.dynamodb.model.AttributeValue diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java index e90bcf582c..f643a44c86 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java @@ -26,6 +26,7 @@ import com.amazonaws.services.dynamodbv2.model.*; import com.amazonaws.services.dynamodbv2.testing.AttributeValueDeserializer; import com.amazonaws.services.dynamodbv2.testing.AttributeValueSerializer; +import com.amazonaws.services.dynamodbv2.testing.DdbRecordMatcher; import com.amazonaws.services.dynamodbv2.testing.ScenarioManifest; import com.amazonaws.services.dynamodbv2.testing.ScenarioManifest.KeyData; import com.amazonaws.services.dynamodbv2.testing.ScenarioManifest.Keys; @@ -36,7 +37,6 @@ import com.amazonaws.services.dynamodbv2.testing.types.Mixed; import com.amazonaws.services.dynamodbv2.testing.types.SignOnly; import com.amazonaws.services.dynamodbv2.testing.types.Untouched; -import com.amazonaws.services.dynamodbv2.testing.DdbRecordMatcher; import com.amazonaws.services.kms.AWSKMS; import com.amazonaws.services.kms.AWSKMSClientBuilder; import com.amazonaws.util.Base64; @@ -332,97 +332,160 @@ public void setUp() { // This test configures EC with various combination. This is different from other tests as other test run in same hardcoded EC. @Test - public void decryptWithECConfigTest() throws IOException, GeneralSecurityException { - final String nullTableNameInECCipherFile = "file://ciphertext/java/static-aes-hmac-null-table-1.json"; - final String nonBMPinECCipherFile = "file://ciphertext/java/kms-nonbmp-hashkey-1.json"; - final String nonAsciiTableInECCipherFile = "file://ciphertext/java/static-aes-hmac-nonascii-table-1.json"; + public void decryptWithECConfigTest() + throws IOException, GeneralSecurityException { + final String nullTableNameInECCipherFile = + "file://ciphertext/java/static-aes-hmac-null-table-1.json"; + final String nonBMPinECCipherFile = + "file://ciphertext/java/kms-nonbmp-hashkey-1.json"; + final String nonAsciiTableInECCipherFile = + "file://ciphertext/java/static-aes-hmac-nonascii-table-1.json"; decryptNullTableNameInEC(nullTableNameInECCipherFile); decryptNonBmpHashKeyVector(nonBMPinECCipherFile); decryptNonAsciiTableNameVector(nonAsciiTableInECCipherFile); } - private void decryptNullTableNameInEC(String nullTableNameInECCipherFile) throws IOException, GeneralSecurityException { + private void decryptNullTableNameInEC(String nullTableNameInECCipherFile) + throws IOException, GeneralSecurityException { DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext ctx = - new EncryptionContext.Builder() - .withTableName(null) - .withHashKeyName("hashKey") - .withRangeKeyName("rangeKey") - .build(); - - Map expectedAttrMap = baseClassToV1AttrMap(ENCRYPTED_TEST_VALUE); + EncryptionContext ctx = new EncryptionContext.Builder() + .withTableName(null) + .withHashKeyName("hashKey") + .withRangeKeyName("rangeKey") + .build(); + + Map expectedAttrMap = baseClassToV1AttrMap( + ENCRYPTED_TEST_VALUE + ); Map> actions = new HashMap<>(); for (String attr : expectedAttrMap.keySet()) { switch (attr) { - case "hashKey": case "rangeKey": case "version": - actions.put(attr, EnumSet.of(EncryptionFlags.SIGN)); break; + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, EnumSet.of(EncryptionFlags.SIGN)); + break; default: - actions.put(attr, EnumSet.of(EncryptionFlags.ENCRYPT, - EncryptionFlags.SIGN)); break; + actions.put( + attr, + EnumSet.of(EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN) + ); + break; } } Map>> manifest = - getCiphertextManifestFromFile(nullTableNameInECCipherFile); - - for (Map encryptedItem : manifest.get(BASE_CLASS_TABLE_NAME)) { - Map decrypted = encryptor.decryptRecord(encryptedItem, actions, ctx); - assertTrue(new DdbRecordMatcher(expectedAttrMap, false).matches(decrypted)); + getCiphertextManifestFromFile(nullTableNameInECCipherFile); + + for (Map encryptedItem : manifest.get( + BASE_CLASS_TABLE_NAME + )) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertTrue( + new DdbRecordMatcher(expectedAttrMap, false).matches(decrypted) + ); } } - private void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) throws IOException, GeneralSecurityException { + private void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) + throws IOException, GeneralSecurityException { ScenarioManifest scenarioManifest = getManifestFromFile( - SCENARIO_MANIFEST_PATH, new TypeReference() {}); + SCENARIO_MANIFEST_PATH, + new TypeReference() {} + ); loadKeyData(scenarioManifest.keyDataPath); DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( - new DirectKmsMaterialProvider(kmsClient, keyDataMap.get("awsKmsUsWest2").keyId)); - EncryptionContext ctx = - new EncryptionContext.Builder() - .withTableName("HashKeyOnly") - .withHashKeyName("hashKey") - .build(); + new DirectKmsMaterialProvider( + kmsClient, + keyDataMap.get("awsKmsUsWest2").keyId + ) + ); + EncryptionContext ctx = new EncryptionContext.Builder() + .withTableName("HashKeyOnly") + .withHashKeyName("hashKey") + .build(); Map> actions = new HashMap<>(); actions.put("hashKey", EnumSet.of(EncryptionFlags.SIGN)); String nonBmpKey = "test\uD83D\uDE00Ψkey"; Map>> manifest = - getCiphertextManifestFromFile(nonBMPinECCipherFile); - for (Map encryptedItem : manifest.get(BASE_CLASS_TABLE_NAME)) { - Map decrypted = encryptor.decryptRecord(encryptedItem, actions, ctx); + getCiphertextManifestFromFile(nonBMPinECCipherFile); + for (Map encryptedItem : manifest.get( + BASE_CLASS_TABLE_NAME + )) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); assertEquals(nonBmpKey, decrypted.get("hashKey").getS()); } } - private void decryptNonAsciiTableNameVector(String nonAsciiTableInECCipherFile) throws IOException, GeneralSecurityException { + private void decryptNonAsciiTableNameVector( + String nonAsciiTableInECCipherFile + ) throws IOException, GeneralSecurityException { DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext ctx = - new com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext.Builder() - .withTableName("テーブル\uD83D\uDE00") - .withHashKeyName("hashKey") - .withRangeKeyName("rangeKey") - .build(); - - Map expectedAttrMap = baseClassToV1AttrMap(ENCRYPTED_TEST_VALUE); - Map> actions = new HashMap<>(); + new com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext.Builder() + .withTableName("テーブル\uD83D\uDE00") + .withHashKeyName("hashKey") + .withRangeKeyName("rangeKey") + .build(); + + Map expectedAttrMap = baseClassToV1AttrMap( + ENCRYPTED_TEST_VALUE + ); + Map< + String, + Set< + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags + > + > actions = new HashMap<>(); for (String attr : expectedAttrMap.keySet()) { switch (attr) { - case "hashKey": case "rangeKey": case "version": - actions.put(attr, EnumSet.of(com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN)); break; + case "hashKey": + case "rangeKey": + case "version": + actions.put( + attr, + EnumSet.of( + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN + ) + ); + break; default: - actions.put(attr, EnumSet.of(com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.ENCRYPT, - com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN)); break; + actions.put( + attr, + EnumSet.of( + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.ENCRYPT, + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN + ) + ); + break; } } Map>> manifest = - getCiphertextManifestFromFile(nonAsciiTableInECCipherFile); - for (Map encryptedItem : manifest.get(BASE_CLASS_TABLE_NAME)) { - Map decrypted = encryptor.decryptRecord(encryptedItem, actions, ctx); - assertTrue(new DdbRecordMatcher(expectedAttrMap, false).matches(decrypted)); + getCiphertextManifestFromFile(nonAsciiTableInECCipherFile); + for (Map encryptedItem : manifest.get( + BASE_CLASS_TABLE_NAME + )) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertTrue( + new DdbRecordMatcher(expectedAttrMap, false).matches(decrypted) + ); } } diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java index 8567154b9d..9d6e5dd901 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java @@ -16,10 +16,10 @@ import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.encryption.providers.WrappedMaterialsProvider; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.encryption.providers.store.MetaStore; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.encryption.providers.store.ProviderStore; +import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.AttributeValueDeserializer; +import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.DdbRecordMatcher; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.LocalDynamoDb; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.ScenarioManifest; -import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.DdbRecordMatcher; -import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.AttributeValueDeserializer; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.ScenarioManifest.KeyData; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.ScenarioManifest.Keys; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.ScenarioManifest.Scenario; @@ -545,24 +545,32 @@ public void generateNullTableNameVector() throws Exception { createCiphertextTables(client); DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext ctx = EncryptionContext.builder() - .tableName(null) - .hashKeyName("hashKey") - .rangeKeyName("rangeKey") - .build(); + EncryptionContext ctx = EncryptionContext + .builder() + .tableName(null) + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); Map> actions = new HashMap<>(); for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { - switch (attr) { - case "hashKey": case "rangeKey": case "version": - actions.put(attr, signOnly); break; - default: - actions.put(attr, encryptAndSign); break; - } + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, signOnly); + break; + default: + actions.put(attr, encryptAndSign); + break; + } } - Map encrypted = - encryptor.encryptRecord(ENCRYPTED_TEST_VALUE, actions, ctx); + Map encrypted = encryptor.encryptRecord( + ENCRYPTED_TEST_VALUE, + actions, + ctx + ); printJSON(encrypted); @@ -572,81 +580,104 @@ public void generateNullTableNameVector() throws Exception { @Test public void generateNonBmpHashKeyVector() throws Exception { - localDynamoDb.start(); - client = localDynamoDb.createLimitedWrappedClient(); - createCiphertextTables(client); - - ScenarioManifest scenarioManifest = getManifestFromFile( - SCENARIO_MANIFEST_PATH, new TypeReference() {}); - loadKeyData(scenarioManifest.keyDataPath); - - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( - new DirectKmsMaterialsProvider(kmsClient, keyDataMap.get("awsKmsUsWest2").keyId)); - EncryptionContext ctx = EncryptionContext.builder() - .tableName("HashKeyOnly") - .hashKeyName("hashKey") - .build(); - - String nonBmpKey = "test\uD83D\uDE00\u03A8key"; - Map item = new HashMap<>(); - item.put("hashKey", AttributeValue.builder().s(nonBmpKey).build()); - - Map> actions = new HashMap<>(); - actions.put("hashKey", signOnly); - - Map encrypted = encryptor.encryptRecord(item, actions, ctx); - - printJSON(encrypted); - - client.close(); - localDynamoDb.stop(); + localDynamoDb.start(); + client = localDynamoDb.createLimitedWrappedClient(); + createCiphertextTables(client); + + ScenarioManifest scenarioManifest = getManifestFromFile( + SCENARIO_MANIFEST_PATH, + new TypeReference() {} + ); + loadKeyData(scenarioManifest.keyDataPath); + + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( + new DirectKmsMaterialsProvider( + kmsClient, + keyDataMap.get("awsKmsUsWest2").keyId + ) + ); + EncryptionContext ctx = EncryptionContext + .builder() + .tableName("HashKeyOnly") + .hashKeyName("hashKey") + .build(); + + String nonBmpKey = "test\uD83D\uDE00\u03A8key"; + Map item = new HashMap<>(); + item.put("hashKey", AttributeValue.builder().s(nonBmpKey).build()); + + Map> actions = new HashMap<>(); + actions.put("hashKey", signOnly); + + Map encrypted = encryptor.encryptRecord( + item, + actions, + ctx + ); + + printJSON(encrypted); + + client.close(); + localDynamoDb.stop(); } @Test public void generateNonAsciiTableNameVector() throws Exception { - localDynamoDb.start(); - client = localDynamoDb.createLimitedWrappedClient(); - createCiphertextTables(client); - - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext ctx = EncryptionContext.builder() - .tableName("テーブル\uD83D\uDE00") - .hashKeyName("hashKey") - .rangeKeyName("rangeKey") - .build(); - - Map> actions = new HashMap<>(); - for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { - switch (attr) { - case "hashKey": case "rangeKey": case "version": - actions.put(attr, signOnly); break; - default: - actions.put(attr, encryptAndSign); break; - } + localDynamoDb.start(); + client = localDynamoDb.createLimitedWrappedClient(); + createCiphertextTables(client); + + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext ctx = EncryptionContext + .builder() + .tableName("テーブル\uD83D\uDE00") + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); + + Map> actions = new HashMap<>(); + for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, signOnly); + break; + default: + actions.put(attr, encryptAndSign); + break; } + } - Map encrypted = encryptor.encryptRecord(ENCRYPTED_TEST_VALUE, actions, ctx); + Map encrypted = encryptor.encryptRecord( + ENCRYPTED_TEST_VALUE, + actions, + ctx + ); - printJSON(encrypted); + printJSON(encrypted); - client.close(); - localDynamoDb.stop(); + client.close(); + localDynamoDb.stop(); } public void printJSON(Map encrypted) { StringBuilder sb = new StringBuilder(); sb.append("{\n \"TableName\": [\n {\n"); for (Map.Entry e : encrypted.entrySet()) { - AttributeValue v = e.getValue(); - sb.append(" \"").append(e.getKey()).append("\": {\n"); - if (v.n() != null) { - sb.append(" \"N\": \"").append(v.n()).append("\"\n"); - } else if (v.b() != null) { - sb.append(" \"B\": \"").append(Base64.encodeAsString(v.b().asByteArray())).append("\"\n"); - } else if (v.s() != null) { - sb.append(" \"S\": \"").append(v.s()).append("\"\n"); - } - sb.append(" },\n"); + AttributeValue v = e.getValue(); + sb.append(" \"").append(e.getKey()).append("\": {\n"); + if (v.n() != null) { + sb.append(" \"N\": \"").append(v.n()).append("\"\n"); + } else if (v.b() != null) { + sb + .append(" \"B\": \"") + .append(Base64.encodeAsString(v.b().asByteArray())) + .append("\"\n"); + } else if (v.s() != null) { + sb.append(" \"S\": \"").append(v.s()).append("\"\n"); + } + sb.append(" },\n"); } sb.append(" }\n ]\n}"); System.out.println(sb); @@ -654,90 +685,131 @@ public void printJSON(Map encrypted) { // This test configures EC with various combination. This is different from other tests as other test run in same hardcoded EC. @Test - public void decryptWithECConfigTest() throws IOException, GeneralSecurityException { - final String nullTableNameInECCipherFile = "file://ciphertext/java/static-aes-hmac-null-table-1.json"; - final String nonBMPinECCipherFile = "file://ciphertext/java/kms-nonbmp-hashkey-1.json"; - final String nonAsciiTableInECCipherFile = "file://ciphertext/java/static-aes-hmac-nonascii-table-1.json"; + public void decryptWithECConfigTest() + throws IOException, GeneralSecurityException { + final String nullTableNameInECCipherFile = + "file://ciphertext/java/static-aes-hmac-null-table-1.json"; + final String nonBMPinECCipherFile = + "file://ciphertext/java/kms-nonbmp-hashkey-1.json"; + final String nonAsciiTableInECCipherFile = + "file://ciphertext/java/static-aes-hmac-nonascii-table-1.json"; decryptNullTableNameInEC(nullTableNameInECCipherFile); decryptNonBmpHashKeyVector(nonBMPinECCipherFile); decryptNonAsciiTableNameVector(nonAsciiTableInECCipherFile); } - public void decryptNullTableNameInEC(String nullTableNameInECCipherFile) throws IOException, GeneralSecurityException { + public void decryptNullTableNameInEC(String nullTableNameInECCipherFile) + throws IOException, GeneralSecurityException { DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext ctx = EncryptionContext.builder() - .tableName(null) - .hashKeyName("hashKey") - .rangeKeyName("rangeKey") - .build(); + EncryptionContext ctx = EncryptionContext + .builder() + .tableName(null) + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); Map> actions = new HashMap<>(); for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { switch (attr) { - case "hashKey": case "rangeKey": case "version": - actions.put(attr, signOnly); break; + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, signOnly); + break; default: - actions.put(attr, encryptAndSign); break; + actions.put(attr, encryptAndSign); + break; } } Map>> manifest = - getCiphertextManifestFromFile(nullTableNameInECCipherFile); + getCiphertextManifestFromFile(nullTableNameInECCipherFile); for (Map encryptedItem : manifest.get(tableName)) { - Map decrypted = encryptor.decryptRecord(encryptedItem, actions, ctx); - assertTrue(new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted)); + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertTrue( + new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted) + ); } } - public void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) throws IOException, GeneralSecurityException { - ScenarioManifest scenarioManifest = getManifestFromFile( - SCENARIO_MANIFEST_PATH, new TypeReference() {}); - loadKeyData(scenarioManifest.keyDataPath); + public void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) + throws IOException, GeneralSecurityException { + ScenarioManifest scenarioManifest = getManifestFromFile( + SCENARIO_MANIFEST_PATH, + new TypeReference() {} + ); + loadKeyData(scenarioManifest.keyDataPath); - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( - new DirectKmsMaterialsProvider(kmsClient, keyDataMap.get("awsKmsUsWest2").keyId)); - EncryptionContext ctx = EncryptionContext.builder() - .tableName("HashKeyOnly") - .hashKeyName("hashKey") - .build(); + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( + new DirectKmsMaterialsProvider( + kmsClient, + keyDataMap.get("awsKmsUsWest2").keyId + ) + ); + EncryptionContext ctx = EncryptionContext + .builder() + .tableName("HashKeyOnly") + .hashKeyName("hashKey") + .build(); - Map> actions = new HashMap<>(); - actions.put("hashKey", signOnly); + Map> actions = new HashMap<>(); + actions.put("hashKey", signOnly); - String nonBmpKey = "test\uD83D\uDE00Ψkey"; + String nonBmpKey = "test\uD83D\uDE00Ψkey"; - Map>> manifest = - getCiphertextManifestFromFile(nonBMPinECCipherFile); - for (Map encryptedItem : manifest.get(tableName)) { - Map decrypted = encryptor.decryptRecord(encryptedItem, actions, ctx); - assertEquals(nonBmpKey, decrypted.get("hashKey").s()); - } + Map>> manifest = + getCiphertextManifestFromFile(nonBMPinECCipherFile); + for (Map encryptedItem : manifest.get(tableName)) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertEquals(nonBmpKey, decrypted.get("hashKey").s()); + } } - public void decryptNonAsciiTableNameVector(String nonAsciiTableInECCipherFile) throws IOException, GeneralSecurityException { - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext ctx = EncryptionContext.builder() - .tableName("テーブル\uD83D\uDE00") - .hashKeyName("hashKey") - .rangeKeyName("rangeKey") - .build(); - - Map> actions = new HashMap<>(); - for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { - switch (attr) { - case "hashKey": case "rangeKey": case "version": - actions.put(attr, signOnly); break; - default: - actions.put(attr, encryptAndSign); break; - } + public void decryptNonAsciiTableNameVector( + String nonAsciiTableInECCipherFile + ) throws IOException, GeneralSecurityException { + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext ctx = EncryptionContext + .builder() + .tableName("テーブル\uD83D\uDE00") + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); + + Map> actions = new HashMap<>(); + for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, signOnly); + break; + default: + actions.put(attr, encryptAndSign); + break; } + } Map>> manifest = - getCiphertextManifestFromFile(nonAsciiTableInECCipherFile); + getCiphertextManifestFromFile(nonAsciiTableInECCipherFile); for (Map encryptedItem : manifest.get(tableName)) { - Map decrypted = encryptor.decryptRecord(encryptedItem, actions, ctx); - assertTrue(new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted)); + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertTrue( + new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted) + ); } } @@ -1329,7 +1401,7 @@ private void assertVersionCompatibility( assertTrue( new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decryptedRecord) ); - + // Atleast decrypt one item with only hash key. EncryptionContext hashOnlyContext = EncryptionContext .builder() @@ -1339,7 +1411,12 @@ private void assertVersionCompatibility( Map> hashOnlyActions = new HashMap<>(); hashOnlyActions.put("hashKey", signOnly); - Map decryptedHashOnlyRecord = encryptor.decryptRecord(getItems(hashKey1, "HashKeyOnly"), hashOnlyActions, hashOnlyContext); + Map decryptedHashOnlyRecord = + encryptor.decryptRecord( + getItems(hashKey1, "HashKeyOnly"), + hashOnlyActions, + hashOnlyContext + ); assertEquals("Foo", decryptedHashOnlyRecord.get("hashKey").s()); assertEquals("Bar", getItems(hashKey2, "HashKeyOnly").get("hashKey").s()); assertEquals("Baz", getItems(hashKey3, "HashKeyOnly").get("hashKey").s()); From bb63d317574f0c98c55ffdf15ca3c2464dd4348d Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 12 Mar 2026 14:41:12 -0700 Subject: [PATCH 06/16] remove temp code --- .../datamodeling/sdkv2/HolisticIT.java | 145 ------------------ 1 file changed, 145 deletions(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java index 9d6e5dd901..dba374859d 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java @@ -538,151 +538,6 @@ public static Object[][] getDecryptTestVectors() throws IOException { .toArray(Object[][]::new); } - @Test - public void generateNullTableNameVector() throws Exception { - localDynamoDb.start(); - client = localDynamoDb.createLimitedWrappedClient(); - createCiphertextTables(client); - - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext ctx = EncryptionContext - .builder() - .tableName(null) - .hashKeyName("hashKey") - .rangeKeyName("rangeKey") - .build(); - - Map> actions = new HashMap<>(); - for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { - switch (attr) { - case "hashKey": - case "rangeKey": - case "version": - actions.put(attr, signOnly); - break; - default: - actions.put(attr, encryptAndSign); - break; - } - } - - Map encrypted = encryptor.encryptRecord( - ENCRYPTED_TEST_VALUE, - actions, - ctx - ); - - printJSON(encrypted); - - client.close(); - localDynamoDb.stop(); - } - - @Test - public void generateNonBmpHashKeyVector() throws Exception { - localDynamoDb.start(); - client = localDynamoDb.createLimitedWrappedClient(); - createCiphertextTables(client); - - ScenarioManifest scenarioManifest = getManifestFromFile( - SCENARIO_MANIFEST_PATH, - new TypeReference() {} - ); - loadKeyData(scenarioManifest.keyDataPath); - - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( - new DirectKmsMaterialsProvider( - kmsClient, - keyDataMap.get("awsKmsUsWest2").keyId - ) - ); - EncryptionContext ctx = EncryptionContext - .builder() - .tableName("HashKeyOnly") - .hashKeyName("hashKey") - .build(); - - String nonBmpKey = "test\uD83D\uDE00\u03A8key"; - Map item = new HashMap<>(); - item.put("hashKey", AttributeValue.builder().s(nonBmpKey).build()); - - Map> actions = new HashMap<>(); - actions.put("hashKey", signOnly); - - Map encrypted = encryptor.encryptRecord( - item, - actions, - ctx - ); - - printJSON(encrypted); - - client.close(); - localDynamoDb.stop(); - } - - @Test - public void generateNonAsciiTableNameVector() throws Exception { - localDynamoDb.start(); - client = localDynamoDb.createLimitedWrappedClient(); - createCiphertextTables(client); - - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext ctx = EncryptionContext - .builder() - .tableName("テーブル\uD83D\uDE00") - .hashKeyName("hashKey") - .rangeKeyName("rangeKey") - .build(); - - Map> actions = new HashMap<>(); - for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { - switch (attr) { - case "hashKey": - case "rangeKey": - case "version": - actions.put(attr, signOnly); - break; - default: - actions.put(attr, encryptAndSign); - break; - } - } - - Map encrypted = encryptor.encryptRecord( - ENCRYPTED_TEST_VALUE, - actions, - ctx - ); - - printJSON(encrypted); - - client.close(); - localDynamoDb.stop(); - } - - public void printJSON(Map encrypted) { - StringBuilder sb = new StringBuilder(); - sb.append("{\n \"TableName\": [\n {\n"); - for (Map.Entry e : encrypted.entrySet()) { - AttributeValue v = e.getValue(); - sb.append(" \"").append(e.getKey()).append("\": {\n"); - if (v.n() != null) { - sb.append(" \"N\": \"").append(v.n()).append("\"\n"); - } else if (v.b() != null) { - sb - .append(" \"B\": \"") - .append(Base64.encodeAsString(v.b().asByteArray())) - .append("\"\n"); - } else if (v.s() != null) { - sb.append(" \"S\": \"").append(v.s()).append("\"\n"); - } - sb.append(" },\n"); - } - sb.append(" }\n ]\n}"); - System.out.println(sb); - } - // This test configures EC with various combination. This is different from other tests as other test run in same hardcoded EC. @Test public void decryptWithECConfigTest() From d95c763dff6a1e3d4f35192cb37ff2364c2c9314 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 12 Mar 2026 15:03:41 -0700 Subject: [PATCH 07/16] m --- .../datamodeling/sdkv2/HolisticIT.java | 29 ++-- .../datamodeling/sdkv2/HolisticITHelper.java | 137 ++++++++++++++++++ 2 files changed, 152 insertions(+), 14 deletions(-) create mode 100644 DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticITHelper.java diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java index dba374859d..aacb5d61e8 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java @@ -42,6 +42,7 @@ import javax.crypto.spec.SecretKeySpec; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import sdkv2.com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.HolisticITHelper; import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.*; @@ -95,26 +96,26 @@ public class HolisticIT { private static final PrivateKey rsaPriv; private static final PublicKey rsaPub; private static final KeyPair rsaPair; - private static final EncryptionMaterialsProvider symProv; + public static final EncryptionMaterialsProvider symProv; private static final EncryptionMaterialsProvider asymProv; private static final EncryptionMaterialsProvider symWrappedProv; private static final String HASH_KEY = "hashKey"; private static final String RANGE_KEY = "rangeKey"; private static final String RSA = "RSA"; - private static final String tableName = "TableName"; - final EnumSet signOnly = EnumSet.of(EncryptionFlags.SIGN); - final EnumSet encryptAndSign = EnumSet.of( + public static final String tableName = "TableName"; + public static final EnumSet signOnly = EnumSet.of(EncryptionFlags.SIGN); + public static final EnumSet encryptAndSign = EnumSet.of( EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN ); private final LocalDynamoDb localDynamoDb = new LocalDynamoDb(); private DynamoDbClient client; - private static KmsClient kmsClient = KmsClient.builder().build(); + public static KmsClient kmsClient = KmsClient.builder().build(); - private static Map keyDataMap = new HashMap<>(); + public static Map keyDataMap = new HashMap<>(); - private static final Map ENCRYPTED_TEST_VALUE = + public static final Map ENCRYPTED_TEST_VALUE = new HashMap<>(); private static final Map MIXED_TEST_VALUE = new HashMap<>(); @@ -134,7 +135,7 @@ public class HolisticIT { private static final String TEST_VECTOR_MANIFEST_DIR = "/vectors/encrypted_item/"; - private static final String SCENARIO_MANIFEST_PATH = + public static final String SCENARIO_MANIFEST_PATH = TEST_VECTOR_MANIFEST_DIR + "scenarios.json"; private static final String JAVA_DIR = "java"; @@ -549,9 +550,9 @@ public void decryptWithECConfigTest() final String nonAsciiTableInECCipherFile = "file://ciphertext/java/static-aes-hmac-nonascii-table-1.json"; - decryptNullTableNameInEC(nullTableNameInECCipherFile); - decryptNonBmpHashKeyVector(nonBMPinECCipherFile); - decryptNonAsciiTableNameVector(nonAsciiTableInECCipherFile); + HolisticITHelper.decryptNullTableNameInEC(nullTableNameInECCipherFile); + HolisticITHelper.decryptNonBmpHashKeyVector(nonBMPinECCipherFile); + HolisticITHelper.decryptNonAsciiTableNameVector(nonAsciiTableInECCipherFile); } public void decryptNullTableNameInEC(String nullTableNameInECCipherFile) @@ -1023,7 +1024,7 @@ private void putDataFromFile(DynamoDbClient localDynamoDb, String filename) } } - private Map< + public static Map< String, List> > getCiphertextManifestFromFile(String filename) throws IOException { @@ -1035,7 +1036,7 @@ > getCiphertextManifestFromFile(String filename) throws IOException { ); } - private static T getManifestFromFile( + public static T getManifestFromFile( String filename, TypeReference typeRef ) throws IOException { @@ -1050,7 +1051,7 @@ private static T getManifestFromFile( return (T) manifestMapper.readValue(manifestFile, typeRef); } - private static void loadKeyData(String filename) throws IOException { + public static void loadKeyData(String filename) throws IOException { keyDataMap = getManifestFromFile( TEST_VECTOR_MANIFEST_DIR + stripFilePath(filename), diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticITHelper.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticITHelper.java new file mode 100644 index 0000000000..a339cf6ee9 --- /dev/null +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticITHelper.java @@ -0,0 +1,137 @@ +package com.amazonaws.services.dynamodbv2.datamodeling.sdkv2; + +import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.encryption.DynamoDBEncryptor; +import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.encryption.EncryptionContext; +import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.encryption.EncryptionFlags; +import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.encryption.providers.DirectKmsMaterialsProvider; +import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.DdbRecordMatcher; +import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.ScenarioManifest; +import com.fasterxml.jackson.core.type.TypeReference; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.HolisticIT.*; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; + +public class HolisticITHelper { + public static void decryptNonAsciiTableNameVector( + String nonAsciiTableInECCipherFile + ) throws IOException, GeneralSecurityException { + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext ctx = EncryptionContext + .builder() + .tableName("テーブル\uD83D\uDE00") + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); + + Map> actions = new HashMap<>(); + for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, signOnly); + break; + default: + actions.put(attr, encryptAndSign); + break; + } + } + + Map>> manifest = + getCiphertextManifestFromFile(nonAsciiTableInECCipherFile); + for (Map encryptedItem : manifest.get(tableName)) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertTrue( + new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted) + ); + } + } + + public static void decryptNullTableNameInEC(String nullTableNameInECCipherFile) + throws IOException, GeneralSecurityException { + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext ctx = EncryptionContext + .builder() + .tableName(null) + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); + + Map> actions = new HashMap<>(); + for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, signOnly); + break; + default: + actions.put(attr, encryptAndSign); + break; + } + } + + Map>> manifest = + getCiphertextManifestFromFile(nullTableNameInECCipherFile); + for (Map encryptedItem : manifest.get(tableName)) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertTrue( + new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted) + ); + } + } + + public static void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) + throws IOException, GeneralSecurityException { + ScenarioManifest scenarioManifest = getManifestFromFile( + SCENARIO_MANIFEST_PATH, + new TypeReference() {} + ); + loadKeyData(scenarioManifest.keyDataPath); + + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( + new DirectKmsMaterialsProvider( + kmsClient, + keyDataMap.get("awsKmsUsWest2").keyId + ) + ); + EncryptionContext ctx = EncryptionContext + .builder() + .tableName("HashKeyOnly") + .hashKeyName("hashKey") + .build(); + + Map> actions = new HashMap<>(); + actions.put("hashKey", signOnly); + + String nonBmpKey = "test\uD83D\uDE00Ψkey"; + + Map>> manifest = + getCiphertextManifestFromFile(nonBMPinECCipherFile); + for (Map encryptedItem : manifest.get(tableName)) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertEquals(nonBmpKey, decrypted.get("hashKey").s()); + } + } +} From 2e40b0947d99aaafcf8a8a813d15eccdfb571b1b Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 12 Mar 2026 15:06:42 -0700 Subject: [PATCH 08/16] m --- .../services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java index aacb5d61e8..8629b1bbc8 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java @@ -42,7 +42,7 @@ import javax.crypto.spec.SecretKeySpec; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import sdkv2.com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.HolisticITHelper; +import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.HolisticITHelper; import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.*; From 78eedbe7dd76a5e3b497c7207962cd0787879f06 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 12 Mar 2026 15:06:54 -0700 Subject: [PATCH 09/16] m --- .../services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java | 1 - 1 file changed, 1 deletion(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java index 8629b1bbc8..cc0a836869 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java @@ -42,7 +42,6 @@ import javax.crypto.spec.SecretKeySpec; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.HolisticITHelper; import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.*; From cee5b6d10f19cd8d4b6fb44e9e1d5a2cfba00669 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 12 Mar 2026 15:18:08 -0700 Subject: [PATCH 10/16] m --- .../datamodeling/TransformerHolisticIT.java | 18 +- .../TransformerHolisticITHelper.java | 160 ++++++++++++++++++ 2 files changed, 169 insertions(+), 9 deletions(-) create mode 100644 DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticITHelper.java diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java index f643a44c86..b62d6295b4 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java @@ -111,18 +111,18 @@ public class TransformerHolisticIT { private static final PrivateKey rsaPriv; private static final PublicKey rsaPub; private static final KeyPair rsaPair; - private static final EncryptionMaterialsProvider symProv; + public static final EncryptionMaterialsProvider symProv; private static final EncryptionMaterialsProvider asymProv; private static final EncryptionMaterialsProvider symWrappedProv; protected static final String HASH_KEY = "hashKey"; protected static final String RANGE_KEY = "rangeKey"; - protected static final String BASE_CLASS_TABLE_NAME = "TableName"; + public static final String BASE_CLASS_TABLE_NAME = "TableName"; private static final String RSA = "RSA"; private AmazonDynamoDB client; - private static AWSKMS kmsClient = AWSKMSClientBuilder.standard().build(); + public static AWSKMS kmsClient = AWSKMSClientBuilder.standard().build(); - private static Map keyDataMap = new HashMap<>(); + public static Map keyDataMap = new HashMap<>(); // AttributeEncryptor *must* be used with SaveBehavior.CLOBBER to avoid the risk of data // corruption. @@ -131,7 +131,7 @@ public class TransformerHolisticIT { .builder() .withSaveBehavior(SaveBehavior.CLOBBER) .build(); - private static final BaseClass ENCRYPTED_TEST_VALUE = new BaseClass(); + public static final BaseClass ENCRYPTED_TEST_VALUE = new BaseClass(); private static final Mixed MIXED_TEST_VALUE = new Mixed(); private static final SignOnly SIGNED_TEST_VALUE = new SignOnly(); private static final Untouched UNTOUCHED_TEST_VALUE = new Untouched(); @@ -143,7 +143,7 @@ public class TransformerHolisticIT { private static final String TEST_VECTOR_MANIFEST_DIR = "/vectors/encrypted_item/"; - private static final String SCENARIO_MANIFEST_PATH = + public static final String SCENARIO_MANIFEST_PATH = TEST_VECTOR_MANIFEST_DIR + "scenarios.json"; private static final String JAVA_DIR = "java"; @@ -1516,7 +1516,7 @@ private void putDataFromFile(AmazonDynamoDB client, String filename) } } - private Map< + public static Map< String, List> > getCiphertextManifestFromFile(String filename) throws IOException { @@ -1528,7 +1528,7 @@ > getCiphertextManifestFromFile(String filename) throws IOException { ); } - private static T getManifestFromFile( + public static T getManifestFromFile( String filename, TypeReference typeRef ) throws IOException { @@ -1543,7 +1543,7 @@ private static T getManifestFromFile( return (T) manifestMapper.readValue(manifestFile, typeRef); } - private static void loadKeyData(String filename) throws IOException { + static void loadKeyData(String filename) throws IOException { keyDataMap = getManifestFromFile( TEST_VECTOR_MANIFEST_DIR + stripFilePath(filename), diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticITHelper.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticITHelper.java new file mode 100644 index 0000000000..56f269b220 --- /dev/null +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticITHelper.java @@ -0,0 +1,160 @@ +package com.amazonaws.services.dynamodbv2.datamodeling; + +import com.amazonaws.services.dynamodbv2.datamodeling.encryption.DynamoDBEncryptor; +import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext; +import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags; +import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.DirectKmsMaterialProvider; +import com.amazonaws.services.dynamodbv2.model.AttributeValue; +import com.fasterxml.jackson.core.type.TypeReference; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.List; + +import static com.amazonaws.services.dynamodbv2.datamodeling.LegacyTestVectors.baseClassToV1AttrMap; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.ENCRYPTED_TEST_VALUE; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.symProv; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.getCiphertextManifestFromFile; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.BASE_CLASS_TABLE_NAME; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.SCENARIO_MANIFEST_PATH; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.loadKeyData; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.kmsClient; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.keyDataMap; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.getManifestFromFile; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; + +public class TransformerHolisticITHelper { + private static void decryptNullTableNameInEC(String nullTableNameInECCipherFile) + throws IOException, GeneralSecurityException { + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext ctx = new EncryptionContext.Builder() + .withTableName(null) + .withHashKeyName("hashKey") + .withRangeKeyName("rangeKey") + .build(); + + Map expectedAttrMap = baseClassToV1AttrMap( + ENCRYPTED_TEST_VALUE + ); + Map> actions = new HashMap<>(); + for (String attr : expectedAttrMap.keySet()) { + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, EnumSet.of(EncryptionFlags.SIGN)); + break; + default: + actions.put( + attr, + EnumSet.of(EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN) + ); + break; + } + } + + Map>> manifest = + getCiphertextManifestFromFile(nullTableNameInECCipherFile); + + for (Map encryptedItem : manifest.get( + BASE_CLASS_TABLE_NAME + )) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertTrue( + new com.amazonaws.services.dynamodbv2.testing.DdbRecordMatcher(expectedAttrMap, false).matches(decrypted) + ); + } + } + + private static void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) + throws IOException, GeneralSecurityException { + com.amazonaws.services.dynamodbv2.testing.ScenarioManifest scenarioManifest = getManifestFromFile( + SCENARIO_MANIFEST_PATH, + new TypeReference() {} + ); + loadKeyData(scenarioManifest.keyDataPath); + + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( + new DirectKmsMaterialProvider( + kmsClient, + keyDataMap.get("awsKmsUsWest2").keyId + ) + ); + EncryptionContext ctx = new EncryptionContext.Builder() + .withTableName("HashKeyOnly") + .withHashKeyName("hashKey") + .build(); + + Map> actions = new HashMap<>(); + actions.put("hashKey", EnumSet.of(EncryptionFlags.SIGN)); + + String nonBmpKey = "test\uD83D\uDE00Ψkey"; + Map>> manifest = + getCiphertextManifestFromFile(nonBMPinECCipherFile); + for (Map encryptedItem : manifest.get( + BASE_CLASS_TABLE_NAME + )) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertEquals(nonBmpKey, decrypted.get("hashKey").getS()); + } + } + + private static void decryptNonAsciiTableNameVector( + String nonAsciiTableInECCipherFile + ) throws IOException, GeneralSecurityException { + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext ctx = + new com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext.Builder() + .withTableName("テーブル\uD83D\uDE00") + .withHashKeyName("hashKey") + .withRangeKeyName("rangeKey") + .build(); + + Map expectedAttrMap = baseClassToV1AttrMap( + ENCRYPTED_TEST_VALUE + ); + Map< + String, + Set< + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags + > + > actions = new HashMap<>(); + for (String attr : expectedAttrMap.keySet()) { + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put( + attr, + EnumSet.of( + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN + ) + ); + break; + default: + actions.put( + attr, + EnumSet.of( + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.ENCRYPT, + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN + ) + ); + break; + } + } + } +} From e22fdf75eb056ea5caa8e6d9afe49dcc9119b382 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 12 Mar 2026 15:58:29 -0700 Subject: [PATCH 11/16] m --- .../datamodeling/sdkv2/HolisticIT.java | 114 ------------------ 1 file changed, 114 deletions(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java index cc0a836869..0366201ab5 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java @@ -554,120 +554,6 @@ public void decryptWithECConfigTest() HolisticITHelper.decryptNonAsciiTableNameVector(nonAsciiTableInECCipherFile); } - public void decryptNullTableNameInEC(String nullTableNameInECCipherFile) - throws IOException, GeneralSecurityException { - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext ctx = EncryptionContext - .builder() - .tableName(null) - .hashKeyName("hashKey") - .rangeKeyName("rangeKey") - .build(); - - Map> actions = new HashMap<>(); - for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { - switch (attr) { - case "hashKey": - case "rangeKey": - case "version": - actions.put(attr, signOnly); - break; - default: - actions.put(attr, encryptAndSign); - break; - } - } - - Map>> manifest = - getCiphertextManifestFromFile(nullTableNameInECCipherFile); - for (Map encryptedItem : manifest.get(tableName)) { - Map decrypted = encryptor.decryptRecord( - encryptedItem, - actions, - ctx - ); - assertTrue( - new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted) - ); - } - } - - public void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) - throws IOException, GeneralSecurityException { - ScenarioManifest scenarioManifest = getManifestFromFile( - SCENARIO_MANIFEST_PATH, - new TypeReference() {} - ); - loadKeyData(scenarioManifest.keyDataPath); - - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( - new DirectKmsMaterialsProvider( - kmsClient, - keyDataMap.get("awsKmsUsWest2").keyId - ) - ); - EncryptionContext ctx = EncryptionContext - .builder() - .tableName("HashKeyOnly") - .hashKeyName("hashKey") - .build(); - - Map> actions = new HashMap<>(); - actions.put("hashKey", signOnly); - - String nonBmpKey = "test\uD83D\uDE00Ψkey"; - - Map>> manifest = - getCiphertextManifestFromFile(nonBMPinECCipherFile); - for (Map encryptedItem : manifest.get(tableName)) { - Map decrypted = encryptor.decryptRecord( - encryptedItem, - actions, - ctx - ); - assertEquals(nonBmpKey, decrypted.get("hashKey").s()); - } - } - - public void decryptNonAsciiTableNameVector( - String nonAsciiTableInECCipherFile - ) throws IOException, GeneralSecurityException { - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext ctx = EncryptionContext - .builder() - .tableName("テーブル\uD83D\uDE00") - .hashKeyName("hashKey") - .rangeKeyName("rangeKey") - .build(); - - Map> actions = new HashMap<>(); - for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { - switch (attr) { - case "hashKey": - case "rangeKey": - case "version": - actions.put(attr, signOnly); - break; - default: - actions.put(attr, encryptAndSign); - break; - } - } - - Map>> manifest = - getCiphertextManifestFromFile(nonAsciiTableInECCipherFile); - for (Map encryptedItem : manifest.get(tableName)) { - Map decrypted = encryptor.decryptRecord( - encryptedItem, - actions, - ctx - ); - assertTrue( - new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted) - ); - } - } - @Test(dataProvider = "getDecryptTestVectors") public void decryptTestVector(Scenario scenario) throws IOException, GeneralSecurityException { From 91d4b480ebc3f03d980237e608df9f5942d7b0ff Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 12 Mar 2026 16:08:24 -0700 Subject: [PATCH 12/16] m --- .../services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java | 4 +++- .../dynamodbv2/datamodeling/sdkv2/HolisticITHelper.java | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java index 0366201ab5..4d2270f5c4 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java @@ -550,7 +550,9 @@ public void decryptWithECConfigTest() "file://ciphertext/java/static-aes-hmac-nonascii-table-1.json"; HolisticITHelper.decryptNullTableNameInEC(nullTableNameInECCipherFile); - HolisticITHelper.decryptNonBmpHashKeyVector(nonBMPinECCipherFile); + // decryptNonBmpHashKeyVectorAndWithNullKeyId uses non bmp hash key and also does not use any KMS key id which proves + // that KMS key id is fetched from message format + HolisticITHelper.decryptNonBmpHashKeyVectorAndWithNullKeyId(nonBMPinECCipherFile); HolisticITHelper.decryptNonAsciiTableNameVector(nonAsciiTableInECCipherFile); } diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticITHelper.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticITHelper.java index a339cf6ee9..8f6ad6be24 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticITHelper.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticITHelper.java @@ -98,7 +98,7 @@ public static void decryptNullTableNameInEC(String nullTableNameInECCipherFile) } } - public static void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) + public static void decryptNonBmpHashKeyVectorAndWithNullKeyId(String nonBMPinECCipherFile) throws IOException, GeneralSecurityException { ScenarioManifest scenarioManifest = getManifestFromFile( SCENARIO_MANIFEST_PATH, @@ -108,8 +108,7 @@ public static void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( new DirectKmsMaterialsProvider( - kmsClient, - keyDataMap.get("awsKmsUsWest2").keyId + kmsClient ) ); EncryptionContext ctx = EncryptionContext From c0624c57696ae5fc5c24b38431404044a8fe2806 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 12 Mar 2026 16:30:17 -0700 Subject: [PATCH 13/16] m --- .../datamodeling/TransformerHolisticIT.java | 152 +----------------- .../TransformerHolisticITHelper.java | 6 +- 2 files changed, 6 insertions(+), 152 deletions(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java index b62d6295b4..6634613f72 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java @@ -12,8 +12,6 @@ import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.SaveBehavior; import com.amazonaws.services.dynamodbv2.datamodeling.encryption.DynamoDBEncryptor; -import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext; -import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags; import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.AsymmetricStaticProvider; import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.CachingMostRecentProvider; import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.DirectKmsMaterialProvider; @@ -26,7 +24,6 @@ import com.amazonaws.services.dynamodbv2.model.*; import com.amazonaws.services.dynamodbv2.testing.AttributeValueDeserializer; import com.amazonaws.services.dynamodbv2.testing.AttributeValueSerializer; -import com.amazonaws.services.dynamodbv2.testing.DdbRecordMatcher; import com.amazonaws.services.dynamodbv2.testing.ScenarioManifest; import com.amazonaws.services.dynamodbv2.testing.ScenarioManifest.KeyData; import com.amazonaws.services.dynamodbv2.testing.ScenarioManifest.Keys; @@ -341,152 +338,9 @@ public void decryptWithECConfigTest() final String nonAsciiTableInECCipherFile = "file://ciphertext/java/static-aes-hmac-nonascii-table-1.json"; - decryptNullTableNameInEC(nullTableNameInECCipherFile); - decryptNonBmpHashKeyVector(nonBMPinECCipherFile); - decryptNonAsciiTableNameVector(nonAsciiTableInECCipherFile); - } - - private void decryptNullTableNameInEC(String nullTableNameInECCipherFile) - throws IOException, GeneralSecurityException { - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext ctx = new EncryptionContext.Builder() - .withTableName(null) - .withHashKeyName("hashKey") - .withRangeKeyName("rangeKey") - .build(); - - Map expectedAttrMap = baseClassToV1AttrMap( - ENCRYPTED_TEST_VALUE - ); - Map> actions = new HashMap<>(); - for (String attr : expectedAttrMap.keySet()) { - switch (attr) { - case "hashKey": - case "rangeKey": - case "version": - actions.put(attr, EnumSet.of(EncryptionFlags.SIGN)); - break; - default: - actions.put( - attr, - EnumSet.of(EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN) - ); - break; - } - } - - Map>> manifest = - getCiphertextManifestFromFile(nullTableNameInECCipherFile); - - for (Map encryptedItem : manifest.get( - BASE_CLASS_TABLE_NAME - )) { - Map decrypted = encryptor.decryptRecord( - encryptedItem, - actions, - ctx - ); - assertTrue( - new DdbRecordMatcher(expectedAttrMap, false).matches(decrypted) - ); - } - } - - private void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) - throws IOException, GeneralSecurityException { - ScenarioManifest scenarioManifest = getManifestFromFile( - SCENARIO_MANIFEST_PATH, - new TypeReference() {} - ); - loadKeyData(scenarioManifest.keyDataPath); - - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( - new DirectKmsMaterialProvider( - kmsClient, - keyDataMap.get("awsKmsUsWest2").keyId - ) - ); - EncryptionContext ctx = new EncryptionContext.Builder() - .withTableName("HashKeyOnly") - .withHashKeyName("hashKey") - .build(); - - Map> actions = new HashMap<>(); - actions.put("hashKey", EnumSet.of(EncryptionFlags.SIGN)); - - String nonBmpKey = "test\uD83D\uDE00Ψkey"; - Map>> manifest = - getCiphertextManifestFromFile(nonBMPinECCipherFile); - for (Map encryptedItem : manifest.get( - BASE_CLASS_TABLE_NAME - )) { - Map decrypted = encryptor.decryptRecord( - encryptedItem, - actions, - ctx - ); - assertEquals(nonBmpKey, decrypted.get("hashKey").getS()); - } - } - - private void decryptNonAsciiTableNameVector( - String nonAsciiTableInECCipherFile - ) throws IOException, GeneralSecurityException { - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext ctx = - new com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext.Builder() - .withTableName("テーブル\uD83D\uDE00") - .withHashKeyName("hashKey") - .withRangeKeyName("rangeKey") - .build(); - - Map expectedAttrMap = baseClassToV1AttrMap( - ENCRYPTED_TEST_VALUE - ); - Map< - String, - Set< - com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags - > - > actions = new HashMap<>(); - for (String attr : expectedAttrMap.keySet()) { - switch (attr) { - case "hashKey": - case "rangeKey": - case "version": - actions.put( - attr, - EnumSet.of( - com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN - ) - ); - break; - default: - actions.put( - attr, - EnumSet.of( - com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.ENCRYPT, - com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN - ) - ); - break; - } - } - - Map>> manifest = - getCiphertextManifestFromFile(nonAsciiTableInECCipherFile); - for (Map encryptedItem : manifest.get( - BASE_CLASS_TABLE_NAME - )) { - Map decrypted = encryptor.decryptRecord( - encryptedItem, - actions, - ctx - ); - assertTrue( - new DdbRecordMatcher(expectedAttrMap, false).matches(decrypted) - ); - } + TransformerHolisticITHelper.decryptNullTableNameInEC(nullTableNameInECCipherFile); + TransformerHolisticITHelper.decryptNonBmpHashKeyVector(nonBMPinECCipherFile); + TransformerHolisticITHelper.decryptNonAsciiTableNameVector(nonAsciiTableInECCipherFile); } @Test(dataProvider = "getDecryptTestVectors") diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticITHelper.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticITHelper.java index 56f269b220..f275eab93e 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticITHelper.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticITHelper.java @@ -30,7 +30,7 @@ import static org.testng.AssertJUnit.assertTrue; public class TransformerHolisticITHelper { - private static void decryptNullTableNameInEC(String nullTableNameInECCipherFile) + public static void decryptNullTableNameInEC(String nullTableNameInECCipherFile) throws IOException, GeneralSecurityException { DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); EncryptionContext ctx = new EncryptionContext.Builder() @@ -76,7 +76,7 @@ private static void decryptNullTableNameInEC(String nullTableNameInECCipherFile) } } - private static void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) + public static void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) throws IOException, GeneralSecurityException { com.amazonaws.services.dynamodbv2.testing.ScenarioManifest scenarioManifest = getManifestFromFile( SCENARIO_MANIFEST_PATH, @@ -113,7 +113,7 @@ private static void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) } } - private static void decryptNonAsciiTableNameVector( + public static void decryptNonAsciiTableNameVector( String nonAsciiTableInECCipherFile ) throws IOException, GeneralSecurityException { DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); From dbcca78553e4aee905078305f57b33b93680a7eb Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Fri, 13 Mar 2026 09:47:51 -0700 Subject: [PATCH 14/16] formatting --- .../datamodeling/TransformerHolisticIT.java | 12 +- .../TransformerHolisticITHelper.java | 269 +++++++++--------- .../datamodeling/sdkv2/HolisticIT.java | 12 +- .../datamodeling/sdkv2/HolisticITHelper.java | 212 +++++++------- 4 files changed, 263 insertions(+), 242 deletions(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java index 6634613f72..4efb542194 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticIT.java @@ -338,9 +338,15 @@ public void decryptWithECConfigTest() final String nonAsciiTableInECCipherFile = "file://ciphertext/java/static-aes-hmac-nonascii-table-1.json"; - TransformerHolisticITHelper.decryptNullTableNameInEC(nullTableNameInECCipherFile); - TransformerHolisticITHelper.decryptNonBmpHashKeyVector(nonBMPinECCipherFile); - TransformerHolisticITHelper.decryptNonAsciiTableNameVector(nonAsciiTableInECCipherFile); + TransformerHolisticITHelper.decryptNullTableNameInEC( + nullTableNameInECCipherFile + ); + TransformerHolisticITHelper.decryptNonBmpHashKeyVector( + nonBMPinECCipherFile + ); + TransformerHolisticITHelper.decryptNonAsciiTableNameVector( + nonAsciiTableInECCipherFile + ); } @Test(dataProvider = "getDecryptTestVectors") diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticITHelper.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticITHelper.java index f275eab93e..40e816a5b3 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticITHelper.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/TransformerHolisticITHelper.java @@ -1,160 +1,167 @@ package com.amazonaws.services.dynamodbv2.datamodeling; +import static com.amazonaws.services.dynamodbv2.datamodeling.LegacyTestVectors.baseClassToV1AttrMap; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.BASE_CLASS_TABLE_NAME; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.ENCRYPTED_TEST_VALUE; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.SCENARIO_MANIFEST_PATH; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.getCiphertextManifestFromFile; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.getManifestFromFile; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.keyDataMap; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.kmsClient; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.loadKeyData; +import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.symProv; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; + import com.amazonaws.services.dynamodbv2.datamodeling.encryption.DynamoDBEncryptor; import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext; import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags; import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.DirectKmsMaterialProvider; import com.amazonaws.services.dynamodbv2.model.AttributeValue; import com.fasterxml.jackson.core.type.TypeReference; - import java.io.IOException; import java.security.GeneralSecurityException; import java.util.EnumSet; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; -import java.util.List; - -import static com.amazonaws.services.dynamodbv2.datamodeling.LegacyTestVectors.baseClassToV1AttrMap; -import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.ENCRYPTED_TEST_VALUE; -import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.symProv; -import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.getCiphertextManifestFromFile; -import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.BASE_CLASS_TABLE_NAME; -import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.SCENARIO_MANIFEST_PATH; -import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.loadKeyData; -import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.kmsClient; -import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.keyDataMap; -import static com.amazonaws.services.dynamodbv2.datamodeling.TransformerHolisticIT.getManifestFromFile; - -import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertTrue; public class TransformerHolisticITHelper { - public static void decryptNullTableNameInEC(String nullTableNameInECCipherFile) - throws IOException, GeneralSecurityException { - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext ctx = new EncryptionContext.Builder() - .withTableName(null) - .withHashKeyName("hashKey") - .withRangeKeyName("rangeKey") - .build(); - Map expectedAttrMap = baseClassToV1AttrMap( - ENCRYPTED_TEST_VALUE - ); - Map> actions = new HashMap<>(); - for (String attr : expectedAttrMap.keySet()) { - switch (attr) { - case "hashKey": - case "rangeKey": - case "version": - actions.put(attr, EnumSet.of(EncryptionFlags.SIGN)); - break; - default: - actions.put( - attr, - EnumSet.of(EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN) - ); - break; - } - } + public static void decryptNullTableNameInEC( + String nullTableNameInECCipherFile + ) throws IOException, GeneralSecurityException { + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext ctx = new EncryptionContext.Builder() + .withTableName(null) + .withHashKeyName("hashKey") + .withRangeKeyName("rangeKey") + .build(); + + Map expectedAttrMap = baseClassToV1AttrMap( + ENCRYPTED_TEST_VALUE + ); + Map> actions = new HashMap<>(); + for (String attr : expectedAttrMap.keySet()) { + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, EnumSet.of(EncryptionFlags.SIGN)); + break; + default: + actions.put( + attr, + EnumSet.of(EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN) + ); + break; + } + } - Map>> manifest = - getCiphertextManifestFromFile(nullTableNameInECCipherFile); + Map>> manifest = + getCiphertextManifestFromFile(nullTableNameInECCipherFile); - for (Map encryptedItem : manifest.get( - BASE_CLASS_TABLE_NAME - )) { - Map decrypted = encryptor.decryptRecord( - encryptedItem, - actions, - ctx - ); - assertTrue( - new com.amazonaws.services.dynamodbv2.testing.DdbRecordMatcher(expectedAttrMap, false).matches(decrypted) - ); - } + for (Map encryptedItem : manifest.get( + BASE_CLASS_TABLE_NAME + )) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertTrue( + new com.amazonaws.services.dynamodbv2.testing.DdbRecordMatcher( + expectedAttrMap, + false + ) + .matches(decrypted) + ); } + } - public static void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) - throws IOException, GeneralSecurityException { - com.amazonaws.services.dynamodbv2.testing.ScenarioManifest scenarioManifest = getManifestFromFile( - SCENARIO_MANIFEST_PATH, - new TypeReference() {} - ); - loadKeyData(scenarioManifest.keyDataPath); + public static void decryptNonBmpHashKeyVector(String nonBMPinECCipherFile) + throws IOException, GeneralSecurityException { + com.amazonaws.services.dynamodbv2.testing.ScenarioManifest scenarioManifest = + getManifestFromFile( + SCENARIO_MANIFEST_PATH, + new TypeReference< + com.amazonaws.services.dynamodbv2.testing.ScenarioManifest + >() {} + ); + loadKeyData(scenarioManifest.keyDataPath); - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( - new DirectKmsMaterialProvider( - kmsClient, - keyDataMap.get("awsKmsUsWest2").keyId - ) - ); - EncryptionContext ctx = new EncryptionContext.Builder() - .withTableName("HashKeyOnly") - .withHashKeyName("hashKey") - .build(); + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( + new DirectKmsMaterialProvider( + kmsClient, + keyDataMap.get("awsKmsUsWest2").keyId + ) + ); + EncryptionContext ctx = new EncryptionContext.Builder() + .withTableName("HashKeyOnly") + .withHashKeyName("hashKey") + .build(); - Map> actions = new HashMap<>(); - actions.put("hashKey", EnumSet.of(EncryptionFlags.SIGN)); + Map> actions = new HashMap<>(); + actions.put("hashKey", EnumSet.of(EncryptionFlags.SIGN)); - String nonBmpKey = "test\uD83D\uDE00Ψkey"; - Map>> manifest = - getCiphertextManifestFromFile(nonBMPinECCipherFile); - for (Map encryptedItem : manifest.get( - BASE_CLASS_TABLE_NAME - )) { - Map decrypted = encryptor.decryptRecord( - encryptedItem, - actions, - ctx - ); - assertEquals(nonBmpKey, decrypted.get("hashKey").getS()); - } + String nonBmpKey = "test\uD83D\uDE00Ψkey"; + Map>> manifest = + getCiphertextManifestFromFile(nonBMPinECCipherFile); + for (Map encryptedItem : manifest.get( + BASE_CLASS_TABLE_NAME + )) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertEquals(nonBmpKey, decrypted.get("hashKey").getS()); } + } - public static void decryptNonAsciiTableNameVector( - String nonAsciiTableInECCipherFile - ) throws IOException, GeneralSecurityException { - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext ctx = - new com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext.Builder() - .withTableName("テーブル\uD83D\uDE00") - .withHashKeyName("hashKey") - .withRangeKeyName("rangeKey") - .build(); + public static void decryptNonAsciiTableNameVector( + String nonAsciiTableInECCipherFile + ) throws IOException, GeneralSecurityException { + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext ctx = + new com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext.Builder() + .withTableName("テーブル\uD83D\uDE00") + .withHashKeyName("hashKey") + .withRangeKeyName("rangeKey") + .build(); - Map expectedAttrMap = baseClassToV1AttrMap( - ENCRYPTED_TEST_VALUE - ); - Map< - String, - Set< - com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags - > - > actions = new HashMap<>(); - for (String attr : expectedAttrMap.keySet()) { - switch (attr) { - case "hashKey": - case "rangeKey": - case "version": - actions.put( - attr, - EnumSet.of( - com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN - ) - ); - break; - default: - actions.put( - attr, - EnumSet.of( - com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.ENCRYPT, - com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN - ) - ); - break; - } - } + Map expectedAttrMap = baseClassToV1AttrMap( + ENCRYPTED_TEST_VALUE + ); + Map< + String, + Set< + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags + > + > actions = new HashMap<>(); + for (String attr : expectedAttrMap.keySet()) { + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put( + attr, + EnumSet.of( + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN + ) + ); + break; + default: + actions.put( + attr, + EnumSet.of( + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.ENCRYPT, + com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags.SIGN + ) + ); + break; + } } + } } diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java index 4d2270f5c4..c17a0f44f6 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java @@ -102,7 +102,9 @@ public class HolisticIT { private static final String RANGE_KEY = "rangeKey"; private static final String RSA = "RSA"; public static final String tableName = "TableName"; - public static final EnumSet signOnly = EnumSet.of(EncryptionFlags.SIGN); + public static final EnumSet signOnly = EnumSet.of( + EncryptionFlags.SIGN + ); public static final EnumSet encryptAndSign = EnumSet.of( EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN @@ -552,8 +554,12 @@ public void decryptWithECConfigTest() HolisticITHelper.decryptNullTableNameInEC(nullTableNameInECCipherFile); // decryptNonBmpHashKeyVectorAndWithNullKeyId uses non bmp hash key and also does not use any KMS key id which proves // that KMS key id is fetched from message format - HolisticITHelper.decryptNonBmpHashKeyVectorAndWithNullKeyId(nonBMPinECCipherFile); - HolisticITHelper.decryptNonAsciiTableNameVector(nonAsciiTableInECCipherFile); + HolisticITHelper.decryptNonBmpHashKeyVectorAndWithNullKeyId( + nonBMPinECCipherFile + ); + HolisticITHelper.decryptNonAsciiTableNameVector( + nonAsciiTableInECCipherFile + ); } @Test(dataProvider = "getDecryptTestVectors") diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticITHelper.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticITHelper.java index 8f6ad6be24..9ac539b162 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticITHelper.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/HolisticITHelper.java @@ -1,5 +1,9 @@ package com.amazonaws.services.dynamodbv2.datamodeling.sdkv2; +import static com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.HolisticIT.*; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; + import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.encryption.DynamoDBEncryptor; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.encryption.EncryptionContext; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.encryption.EncryptionFlags; @@ -7,130 +11,128 @@ import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.DdbRecordMatcher; import com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.ScenarioManifest; import com.fasterxml.jackson.core.type.TypeReference; -import software.amazon.awssdk.services.dynamodb.model.AttributeValue; - import java.io.IOException; import java.security.GeneralSecurityException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; - -import static com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.HolisticIT.*; -import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertTrue; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; public class HolisticITHelper { - public static void decryptNonAsciiTableNameVector( - String nonAsciiTableInECCipherFile - ) throws IOException, GeneralSecurityException { - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext ctx = EncryptionContext - .builder() - .tableName("テーブル\uD83D\uDE00") - .hashKeyName("hashKey") - .rangeKeyName("rangeKey") - .build(); - Map> actions = new HashMap<>(); - for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { - switch (attr) { - case "hashKey": - case "rangeKey": - case "version": - actions.put(attr, signOnly); - break; - default: - actions.put(attr, encryptAndSign); - break; - } - } + public static void decryptNonAsciiTableNameVector( + String nonAsciiTableInECCipherFile + ) throws IOException, GeneralSecurityException { + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext ctx = EncryptionContext + .builder() + .tableName("テーブル\uD83D\uDE00") + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); - Map>> manifest = - getCiphertextManifestFromFile(nonAsciiTableInECCipherFile); - for (Map encryptedItem : manifest.get(tableName)) { - Map decrypted = encryptor.decryptRecord( - encryptedItem, - actions, - ctx - ); - assertTrue( - new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted) - ); - } + Map> actions = new HashMap<>(); + for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, signOnly); + break; + default: + actions.put(attr, encryptAndSign); + break; + } } - public static void decryptNullTableNameInEC(String nullTableNameInECCipherFile) - throws IOException, GeneralSecurityException { - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext ctx = EncryptionContext - .builder() - .tableName(null) - .hashKeyName("hashKey") - .rangeKeyName("rangeKey") - .build(); + Map>> manifest = + getCiphertextManifestFromFile(nonAsciiTableInECCipherFile); + for (Map encryptedItem : manifest.get(tableName)) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertTrue( + new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted) + ); + } + } + + public static void decryptNullTableNameInEC( + String nullTableNameInECCipherFile + ) throws IOException, GeneralSecurityException { + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext ctx = EncryptionContext + .builder() + .tableName(null) + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); - Map> actions = new HashMap<>(); - for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { - switch (attr) { - case "hashKey": - case "rangeKey": - case "version": - actions.put(attr, signOnly); - break; - default: - actions.put(attr, encryptAndSign); - break; - } - } + Map> actions = new HashMap<>(); + for (String attr : ENCRYPTED_TEST_VALUE.keySet()) { + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, signOnly); + break; + default: + actions.put(attr, encryptAndSign); + break; + } + } - Map>> manifest = - getCiphertextManifestFromFile(nullTableNameInECCipherFile); - for (Map encryptedItem : manifest.get(tableName)) { - Map decrypted = encryptor.decryptRecord( - encryptedItem, - actions, - ctx - ); - assertTrue( - new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted) - ); - } + Map>> manifest = + getCiphertextManifestFromFile(nullTableNameInECCipherFile); + for (Map encryptedItem : manifest.get(tableName)) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertTrue( + new DdbRecordMatcher(ENCRYPTED_TEST_VALUE, false).matches(decrypted) + ); } + } - public static void decryptNonBmpHashKeyVectorAndWithNullKeyId(String nonBMPinECCipherFile) - throws IOException, GeneralSecurityException { - ScenarioManifest scenarioManifest = getManifestFromFile( - SCENARIO_MANIFEST_PATH, - new TypeReference() {} - ); - loadKeyData(scenarioManifest.keyDataPath); + public static void decryptNonBmpHashKeyVectorAndWithNullKeyId( + String nonBMPinECCipherFile + ) throws IOException, GeneralSecurityException { + ScenarioManifest scenarioManifest = getManifestFromFile( + SCENARIO_MANIFEST_PATH, + new TypeReference< + com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.ScenarioManifest + >() {} + ); + loadKeyData(scenarioManifest.keyDataPath); - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( - new DirectKmsMaterialsProvider( - kmsClient - ) - ); - EncryptionContext ctx = EncryptionContext - .builder() - .tableName("HashKeyOnly") - .hashKeyName("hashKey") - .build(); + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance( + new DirectKmsMaterialsProvider(kmsClient) + ); + EncryptionContext ctx = EncryptionContext + .builder() + .tableName("HashKeyOnly") + .hashKeyName("hashKey") + .build(); - Map> actions = new HashMap<>(); - actions.put("hashKey", signOnly); + Map> actions = new HashMap<>(); + actions.put("hashKey", signOnly); - String nonBmpKey = "test\uD83D\uDE00Ψkey"; + String nonBmpKey = "test\uD83D\uDE00Ψkey"; - Map>> manifest = - getCiphertextManifestFromFile(nonBMPinECCipherFile); - for (Map encryptedItem : manifest.get(tableName)) { - Map decrypted = encryptor.decryptRecord( - encryptedItem, - actions, - ctx - ); - assertEquals(nonBmpKey, decrypted.get("hashKey").s()); - } + Map>> manifest = + getCiphertextManifestFromFile(nonBMPinECCipherFile); + for (Map encryptedItem : manifest.get(tableName)) { + Map decrypted = encryptor.decryptRecord( + encryptedItem, + actions, + ctx + ); + assertEquals(nonBmpKey, decrypted.get("hashKey").s()); } + } } From 24a064f11d4b2a5bdefda2a44e0b8c0bb9c6e294 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Fri, 13 Mar 2026 10:51:32 -0700 Subject: [PATCH 15/16] Don't reuse test --- DynamoDbEncryption/runtimes/java/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/DynamoDbEncryption/runtimes/java/build.gradle.kts b/DynamoDbEncryption/runtimes/java/build.gradle.kts index 0557befdbb..054334cf1c 100644 --- a/DynamoDbEncryption/runtimes/java/build.gradle.kts +++ b/DynamoDbEncryption/runtimes/java/build.gradle.kts @@ -189,6 +189,7 @@ tasks.withType() { } tasks.test { + outputs.upToDateWhen { false } useTestNG() dependsOn("CopyDynamoDb") systemProperty("java.library.path", "build/libs") From aa491773525608ad6d9b8c24a01b4bdd42da13f3 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Fri, 13 Mar 2026 11:09:30 -0700 Subject: [PATCH 16/16] Revert "Don't reuse test" This reverts commit 24a064f11d4b2a5bdefda2a44e0b8c0bb9c6e294. --- DynamoDbEncryption/runtimes/java/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/DynamoDbEncryption/runtimes/java/build.gradle.kts b/DynamoDbEncryption/runtimes/java/build.gradle.kts index 054334cf1c..0557befdbb 100644 --- a/DynamoDbEncryption/runtimes/java/build.gradle.kts +++ b/DynamoDbEncryption/runtimes/java/build.gradle.kts @@ -189,7 +189,6 @@ tasks.withType() { } tasks.test { - outputs.upToDateWhen { false } useTestNG() dependsOn("CopyDynamoDb") systemProperty("java.library.path", "build/libs")