From 74c84aba323fe0544f84a73a042b2a22ab7ccb7e Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sat, 28 Mar 2026 12:47:02 -0700 Subject: [PATCH 01/18] m --- .../java/static-aes-hmac-complex-1.json | 198 +++++++++++ .../vectors/encrypted_item/scenarios.json | 11 + .../datamodeling/LegacyTestVectors.java | 77 +++++ .../datamodeling/TransformerHolisticIT.java | 145 ++++++-- .../datamodeling/sdkv2/HolisticIT.java | 326 +++++++++++++++++- 5 files changed, 729 insertions(+), 28 deletions(-) create mode 100644 DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json diff --git a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json new file mode 100644 index 0000000000..3417a5535a --- /dev/null +++ b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json @@ -0,0 +1,198 @@ +{ + "TableName": [ + { + "hashKey": { + "N": "5" + }, + "intSet": { + "B": "8opVq3jaEQzMyl/IpUpPSMT4/ZBCWM99xKZbHLUgOAC9VQy6s8ALz31nouDRdHsO3di+gK+lc5KyZ3Xnswy8ug==" + }, + "doubleSet": { + "B": "pj0Z9DVUZwaWRZAc5VDRqLuCVnaPIWrwRD0o8ov92rjMUh/x5dRq9x6wUJvFQk3b5OHpiaV9h37Szww6ZznvOg==" + }, + "intValue": { + "B": "9Ykw7qNiJnxRFq4Qv3FULrcAH/zjgxwUnk6TCTmpRo0=" + }, + "stringSet": { + "B": "BGF4UgtpuxecA4ekUfdrSTi5780EjKnK27p3xKRwCNHqKabD6qts86KKKWfudISZ0EHRU9rqYDt4Worz7krguA==" + }, + "doubleValue": { + "B": "mjlEbixV4CXTu69osmacBk1fpsDZu5T33gHKSnblq2o=" + }, + "version": { + "N": "0" + }, + "*amzn-ddb-map-sig*": { + "B": "sU5hyFsSyqRN0Xo8gHXPw5xMU4RPOR8AgFefsFSCmEE=" + }, + "rangeKey": { + "N": "7" + }, + "stringValue": { + "B": "+sY4HCjSWlPQBpjyhdLPQm3a+qgMzba7dS9Cr+jXKS/iGgebu6n6H95D4AGfNEyu" + }, + "*amzn-ddb-map-desc*": { + "B": "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" + }, + "byteArrayValue": { + "B": "4ofQ7VKBlFWO+VZb1LIQQsDvmkeh6W82MFs2JKP0XCs=" + }, + "complexValue": { + "B": "Eh8eXrxBUCZ4x/QR9Ub7l0inMcHHL5GhgDFUuc64+Fk196zzebXFyr1yHE/Yfr57jstYIPS1XXOtGHaa6TCFh+hQQOijcLxkxKyeRboev2vCOoPF3Og9SMwRcZvlchxePJsHeIBTc0KlKHD1nZ4sSEmDdxmy7E9mZgcgHELYwoA=" + } + }, + { + "hashKey": { + "N": "8" + }, + "intSet": { + "NS": ["0", "1", "10", "15", "200"] + }, + "doubleSet": { + "NS": ["-34.2", "-3", "0", "7.6", "15"] + }, + "intValue": { + "N": "123" + }, + "stringSet": { + "SS": ["?", "Cruel", "Goodbye", "World"] + }, + "doubleValue": { + "N": "15" + }, + "version": { + "N": "0" + }, + "*amzn-ddb-map-sig*": { + "B": "n7z2izd+rfq/3BGoqRRgobOwZ3zHEkYZwWdnDpG7CNw=" + }, + "rangeKey": { + "N": "10" + }, + "stringValue": { + "S": "Hello world!" + }, + "*amzn-ddb-map-desc*": { + "B": "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" + }, + "byteArrayValue": { + "B": "AAECAwQF" + }, + "complexValue": { + "L": [ + { + "M": { + "innerNum": { + "S": "42" + }, + "innerKey": { + "S": "innerVal" + } + } + }, + { + "M": { + "nestedKey": { + "S": "nestedVal" + } + } + } + ] + } + }, + { + "rangeKey": { + "N": "9" + }, + "hashKey": { + "N": "7" + }, + "stringValue": { + "S": "Hello world!" + }, + "intSet": { + "NS": ["0", "1", "10", "15", "200"] + }, + "doubleSet": { + "NS": ["-34.2", "-3", "0", "7.6", "15"] + }, + "byteArrayValue": { + "B": "AAECAwQF" + }, + "complexValue": { + "L": [ + { + "M": { + "innerNum": { + "S": "42" + }, + "innerKey": { + "S": "innerVal" + } + } + }, + { + "M": { + "nestedKey": { + "S": "nestedVal" + } + } + } + ] + }, + "intValue": { + "N": "123" + }, + "stringSet": { + "SS": ["?", "Cruel", "Goodbye", "World"] + }, + "doubleValue": { + "N": "15" + }, + "version": { + "N": "0" + } + }, + { + "hashKey": { + "N": "6" + }, + "intSet": { + "B": "GQqk1bZLTkSwzf/v95GBpxKVjQFNs/PDeRY8eltfzDVFs1HRhNwP6A9VobvR+rv7aCwhIzXWRepkTPoibalm7w==" + }, + "doubleSet": { + "NS": ["-34.2", "-3", "0", "7.6", "15"] + }, + "intValue": { + "N": "123" + }, + "stringSet": { + "B": "ZaKWrxJmvTOhcTxXrLD01VEy2ABTX/JpBR75lRl2QWuoy0Ly0Kod0DtscHnEJkO8U79FhumOi9r0C3yYH9iM8A==" + }, + "doubleValue": { + "N": "15" + }, + "version": { + "N": "0" + }, + "*amzn-ddb-map-sig*": { + "B": "8vHkkQ6zSMP846QOJrelmFI/EZA2HmI7TgZUbccE1rI=" + }, + "rangeKey": { + "N": "8" + }, + "stringValue": { + "S": "Hello world!" + }, + "*amzn-ddb-map-desc*": { + "B": "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" + }, + "byteArrayValue": { + "B": "j0oZDI4LcQpD8h6+5/v2iPD2riMsq7WH804sAyr6J94=" + }, + "complexValue": { + "B": "SY5ypLds8Bx6+9nNBfEe7ZkYD2BG8lYNkEngMI14A77hgC3TYJg40LA5gV6jgrXw5K4Z/s5DQCTKjNco+BUT6p4bKmuA3QO1XI00Uddgq+Ci9YjQewpYO9P2tUnnGe/1xSa8V+9JFaG2plVTL0H2Js7zDbu5geTok8blhvScXi0=" + } + } + ] +} diff --git a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/scenarios.json b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/scenarios.json index 39cd348968..96ec54746e 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/scenarios.json +++ b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/scenarios.json @@ -378,6 +378,17 @@ "plaintext": "file://plaintext.json", "ciphertext": "file://ciphertext/java/wrapped-rsa-hmac-1.json", "network": false + }, + { + "version": "v2_complex", + "provider": "static", + "keys": { + "decrypt": "aesKey", + "verify": "hmacKey" + }, + "plaintext": "file://plaintext.json", + "ciphertext": "file://ciphertext/java/static-aes-hmac-complex-1.json", + "network": false } ] } 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 7bab27e430..0c37f32b18 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 @@ -11,6 +11,7 @@ import java.lang.reflect.InvocationTargetException; import java.nio.ByteBuffer; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.stream.Collectors; import software.amazon.awssdk.core.SdkBytes; @@ -279,6 +280,10 @@ public static HashMap ActionsFromClass( attributeActionsOnEncrypt.put("version", CryptoAction.SIGN_ONLY); attributeActionsOnEncrypt.put("doubleValue", CryptoAction.SIGN_ONLY); attributeActionsOnEncrypt.put("doubleSet", CryptoAction.SIGN_ONLY); + attributeActionsOnEncrypt.put( + "complexValue", + CryptoAction.ENCRYPT_AND_SIGN + ); } else if (value instanceof SignOnly) { attributeActionsOnEncrypt.put(HASH_KEY, CryptoAction.SIGN_ONLY); attributeActionsOnEncrypt.put(RANGE_KEY, CryptoAction.SIGN_ONLY); @@ -290,6 +295,7 @@ public static HashMap ActionsFromClass( attributeActionsOnEncrypt.put("version", CryptoAction.SIGN_ONLY); attributeActionsOnEncrypt.put("doubleValue", CryptoAction.SIGN_ONLY); attributeActionsOnEncrypt.put("doubleSet", CryptoAction.SIGN_ONLY); + attributeActionsOnEncrypt.put("complexValue", CryptoAction.SIGN_ONLY); } else if (value instanceof Untouched) { attributeActionsOnEncrypt.put(HASH_KEY, CryptoAction.SIGN_ONLY); attributeActionsOnEncrypt.put(RANGE_KEY, CryptoAction.SIGN_ONLY); @@ -301,6 +307,7 @@ public static HashMap ActionsFromClass( attributeActionsOnEncrypt.put("version", CryptoAction.DO_NOTHING); attributeActionsOnEncrypt.put("doubleValue", CryptoAction.DO_NOTHING); attributeActionsOnEncrypt.put("doubleSet", CryptoAction.DO_NOTHING); + attributeActionsOnEncrypt.put("complexValue", CryptoAction.DO_NOTHING); } else if (value instanceof BaseClass) { // This is a BaseClass attributeActionsOnEncrypt.put(HASH_KEY, CryptoAction.SIGN_ONLY); @@ -322,6 +329,10 @@ public static HashMap ActionsFromClass( CryptoAction.ENCRYPT_AND_SIGN ); attributeActionsOnEncrypt.put("doubleSet", CryptoAction.ENCRYPT_AND_SIGN); + attributeActionsOnEncrypt.put( + "complexValue", + CryptoAction.ENCRYPT_AND_SIGN + ); } else if (value instanceof KeysOnly) { attributeActionsOnEncrypt.put(HASH_KEY, CryptoAction.SIGN_ONLY); attributeActionsOnEncrypt.put(RANGE_KEY, CryptoAction.SIGN_ONLY); @@ -393,6 +404,26 @@ public static BaseClass attributeMapToBaseClass( .collect(Collectors.toSet()) ); } + if (attributeMap.containsKey("complexValue")) { + List> complex = attributeMap + .get("complexValue") + .l() + .stream() + .map(av -> + av + .m() + .entrySet() + .stream() + .collect( + java.util.stream.Collectors.toMap( + Map.Entry::getKey, + e -> e.getValue().s() + ) + ) + ) + .collect(java.util.stream.Collectors.toList()); + value.setComplexValue(complex); + } return value; } @@ -435,6 +466,18 @@ public static Map baseClassToV1AttrMap( .collect(java.util.stream.Collectors.toList()) ) ); + if (obj.getComplexValue() != null) { + java.util.List listItems = obj + .getComplexValue() + .stream() + .map(m -> { + Map avMap = new HashMap<>(); + m.forEach((k, v) -> avMap.put(k, new AttributeValue().withS(v))); + return new AttributeValue().withM(avMap); + }) + .collect(java.util.stream.Collectors.toList()); + map.put("complexValue", new AttributeValue().withL(listItems)); + } return map; } @@ -531,6 +574,40 @@ > baseClassToAttributeMap(Object TEST_VALUE) { ) .build() ); + if (((BaseClass) TEST_VALUE).getComplexValue() != null) { + java.util.List< + software.amazon.awssdk.services.dynamodb.model.AttributeValue + > listItems = + ((BaseClass) TEST_VALUE).getComplexValue() + .stream() + .map(m -> { + Map< + String, + software.amazon.awssdk.services.dynamodb.model.AttributeValue + > avMap = new HashMap<>(); + m.forEach((k, v) -> + avMap.put( + k, + software.amazon.awssdk.services.dynamodb.model.AttributeValue + .builder() + .s(v) + .build() + ) + ); + return software.amazon.awssdk.services.dynamodb.model.AttributeValue + .builder() + .m(avMap) + .build(); + }) + .collect(java.util.stream.Collectors.toList()); + attributes.put( + "complexValue", + software.amazon.awssdk.services.dynamodb.model.AttributeValue + .builder() + .l(listItems) + .build() + ); + } } else if (TEST_VALUE instanceof KeysOnly) { attributes.put( HASH_KEY, 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 891054fcde..9714a5b1f3 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 @@ -405,6 +405,9 @@ public void decryptTestVector(Scenario scenario) throws IOException { case "v1": assertVersionCompatibility_2(mapper); break; + case "v2_complex": + assertVersionCompatibility_complex(mapper); + break; default: throw new IllegalStateException( "Version " + @@ -507,6 +510,23 @@ public void decryptLegacyTestVector(Scenario scenario) throws IOException { // This is why this vector exists but is not tested. // assertTrue(LegacyTestVectors.testDecryptionTestVector(client, legacyEncryptor, UNTOUCHED_TEST_VALUE_2)); break; + case "v2_complex": + LegacyTestVectors.decryptBaseClassTestVector( + client, + legacyEncryptor, + withComplexValue(ENCRYPTED_TEST_VALUE_2) + ); + LegacyTestVectors.decryptBaseClassTestVector( + client, + legacyEncryptor, + withComplexValue(MIXED_TEST_VALUE_2) + ); + LegacyTestVectors.decryptBaseClassTestVector( + client, + legacyEncryptor, + withComplexValue(SIGNED_TEST_VALUE_2) + ); + break; default: throw new IllegalStateException( "Version " + @@ -515,41 +535,43 @@ public void decryptLegacyTestVector(Scenario scenario) throws IOException { ); } - LegacyTestVectors.decryptHashKeyOnlyTestVector( - client, - legacyEncryptor, - "Foo" - ); - LegacyTestVectors.decryptHashKeyOnlyTestVector( - client, - legacyEncryptor, - "Bar" - ); - LegacyTestVectors.decryptHashKeyOnlyTestVector( - client, - legacyEncryptor, - "Baz" - ); - - for (int x = 1; x <= 3; ++x) { - LegacyTestVectors.decryptKeysOnlyTestVector( + if (!"v2_complex".equals(scenario.version)) { + LegacyTestVectors.decryptHashKeyOnlyTestVector( client, legacyEncryptor, - 0, - x + "Foo" ); - LegacyTestVectors.decryptKeysOnlyTestVector( + LegacyTestVectors.decryptHashKeyOnlyTestVector( client, legacyEncryptor, - 1, - x + "Bar" ); - LegacyTestVectors.decryptKeysOnlyTestVector( + LegacyTestVectors.decryptHashKeyOnlyTestVector( client, legacyEncryptor, - 4 + x, - x + "Baz" ); + + for (int x = 1; x <= 3; ++x) { + LegacyTestVectors.decryptKeysOnlyTestVector( + client, + legacyEncryptor, + 0, + x + ); + LegacyTestVectors.decryptKeysOnlyTestVector( + client, + legacyEncryptor, + 1, + x + ); + LegacyTestVectors.decryptKeysOnlyTestVector( + client, + legacyEncryptor, + 4 + x, + x + ); + } } } @@ -1159,6 +1181,77 @@ private void assertVersionCompatibility_2(DynamoDBMapper mapper) { } } + private static final List> COMPLEX_VALUE = + java.util.Arrays.asList( + new java.util.HashMap() { + { + put("innerKey", "innerVal"); + put("innerNum", "42"); + } + }, + new java.util.HashMap() { + { + put("nestedKey", "nestedVal"); + } + } + ); + + @SuppressWarnings("unchecked") + private static T withComplexValue(T source) { + try { + T copy = (T) source.getClass().getDeclaredConstructor().newInstance(); + copy.setHashKey(source.getHashKey()); + copy.setRangeKey(source.getRangeKey()); + copy.setVersion(source.getVersion()); + copy.setIntValue(source.getIntValue()); + copy.setStringValue(source.getStringValue()); + copy.setByteArrayValue(source.getByteArrayValue()); + copy.setStringSet(source.getStringSet()); + copy.setIntSet(source.getIntSet()); + copy.setDoubleValue(source.getDoubleValue()); + copy.setDoubleSet(source.getDoubleSet()); + copy.setComplexValue(COMPLEX_VALUE); + return copy; + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + private void assertVersionCompatibility_complex(DynamoDBMapper mapper) { + assertEquals( + withComplexValue(UNTOUCHED_TEST_VALUE_2), + mapper.load( + UNTOUCHED_TEST_VALUE_2.getClass(), + UNTOUCHED_TEST_VALUE_2.getHashKey(), + UNTOUCHED_TEST_VALUE_2.getRangeKey() + ) + ); + assertEquals( + withComplexValue(SIGNED_TEST_VALUE_2), + mapper.load( + SIGNED_TEST_VALUE_2.getClass(), + SIGNED_TEST_VALUE_2.getHashKey(), + SIGNED_TEST_VALUE_2.getRangeKey() + ) + ); + assertEquals( + withComplexValue(MIXED_TEST_VALUE_2), + mapper.load( + MIXED_TEST_VALUE_2.getClass(), + MIXED_TEST_VALUE_2.getHashKey(), + MIXED_TEST_VALUE_2.getRangeKey() + ) + ); + assertEquals( + withComplexValue(ENCRYPTED_TEST_VALUE_2), + mapper.load( + ENCRYPTED_TEST_VALUE_2.getClass(), + ENCRYPTED_TEST_VALUE_2.getHashKey(), + ENCRYPTED_TEST_VALUE_2.getRangeKey() + ) + ); + } + // Prints all current tables in the expected test vector format. // You may need to edit the output to grab the tables you care about, or // separate the tables into separate files for test vectors (metastores e.g.). 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 87598548f5..17f5c7e2b3 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 @@ -648,6 +648,9 @@ public void decryptTestVector(Scenario scenario) case "v1": assertVersionCompatibility_2(provider, tableName); break; + case "v2_complex": + assertVersionCompatibility_complex(provider, tableName); + break; default: throw new IllegalStateException( "Version " + @@ -706,9 +709,17 @@ public void encryptWithTestVector(Scenario scenario) throws IOException { metastore, scenario.materialDescription ); - Set tables = generateStandardData(provider); + Set tables; + if ("v2_complex".equals(scenario.version)) { + tables = generateComplexData(provider); + } else { + tables = generateStandardData(provider); + } - if (saveToJson && "v1".equals(scenario.version)) { + if ( + saveToJson && + ("v1".equals(scenario.version) || "v2_complex".equals(scenario.version)) + ) { String outputFile = java.nio.file.Paths .get(scenario.ciphertextPath.replace("file://", "")) .getFileName() @@ -1209,6 +1220,100 @@ public Set generateStandardData(EncryptionMaterialsProvider prov) { return tables; } + public Set generateComplexData(EncryptionMaterialsProvider prov) { + Set tables = new LinkedHashSet<>(); + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(prov); + EncryptionContext encryptionContext = EncryptionContext + .builder() + .tableName(tableName) + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); + + Map innerMap1 = new HashMap<>(); + innerMap1.put("innerKey", AttributeValue.builder().s("innerVal").build()); + innerMap1.put("innerNum", AttributeValue.builder().s("42").build()); + Map innerMap2 = new HashMap<>(); + innerMap2.put("nestedKey", AttributeValue.builder().s("nestedVal").build()); + AttributeValue complexAttr = AttributeValue + .builder() + .l( + AttributeValue.builder().m(innerMap1).build(), + AttributeValue.builder().m(innerMap2).build() + ) + .build(); + + Map item; + Map> actions; + + // encrypted + item = new HashMap<>(ENCRYPTED_TEST_VALUE_2); + item.put("complexValue", complexAttr); + actions = new HashMap<>(); + for (String attr : item.keySet()) { + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, signOnly); + break; + default: + actions.put(attr, encryptAndSign); + break; + } + } + tables.add(tableName); + putItems( + encryptor.encryptRecord(item, actions, encryptionContext), + tableName + ); + + // mixed + item = new HashMap<>(MIXED_TEST_VALUE_2); + item.put("complexValue", complexAttr); + actions = new HashMap<>(); + for (String attr : item.keySet()) { + switch (attr) { + case "rangeKey": + case "hashKey": + case "version": + case "stringValue": + case "doubleValue": + case "doubleSet": + actions.put(attr, signOnly); + break; + case "intValue": + break; + default: + actions.put(attr, encryptAndSign); + break; + } + } + putItems( + encryptor.encryptRecord(item, actions, encryptionContext), + tableName + ); + + // signed + item = new HashMap<>(SIGNED_TEST_VALUE_2); + item.put("complexValue", complexAttr); + actions = new HashMap<>(); + for (String attr : item.keySet()) { + actions.put(attr, signOnly); + } + putItems( + encryptor.encryptRecord(item, actions, encryptionContext), + tableName + ); + + // untouched + item = new HashMap<>(UNTOUCHED_TEST_VALUE_2); + item.put("complexValue", complexAttr); + putItems(item, tableName); + + return tables; + } + protected void putItems(Map map, String tableName) { PutItemRequest request = PutItemRequest .builder() @@ -1529,10 +1634,227 @@ assert new DdbRecordMatcher(UNTOUCHED_TEST_VALUE_2, false) } } + private void assertVersionCompatibility_complex( + EncryptionMaterialsProvider provider, + String tableName + ) throws java.security.GeneralSecurityException { + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(provider); + EncryptionContext encryptionContext = EncryptionContext + .builder() + .tableName(tableName) + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); + + Map innerMap1 = new HashMap<>(); + innerMap1.put("innerKey", AttributeValue.builder().s("innerVal").build()); + innerMap1.put("innerNum", AttributeValue.builder().s("42").build()); + Map innerMap2 = new HashMap<>(); + innerMap2.put("nestedKey", AttributeValue.builder().s("nestedVal").build()); + AttributeValue complexAttr = AttributeValue + .builder() + .l( + AttributeValue.builder().m(innerMap1).build(), + AttributeValue.builder().m(innerMap2).build() + ) + .build(); + + Map expectedEncrypted = new HashMap<>( + ENCRYPTED_TEST_VALUE_2 + ); + expectedEncrypted.put("complexValue", complexAttr); + Map expectedMixed = new HashMap<>( + MIXED_TEST_VALUE_2 + ); + expectedMixed.put("complexValue", complexAttr); + Map expectedSigned = new HashMap<>( + SIGNED_TEST_VALUE_2 + ); + expectedSigned.put("complexValue", complexAttr); + Map expectedUntouched = new HashMap<>( + UNTOUCHED_TEST_VALUE_2 + ); + expectedUntouched.put("complexValue", complexAttr); + + // untouched + HashMap key = new HashMap<>(); + key.put("hashKey", expectedUntouched.get("hashKey")); + key.put("rangeKey", expectedUntouched.get("rangeKey")); + assertTrue( + new com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.DdbRecordMatcher( + expectedUntouched, + false + ) + .matches(getItems(key, tableName)) + ); + + // signed + key = new HashMap<>(); + key.put("hashKey", expectedSigned.get("hashKey")); + key.put("rangeKey", expectedSigned.get("rangeKey")); + Map> actions = new HashMap<>(); + for (String attr : expectedSigned.keySet()) { + actions.put(attr, signOnly); + } + assertTrue( + new com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.DdbRecordMatcher( + expectedSigned, + false + ) + .matches( + encryptor.decryptRecord( + getItems(key, tableName), + actions, + encryptionContext + ) + ) + ); + + // mixed + key = new HashMap<>(); + key.put("hashKey", expectedMixed.get("hashKey")); + key.put("rangeKey", expectedMixed.get("rangeKey")); + actions = new HashMap<>(); + for (String attr : expectedMixed.keySet()) { + switch (attr) { + case "rangeKey": + case "hashKey": + case "version": + case "stringValue": + case "doubleValue": + case "doubleSet": + actions.put(attr, signOnly); + break; + case "intValue": + break; + default: + actions.put(attr, encryptAndSign); + break; + } + } + assertTrue( + new com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.DdbRecordMatcher( + expectedMixed, + false + ) + .matches( + encryptor.decryptRecord( + getItems(key, tableName), + actions, + encryptionContext + ) + ) + ); + + // encrypted + key = new HashMap<>(); + key.put("hashKey", expectedEncrypted.get("hashKey")); + key.put("rangeKey", expectedEncrypted.get("rangeKey")); + actions = new HashMap<>(); + for (String attr : expectedEncrypted.keySet()) { + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, signOnly); + break; + default: + actions.put(attr, encryptAndSign); + break; + } + } + assertTrue( + new com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.DdbRecordMatcher( + expectedEncrypted, + false + ) + .matches( + encryptor.decryptRecord( + getItems(key, tableName), + actions, + encryptionContext + ) + ) + ); + } + private static String stripFilePath(String path) { return path.replaceFirst("file://", ""); } + @Test + public void complexValueRoundTrip() + throws java.security.GeneralSecurityException { + localDynamoDb.start(); + client = localDynamoDb.createLimitedWrappedClient(); + createCiphertextTables(client); + + DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); + EncryptionContext encryptionContext = EncryptionContext + .builder() + .tableName(tableName) + .hashKeyName("hashKey") + .rangeKeyName("rangeKey") + .build(); + + // Build item with nested complex value: List[ Map{S,S}, Map{S} ] + Map item = new HashMap<>(ENCRYPTED_TEST_VALUE_2); + Map innerMap1 = new HashMap<>(); + innerMap1.put("innerKey", AttributeValue.builder().s("innerVal").build()); + innerMap1.put("innerNum", AttributeValue.builder().s("42").build()); + Map innerMap2 = new HashMap<>(); + innerMap2.put("nestedKey", AttributeValue.builder().s("nestedVal").build()); + item.put( + "complexValue", + AttributeValue + .builder() + .l( + AttributeValue.builder().m(innerMap1).build(), + AttributeValue.builder().m(innerMap2).build() + ) + .build() + ); + + // Encrypt + Map> actions = new HashMap<>(); + for (String attr : item.keySet()) { + switch (attr) { + case "hashKey": + case "rangeKey": + case "version": + actions.put(attr, signOnly); + break; + default: + actions.put(attr, encryptAndSign); + break; + } + } + Map encrypted = encryptor.encryptRecord( + item, + actions, + encryptionContext + ); + + // Decrypt + Map decrypted = encryptor.decryptRecord( + encrypted, + actions, + encryptionContext + ); + + // Verify round-trip + assertTrue( + new com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.DdbRecordMatcher( + item, + false + ) + .matches(decrypted) + ); + + client.close(); + localDynamoDb.stop(); + } + @JsonDeserialize(using = AttributeValueDeserializer.class) public abstract static class DeserializedAttributeValue implements AttributeValue.Builder {} From 00ee5951e7e55809078bc51893d648ea5a740b0f Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sat, 28 Mar 2026 15:08:26 -0700 Subject: [PATCH 02/18] m --- .../dynamodbv2/testing/types/BaseClass.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/types/BaseClass.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/types/BaseClass.java index e42e3c886d..41da3c3e02 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/types/BaseClass.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/types/BaseClass.java @@ -19,6 +19,8 @@ import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBVersionAttribute; import java.util.Arrays; +import java.util.List; +import java.util.Map; import java.util.Set; @DynamoDBTable(tableName = "TableName") @@ -38,6 +40,8 @@ public int hashCode() { prime * result + ((stringValue == null) ? 0 : stringValue.hashCode()); result = prime * result + Double.valueOf(doubleValue).hashCode(); result = prime * result + ((doubleSet == null) ? 0 : doubleSet.hashCode()); + result = + prime * result + ((complexValue == null) ? 0 : complexValue.hashCode()); return result; } @@ -63,6 +67,9 @@ public boolean equals(Object obj) { if (doubleSet == null) { if (other.doubleSet != null) return false; } else if (!doubleSet.equals(other.doubleSet)) return false; + if (complexValue == null) { + if (other.complexValue != null) return false; + } else if (!complexValue.equals(other.complexValue)) return false; return true; } @@ -76,6 +83,7 @@ public boolean equals(Object obj) { private Integer version; private double doubleValue; private Set doubleSet; + private List> complexValue; @DynamoDBHashKey public int getHashKey() { @@ -143,6 +151,14 @@ public void setDoubleSet(Set doubleSet) { this.doubleSet = doubleSet; } + public List> getComplexValue() { + return complexValue; + } + + public void setComplexValue(List> complexValue) { + this.complexValue = complexValue; + } + public double getDoubleValue() { return doubleValue; } @@ -181,6 +197,8 @@ public String toString() { doubleValue + ", doubleSet=" + doubleSet + + ", complexValue=" + + complexValue + ", version=" + version + "]" From a3b0d6d96109f51194f18bec030c24cba97b5f2f Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sat, 28 Mar 2026 15:08:53 -0700 Subject: [PATCH 03/18] m --- .../testing/AttributeValueDeserializer.java | 25 +++++++++++++++++++ .../testing/AttributeValueMatcher.java | 20 +++++++++++++++ .../testing/AttributeValueSerializer.java | 17 +++++++++++++ 3 files changed, 62 insertions(+) diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/AttributeValueDeserializer.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/AttributeValueDeserializer.java index 89021f3002..12954e5e57 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/AttributeValueDeserializer.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/AttributeValueDeserializer.java @@ -57,6 +57,31 @@ public AttributeValue deserialize(JsonParser jp, DeserializationContext ctxt) new TypeReference>() {} ); return new AttributeValue().withNS(numSet); + case "L": + java.util.List listItems = + new java.util.ArrayList<>(); + for (JsonNode element : value) { + JsonParser elemParser = objectMapper.treeAsTokens(element); + elemParser.nextToken(); + listItems.add(deserialize(elemParser, ctxt)); + } + return new AttributeValue().withL(listItems); + case "M": + java.util.Map mapItems = + new java.util.LinkedHashMap<>(); + for ( + java.util.Iterator> mapIter = + value.fields(); + mapIter.hasNext(); + ) { + java.util.Map.Entry entry = mapIter.next(); + JsonParser entryParser = objectMapper.treeAsTokens( + entry.getValue() + ); + entryParser.nextToken(); + mapItems.put(entry.getKey(), deserialize(entryParser, ctxt)); + } + return new AttributeValue().withM(mapItems); default: throw new IllegalStateException( "DDB JSON type " + diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/AttributeValueMatcher.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/AttributeValueMatcher.java index f09c693392..5b8387cd51 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/AttributeValueMatcher.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/AttributeValueMatcher.java @@ -18,6 +18,8 @@ import java.math.BigDecimal; import java.util.Collection; import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Set; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; @@ -60,6 +62,24 @@ public static boolean attrEquals(AttributeValue e, AttributeValue a) { ) { return false; } + List eL = e.getL(); + List aL = a.getL(); + if ((eL == null) != (aL == null)) return false; + if (eL != null) { + if (eL.size() != aL.size()) return false; + for (int i = 0; i < eL.size(); i++) { + if (!attrEquals(eL.get(i), aL.get(i))) return false; + } + } + Map eM = e.getM(); + Map aM = a.getM(); + if ((eM == null) != (aM == null)) return false; + if (eM != null) { + if (!eM.keySet().equals(aM.keySet())) return false; + for (String key : eM.keySet()) { + if (!attrEquals(eM.get(key), aM.get(key))) return false; + } + } return true; } diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/AttributeValueSerializer.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/AttributeValueSerializer.java index 922380ffaa..256f2beb1a 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/AttributeValueSerializer.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/AttributeValueSerializer.java @@ -41,6 +41,23 @@ public void serialize( jgen.writeString(num); } jgen.writeEndArray(); + } else if (value.getL() != null && !value.getL().isEmpty()) { + jgen.writeFieldName("L"); + jgen.writeStartArray(); + for (AttributeValue item : value.getL()) { + serialize(item, jgen, provider); + } + jgen.writeEndArray(); + } else if (value.getM() != null && !value.getM().isEmpty()) { + jgen.writeFieldName("M"); + jgen.writeStartObject(); + for (java.util.Map.Entry entry : value + .getM() + .entrySet()) { + jgen.writeFieldName(entry.getKey()); + serialize(entry.getValue(), jgen, provider); + } + jgen.writeEndObject(); } else { throw new IllegalStateException( "AttributeValue has no value or type not implemented for serialization." From 0f87e403f7afb1c5759438977594770689c09d69 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sat, 28 Mar 2026 15:27:29 -0700 Subject: [PATCH 04/18] m --- .../testing/AttributeValueDeserializer.java | 25 +++++++++++++++++++ .../sdkv2/testing/AttributeValueMatcher.java | 20 +++++++++++++++ .../testing/AttributeValueSerializer.java | 17 +++++++++++++ 3 files changed, 62 insertions(+) diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/testing/AttributeValueDeserializer.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/testing/AttributeValueDeserializer.java index d197ce324d..8b9612818a 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/testing/AttributeValueDeserializer.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/testing/AttributeValueDeserializer.java @@ -57,6 +57,31 @@ public AttributeValue deserialize(JsonParser jp, DeserializationContext ctxt) new TypeReference>() {} ); return AttributeValue.builder().ns(numSet).build(); + case "L": + java.util.List listItems = + new java.util.ArrayList<>(); + for (JsonNode element : value) { + JsonParser elemParser = objectMapper.treeAsTokens(element); + elemParser.nextToken(); + listItems.add(deserialize(elemParser, ctxt)); + } + return AttributeValue.builder().l(listItems).build(); + case "M": + java.util.Map mapItems = + new java.util.LinkedHashMap<>(); + for ( + java.util.Iterator> mapIter = + value.fields(); + mapIter.hasNext(); + ) { + java.util.Map.Entry entry = mapIter.next(); + JsonParser entryParser = objectMapper.treeAsTokens( + entry.getValue() + ); + entryParser.nextToken(); + mapItems.put(entry.getKey(), deserialize(entryParser, ctxt)); + } + return AttributeValue.builder().m(mapItems).build(); default: throw new IllegalStateException( "DDB JSON type " + diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/testing/AttributeValueMatcher.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/testing/AttributeValueMatcher.java index 45723325ac..c9b5257370 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/testing/AttributeValueMatcher.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/testing/AttributeValueMatcher.java @@ -3,6 +3,8 @@ import java.math.BigDecimal; import java.util.Collection; import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Set; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; @@ -46,6 +48,24 @@ public static boolean attrEquals(AttributeValue e, AttributeValue a) { ) { return false; } + if (e.hasL() != a.hasL()) return false; + if (e.hasL()) { + List eL = e.l(); + List aL = a.l(); + if (eL.size() != aL.size()) return false; + for (int i = 0; i < eL.size(); i++) { + if (!attrEquals(eL.get(i), aL.get(i))) return false; + } + } + if (e.hasM() != a.hasM()) return false; + if (e.hasM()) { + Map eM = e.m(); + Map aM = a.m(); + if (!eM.keySet().equals(aM.keySet())) return false; + for (String key : eM.keySet()) { + if (!attrEquals(eM.get(key), aM.get(key))) return false; + } + } return true; } diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/testing/AttributeValueSerializer.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/testing/AttributeValueSerializer.java index 7c108422a8..fd9a8c3011 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/testing/AttributeValueSerializer.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv2/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/testing/AttributeValueSerializer.java @@ -40,6 +40,23 @@ public void serialize( jgen.writeString(num); } jgen.writeEndArray(); + } else if (value.hasL()) { + jgen.writeFieldName("L"); + jgen.writeStartArray(); + for (AttributeValue item : value.l()) { + serialize(item, jgen, provider); + } + jgen.writeEndArray(); + } else if (value.hasM()) { + jgen.writeFieldName("M"); + jgen.writeStartObject(); + for (java.util.Map.Entry entry : value + .m() + .entrySet()) { + jgen.writeFieldName(entry.getKey()); + serialize(entry.getValue(), jgen, provider); + } + jgen.writeEndObject(); } else { throw new IllegalStateException( "AttributeValue has no value or type not implemented for serialization." From 3ddda30d454a576fa7ca90651d6b7386171e08e3 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sat, 28 Mar 2026 17:09:40 -0700 Subject: [PATCH 05/18] m --- .../datamodeling/sdkv2/HolisticIT.java | 73 ------------------- 1 file changed, 73 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 17f5c7e2b3..784defb9c1 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 @@ -1782,79 +1782,6 @@ private static String stripFilePath(String path) { return path.replaceFirst("file://", ""); } - @Test - public void complexValueRoundTrip() - throws java.security.GeneralSecurityException { - localDynamoDb.start(); - client = localDynamoDb.createLimitedWrappedClient(); - createCiphertextTables(client); - - DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(symProv); - EncryptionContext encryptionContext = EncryptionContext - .builder() - .tableName(tableName) - .hashKeyName("hashKey") - .rangeKeyName("rangeKey") - .build(); - - // Build item with nested complex value: List[ Map{S,S}, Map{S} ] - Map item = new HashMap<>(ENCRYPTED_TEST_VALUE_2); - Map innerMap1 = new HashMap<>(); - innerMap1.put("innerKey", AttributeValue.builder().s("innerVal").build()); - innerMap1.put("innerNum", AttributeValue.builder().s("42").build()); - Map innerMap2 = new HashMap<>(); - innerMap2.put("nestedKey", AttributeValue.builder().s("nestedVal").build()); - item.put( - "complexValue", - AttributeValue - .builder() - .l( - AttributeValue.builder().m(innerMap1).build(), - AttributeValue.builder().m(innerMap2).build() - ) - .build() - ); - - // Encrypt - Map> actions = new HashMap<>(); - for (String attr : item.keySet()) { - switch (attr) { - case "hashKey": - case "rangeKey": - case "version": - actions.put(attr, signOnly); - break; - default: - actions.put(attr, encryptAndSign); - break; - } - } - Map encrypted = encryptor.encryptRecord( - item, - actions, - encryptionContext - ); - - // Decrypt - Map decrypted = encryptor.decryptRecord( - encrypted, - actions, - encryptionContext - ); - - // Verify round-trip - assertTrue( - new com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.testing.DdbRecordMatcher( - item, - false - ) - .matches(decrypted) - ); - - client.close(); - localDynamoDb.stop(); - } - @JsonDeserialize(using = AttributeValueDeserializer.class) public abstract static class DeserializedAttributeValue implements AttributeValue.Builder {} From f4613e3e26ba9ae2395ad0785458a3240947de52 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sat, 28 Mar 2026 18:00:05 -0700 Subject: [PATCH 06/18] m --- .../services/dynamodbv2/datamodeling/sdkv2/HolisticIT.java | 2 ++ 1 file changed, 2 insertions(+) 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 784defb9c1..fe1bb5d1a1 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 @@ -1233,6 +1233,7 @@ public Set generateComplexData(EncryptionMaterialsProvider prov) { Map innerMap1 = new HashMap<>(); innerMap1.put("innerKey", AttributeValue.builder().s("innerVal").build()); innerMap1.put("innerNum", AttributeValue.builder().s("42").build()); + innerMap1.put("tags", AttributeValue.builder().ss("banana", "apple", "cherry").build()); Map innerMap2 = new HashMap<>(); innerMap2.put("nestedKey", AttributeValue.builder().s("nestedVal").build()); AttributeValue complexAttr = AttributeValue @@ -1649,6 +1650,7 @@ private void assertVersionCompatibility_complex( Map innerMap1 = new HashMap<>(); innerMap1.put("innerKey", AttributeValue.builder().s("innerVal").build()); innerMap1.put("innerNum", AttributeValue.builder().s("42").build()); + innerMap1.put("tags", AttributeValue.builder().ss("banana", "apple", "cherry").build()); Map innerMap2 = new HashMap<>(); innerMap2.put("nestedKey", AttributeValue.builder().s("nestedVal").build()); AttributeValue complexAttr = AttributeValue From 4f4579832a14353fdb172301e276b87f44087e50 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sat, 28 Mar 2026 18:07:16 -0700 Subject: [PATCH 07/18] m --- .../java/static-aes-hmac-complex-1.json | 379 +++++++++--------- 1 file changed, 187 insertions(+), 192 deletions(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json index 3417a5535a..40ecad72de 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json +++ b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json @@ -1,198 +1,193 @@ { - "TableName": [ - { - "hashKey": { - "N": "5" - }, - "intSet": { - "B": "8opVq3jaEQzMyl/IpUpPSMT4/ZBCWM99xKZbHLUgOAC9VQy6s8ALz31nouDRdHsO3di+gK+lc5KyZ3Xnswy8ug==" - }, - "doubleSet": { - "B": "pj0Z9DVUZwaWRZAc5VDRqLuCVnaPIWrwRD0o8ov92rjMUh/x5dRq9x6wUJvFQk3b5OHpiaV9h37Szww6ZznvOg==" - }, - "intValue": { - "B": "9Ykw7qNiJnxRFq4Qv3FULrcAH/zjgxwUnk6TCTmpRo0=" - }, - "stringSet": { - "B": "BGF4UgtpuxecA4ekUfdrSTi5780EjKnK27p3xKRwCNHqKabD6qts86KKKWfudISZ0EHRU9rqYDt4Worz7krguA==" - }, - "doubleValue": { - "B": "mjlEbixV4CXTu69osmacBk1fpsDZu5T33gHKSnblq2o=" - }, - "version": { - "N": "0" - }, - "*amzn-ddb-map-sig*": { - "B": "sU5hyFsSyqRN0Xo8gHXPw5xMU4RPOR8AgFefsFSCmEE=" - }, - "rangeKey": { - "N": "7" - }, - "stringValue": { - "B": "+sY4HCjSWlPQBpjyhdLPQm3a+qgMzba7dS9Cr+jXKS/iGgebu6n6H95D4AGfNEyu" - }, - "*amzn-ddb-map-desc*": { - "B": "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" - }, - "byteArrayValue": { - "B": "4ofQ7VKBlFWO+VZb1LIQQsDvmkeh6W82MFs2JKP0XCs=" - }, - "complexValue": { - "B": "Eh8eXrxBUCZ4x/QR9Ub7l0inMcHHL5GhgDFUuc64+Fk196zzebXFyr1yHE/Yfr57jstYIPS1XXOtGHaa6TCFh+hQQOijcLxkxKyeRboev2vCOoPF3Og9SMwRcZvlchxePJsHeIBTc0KlKHD1nZ4sSEmDdxmy7E9mZgcgHELYwoA=" - } - }, - { - "hashKey": { - "N": "8" - }, - "intSet": { - "NS": ["0", "1", "10", "15", "200"] - }, - "doubleSet": { - "NS": ["-34.2", "-3", "0", "7.6", "15"] - }, - "intValue": { - "N": "123" - }, - "stringSet": { - "SS": ["?", "Cruel", "Goodbye", "World"] - }, - "doubleValue": { - "N": "15" - }, - "version": { - "N": "0" - }, - "*amzn-ddb-map-sig*": { - "B": "n7z2izd+rfq/3BGoqRRgobOwZ3zHEkYZwWdnDpG7CNw=" - }, - "rangeKey": { - "N": "10" - }, - "stringValue": { - "S": "Hello world!" - }, - "*amzn-ddb-map-desc*": { - "B": "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" - }, - "byteArrayValue": { - "B": "AAECAwQF" - }, - "complexValue": { - "L": [ - { - "M": { - "innerNum": { - "S": "42" - }, - "innerKey": { - "S": "innerVal" - } - } + "TableName" : [ { + "hashKey" : { + "N" : "5" + }, + "intSet" : { + "B" : "Qesn5KxFtPllX9jqJXInCZxDt7S2VBqA26BKEGTb/jbme0N+HVSMlo8kzY2GBXL391YAZ2imNcsd09kooWoiSA==" + }, + "doubleSet" : { + "B" : "IAkDbQWnXqfJuxwz82hECh36x1kCd3cJZQo+4nH3Bi1QMkJYiOkabP4kW9kyDAoNjYLMJA19kayYqoF+bh+kDw==" + }, + "intValue" : { + "B" : "XPNIlReAlBIdbyEOndVjAfU2cnFFBowizsRdcBFzVyw=" + }, + "stringSet" : { + "B" : "Xp6Zg2URo0ypLZs3t1PFVZghfZEUlWk/VrkjbMp8rH8fdcub1AmbmPrlzk+T+UdxwNLbYFoZSX2GmpVl+A6cgw==" + }, + "doubleValue" : { + "B" : "wCV+5dqJ6ZLLiTqhUi7nYVAiIPQxx/zTbSfkDJGZanA=" + }, + "version" : { + "N" : "0" + }, + "*amzn-ddb-map-sig*" : { + "B" : "WvJmJp7OX3G+xB9u1mkhBVz5BVKtnfmWc1zL3qRTQzw=" + }, + "rangeKey" : { + "N" : "7" + }, + "stringValue" : { + "B" : "+Y/eTwtN1xakZCH8+7oH5VADROISOudAe6ieWhjXtsuvnDpDemUtq/T7F0q5G9np" + }, + "*amzn-ddb-map-desc*" : { + "B" : "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" + }, + "byteArrayValue" : { + "B" : "g59ZhiTxe8r8R2SwlvBFGFPoDgIlqgJuyVrGOq8iVo0=" + }, + "complexValue" : { + "B" : "826Hs6VEYM7W3Eu1eqIik06gkwCZyMxUKunm09dbiQKJRjodb0t5IUcwc2gxTj9juj0e4CO7r5i7ADspWHGZfvL9MEcnkkURP73baU6LTzdCMbWFn8qJfDooP8VmYYFEhfFqH1lUtJS4IoEZXqauTWMZgjfgSPZ3ULW5Xhtm/eGAlVG+jcXMcqIxKBinnxdi8680Rj0VJySrgOecvKINcA==" + } + }, { + "hashKey" : { + "N" : "8" + }, + "intSet" : { + "NS" : [ "0", "1", "10", "15", "200" ] + }, + "doubleSet" : { + "NS" : [ "-34.2", "-3", "0", "7.6", "15" ] + }, + "intValue" : { + "N" : "123" + }, + "stringSet" : { + "SS" : [ "?", "Cruel", "Goodbye", "World" ] + }, + "doubleValue" : { + "N" : "15" + }, + "version" : { + "N" : "0" + }, + "*amzn-ddb-map-sig*" : { + "B" : "Ae3akfxslcXmwxoAFJwumhzwBVdnzc7oFNhoW1tz0qo=" + }, + "rangeKey" : { + "N" : "10" + }, + "stringValue" : { + "S" : "Hello world!" + }, + "*amzn-ddb-map-desc*" : { + "B" : "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" + }, + "byteArrayValue" : { + "B" : "AAECAwQF" + }, + "complexValue" : { + "L" : [ { + "M" : { + "innerNum" : { + "S" : "42" + }, + "innerKey" : { + "S" : "innerVal" }, - { - "M": { - "nestedKey": { - "S": "nestedVal" - } - } + "tags" : { + "SS" : [ "apple", "banana", "cherry" ] + } + } + }, { + "M" : { + "nestedKey" : { + "S" : "nestedVal" } - ] - } - }, - { - "rangeKey": { - "N": "9" - }, - "hashKey": { - "N": "7" - }, - "stringValue": { - "S": "Hello world!" - }, - "intSet": { - "NS": ["0", "1", "10", "15", "200"] - }, - "doubleSet": { - "NS": ["-34.2", "-3", "0", "7.6", "15"] - }, - "byteArrayValue": { - "B": "AAECAwQF" - }, - "complexValue": { - "L": [ - { - "M": { - "innerNum": { - "S": "42" - }, - "innerKey": { - "S": "innerVal" - } - } + } + } ] + } + }, { + "rangeKey" : { + "N" : "9" + }, + "hashKey" : { + "N" : "7" + }, + "stringValue" : { + "S" : "Hello world!" + }, + "intSet" : { + "NS" : [ "0", "1", "10", "15", "200" ] + }, + "doubleSet" : { + "NS" : [ "-34.2", "-3", "0", "7.6", "15" ] + }, + "byteArrayValue" : { + "B" : "AAECAwQF" + }, + "complexValue" : { + "L" : [ { + "M" : { + "innerNum" : { + "S" : "42" }, - { - "M": { - "nestedKey": { - "S": "nestedVal" - } - } + "innerKey" : { + "S" : "innerVal" + }, + "tags" : { + "SS" : [ "apple", "banana", "cherry" ] + } + } + }, { + "M" : { + "nestedKey" : { + "S" : "nestedVal" } - ] - }, - "intValue": { - "N": "123" - }, - "stringSet": { - "SS": ["?", "Cruel", "Goodbye", "World"] - }, - "doubleValue": { - "N": "15" - }, - "version": { - "N": "0" - } - }, - { - "hashKey": { - "N": "6" - }, - "intSet": { - "B": "GQqk1bZLTkSwzf/v95GBpxKVjQFNs/PDeRY8eltfzDVFs1HRhNwP6A9VobvR+rv7aCwhIzXWRepkTPoibalm7w==" - }, - "doubleSet": { - "NS": ["-34.2", "-3", "0", "7.6", "15"] - }, - "intValue": { - "N": "123" - }, - "stringSet": { - "B": "ZaKWrxJmvTOhcTxXrLD01VEy2ABTX/JpBR75lRl2QWuoy0Ly0Kod0DtscHnEJkO8U79FhumOi9r0C3yYH9iM8A==" - }, - "doubleValue": { - "N": "15" - }, - "version": { - "N": "0" - }, - "*amzn-ddb-map-sig*": { - "B": "8vHkkQ6zSMP846QOJrelmFI/EZA2HmI7TgZUbccE1rI=" - }, - "rangeKey": { - "N": "8" - }, - "stringValue": { - "S": "Hello world!" - }, - "*amzn-ddb-map-desc*": { - "B": "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" - }, - "byteArrayValue": { - "B": "j0oZDI4LcQpD8h6+5/v2iPD2riMsq7WH804sAyr6J94=" - }, - "complexValue": { - "B": "SY5ypLds8Bx6+9nNBfEe7ZkYD2BG8lYNkEngMI14A77hgC3TYJg40LA5gV6jgrXw5K4Z/s5DQCTKjNco+BUT6p4bKmuA3QO1XI00Uddgq+Ci9YjQewpYO9P2tUnnGe/1xSa8V+9JFaG2plVTL0H2Js7zDbu5geTok8blhvScXi0=" - } + } + } ] + }, + "intValue" : { + "N" : "123" + }, + "stringSet" : { + "SS" : [ "?", "Cruel", "Goodbye", "World" ] + }, + "doubleValue" : { + "N" : "15" + }, + "version" : { + "N" : "0" + } + }, { + "hashKey" : { + "N" : "6" + }, + "intSet" : { + "B" : "x19+XHMiU3Mzrfo8iKEixyMuSK+M8pYs9uBolbcgsWxJpr0t0DfXi8Lbs0r7UOkOTcpeblpIBLYhwoN4kECX/A==" + }, + "doubleSet" : { + "NS" : [ "-34.2", "-3", "0", "7.6", "15" ] + }, + "intValue" : { + "N" : "123" + }, + "stringSet" : { + "B" : "OBCSZ/RaT2pEJYnO4eNxTBXaMcf3N6L8J20Y3Qst2R7BQYx4l3DFZ9pbZJ44pxBJvtsZltTUlYyTqMzk2AFmVA==" + }, + "doubleValue" : { + "N" : "15" + }, + "version" : { + "N" : "0" + }, + "*amzn-ddb-map-sig*" : { + "B" : "YcHz06gurNPDMQonlzVP/dOj4Tj8gyzEPRqG7s7TpT0=" + }, + "rangeKey" : { + "N" : "8" + }, + "stringValue" : { + "S" : "Hello world!" + }, + "*amzn-ddb-map-desc*" : { + "B" : "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" + }, + "byteArrayValue" : { + "B" : "Gbs6G5YIuDt6Vdrfc9Z3aTaK665ocagA92qds1NrNVE=" + }, + "complexValue" : { + "B" : "QeuExksSrD4/VwW6ynLrmk/zy2IV3qTWW4/lsmjw89Y60T7Yf3/c2Zz7jXqaTRkaFyGAnBWQjo/5gQ7kLumA+LysicFFQ2bLfq11P60n+YBYkejOC022IYw/qNQPLtKN7O6ZQzWHSPSoSq6StFZsuGTIaZUCyeEDOq9vIDZAl/OzsRkmvoY3FKveoxd7qRb1wyunzQKRc065VhcrGZgcCQ==" } - ] -} + } ] +} \ No newline at end of file From d612c3ddc33dcd89aa9538d21269cee8ded0f9d2 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sat, 28 Mar 2026 22:48:17 -0700 Subject: [PATCH 08/18] m --- .../java/static-aes-hmac-complex-1.json | 54 ++++----------- .../datamodeling/LegacyTestVectors.java | 68 +++++-------------- .../datamodeling/TransformerHolisticIT.java | 18 ++--- .../dynamodbv2/testing/types/BaseClass.java | 6 +- .../datamodeling/sdkv2/HolisticIT.java | 28 ++------ 5 files changed, 48 insertions(+), 126 deletions(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json index 40ecad72de..e88dbb2f09 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json +++ b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json @@ -4,40 +4,40 @@ "N" : "5" }, "intSet" : { - "B" : "Qesn5KxFtPllX9jqJXInCZxDt7S2VBqA26BKEGTb/jbme0N+HVSMlo8kzY2GBXL391YAZ2imNcsd09kooWoiSA==" + "B" : "YT/4WCrk0h3ywpKPCn4cXFOKJeZZcd1m2xFdXPqQs3S/rjoALLdG1pvc2XywQxgpB7a4UKDaL5lGcb2l2BejkA==" }, "doubleSet" : { - "B" : "IAkDbQWnXqfJuxwz82hECh36x1kCd3cJZQo+4nH3Bi1QMkJYiOkabP4kW9kyDAoNjYLMJA19kayYqoF+bh+kDw==" + "B" : "pWx7fEGKniYnXit0LdrpC3j4Cc3VdCMrypFzHyWuHCSLx8wKmw4FFMDdC5oewTL9unfs87qL7k238R7ky4of2g==" }, "intValue" : { - "B" : "XPNIlReAlBIdbyEOndVjAfU2cnFFBowizsRdcBFzVyw=" + "B" : "w9XJYu30P/e9cypdUxLkI/eeX20+skX5zCwuNPWNJuc=" }, "stringSet" : { - "B" : "Xp6Zg2URo0ypLZs3t1PFVZghfZEUlWk/VrkjbMp8rH8fdcub1AmbmPrlzk+T+UdxwNLbYFoZSX2GmpVl+A6cgw==" + "B" : "VmlhLGf+6XEGsGacVb9vGW5eHRKVgGYv1qeJ3ih9tGlSGsUHtgach2Oz4R1srhvYh4a8jKRX4S9P4nePU7xeaA==" }, "doubleValue" : { - "B" : "wCV+5dqJ6ZLLiTqhUi7nYVAiIPQxx/zTbSfkDJGZanA=" + "B" : "YGjpcbIplQCcc8N3WeWgmO9kcqbhA/5hSCz+Ow/HD5g=" }, "version" : { "N" : "0" }, "*amzn-ddb-map-sig*" : { - "B" : "WvJmJp7OX3G+xB9u1mkhBVz5BVKtnfmWc1zL3qRTQzw=" + "B" : "CZwERkVud3QnWDMbn0viTLnrLI8wqkCc/Z4irQWHfNg=" }, "rangeKey" : { "N" : "7" }, "stringValue" : { - "B" : "+Y/eTwtN1xakZCH8+7oH5VADROISOudAe6ieWhjXtsuvnDpDemUtq/T7F0q5G9np" + "B" : "Y5SLBjcna7Lnadg/HC45nj35bXbkVpOZGUIo1Mm0HQkVlHkaUa3WDhhbnffDCxBA" }, "*amzn-ddb-map-desc*" : { "B" : "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" }, "byteArrayValue" : { - "B" : "g59ZhiTxe8r8R2SwlvBFGFPoDgIlqgJuyVrGOq8iVo0=" + "B" : "ZUNvrVLblHJA4spvqMFNdWoFh5AKUDYnN/oKfHOSano=" }, "complexValue" : { - "B" : "826Hs6VEYM7W3Eu1eqIik06gkwCZyMxUKunm09dbiQKJRjodb0t5IUcwc2gxTj9juj0e4CO7r5i7ADspWHGZfvL9MEcnkkURP73baU6LTzdCMbWFn8qJfDooP8VmYYFEhfFqH1lUtJS4IoEZXqauTWMZgjfgSPZ3ULW5Xhtm/eGAlVG+jcXMcqIxKBinnxdi8680Rj0VJySrgOecvKINcA==" + "B" : "liKhRjo+MuAgBFOW1djSFitElqrXbIVCFZUeBobysahGXMOgYLCPHn3eI6JWka/va/RgSsCs2iUuAJg59XFYTEpuXMnjr/FL9Wuxl4naYR0=" } }, { "hashKey" : { @@ -62,7 +62,7 @@ "N" : "0" }, "*amzn-ddb-map-sig*" : { - "B" : "Ae3akfxslcXmwxoAFJwumhzwBVdnzc7oFNhoW1tz0qo=" + "B" : "xBoeUzfWxAsm641nvqJhS7tAaILav/LvusuY39mNYYI=" }, "rangeKey" : { "N" : "10" @@ -79,22 +79,10 @@ "complexValue" : { "L" : [ { "M" : { - "innerNum" : { - "S" : "42" - }, - "innerKey" : { - "S" : "innerVal" - }, "tags" : { "SS" : [ "apple", "banana", "cherry" ] } } - }, { - "M" : { - "nestedKey" : { - "S" : "nestedVal" - } - } } ] } }, { @@ -119,22 +107,10 @@ "complexValue" : { "L" : [ { "M" : { - "innerNum" : { - "S" : "42" - }, - "innerKey" : { - "S" : "innerVal" - }, "tags" : { "SS" : [ "apple", "banana", "cherry" ] } } - }, { - "M" : { - "nestedKey" : { - "S" : "nestedVal" - } - } } ] }, "intValue" : { @@ -154,7 +130,7 @@ "N" : "6" }, "intSet" : { - "B" : "x19+XHMiU3Mzrfo8iKEixyMuSK+M8pYs9uBolbcgsWxJpr0t0DfXi8Lbs0r7UOkOTcpeblpIBLYhwoN4kECX/A==" + "B" : "Jm8klYgp+vOhHSlv1yIeSXFwngnQMhLcFkd8aNNC3phPtlGEtZkaGxaGoKlrw2kg5BWNjd8BQ812DGWrd32Csg==" }, "doubleSet" : { "NS" : [ "-34.2", "-3", "0", "7.6", "15" ] @@ -163,7 +139,7 @@ "N" : "123" }, "stringSet" : { - "B" : "OBCSZ/RaT2pEJYnO4eNxTBXaMcf3N6L8J20Y3Qst2R7BQYx4l3DFZ9pbZJ44pxBJvtsZltTUlYyTqMzk2AFmVA==" + "B" : "bZN60XkckRwMF0Xpxs1FYi0o63O5otW/vZZz/QENpPmdI/6OmZ14Hce6hEeA9B2wffZJNtn/nCKGznLx2C8sjQ==" }, "doubleValue" : { "N" : "15" @@ -172,7 +148,7 @@ "N" : "0" }, "*amzn-ddb-map-sig*" : { - "B" : "YcHz06gurNPDMQonlzVP/dOj4Tj8gyzEPRqG7s7TpT0=" + "B" : "ygxuzPMMeHAJJ0TUuM2HuNjKBQAryPDIrw9oYBZxhAw=" }, "rangeKey" : { "N" : "8" @@ -184,10 +160,10 @@ "B" : "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" }, "byteArrayValue" : { - "B" : "Gbs6G5YIuDt6Vdrfc9Z3aTaK665ocagA92qds1NrNVE=" + "B" : "YJjfl3udiDUL7y8HVsb4J2tX2x27/R/DbaxGoGm4LMw=" }, "complexValue" : { - "B" : "QeuExksSrD4/VwW6ynLrmk/zy2IV3qTWW4/lsmjw89Y60T7Yf3/c2Zz7jXqaTRkaFyGAnBWQjo/5gQ7kLumA+LysicFFQ2bLfq11P60n+YBYkejOC022IYw/qNQPLtKN7O6ZQzWHSPSoSq6StFZsuGTIaZUCyeEDOq9vIDZAl/OzsRkmvoY3FKveoxd7qRb1wyunzQKRc065VhcrGZgcCQ==" + "B" : "11HI3CpWEI/PnmRE0V3rrQdsunVKN9A7r2w+jUoqG62HEwvnhaqQS8zYYBcIrnTJQVa3Y47/uXynE4byRF43SW7Wa0GFJPe0mDUFLPzQbCE=" } } ] } \ 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 0c37f32b18..83cf046d07 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 @@ -405,23 +405,14 @@ public static BaseClass attributeMapToBaseClass( ); } if (attributeMap.containsKey("complexValue")) { - List> complex = attributeMap - .get("complexValue") - .l() - .stream() - .map(av -> - av - .m() - .entrySet() - .stream() - .collect( - java.util.stream.Collectors.toMap( - Map.Entry::getKey, - e -> e.getValue().s() - ) - ) - ) - .collect(java.util.stream.Collectors.toList()); + java.util.List>> complex = + attributeMap.get("complexValue").l().stream() + .map(av -> { + java.util.Map> m = new java.util.HashMap<>(); + av.m().forEach((k, v) -> m.put(k, new java.util.HashSet<>(v.ss()))); + return m; + }) + .collect(java.util.stream.Collectors.toList()); value.setComplexValue(complex); } @@ -467,12 +458,10 @@ public static Map baseClassToV1AttrMap( ) ); if (obj.getComplexValue() != null) { - java.util.List listItems = obj - .getComplexValue() - .stream() + java.util.List listItems = obj.getComplexValue().stream() .map(m -> { Map avMap = new HashMap<>(); - m.forEach((k, v) -> avMap.put(k, new AttributeValue().withS(v))); + m.forEach((k, v) -> avMap.put(k, new AttributeValue().withSS(v))); return new AttributeValue().withM(avMap); }) .collect(java.util.stream.Collectors.toList()); @@ -575,38 +564,17 @@ > baseClassToAttributeMap(Object TEST_VALUE) { .build() ); if (((BaseClass) TEST_VALUE).getComplexValue() != null) { - java.util.List< - software.amazon.awssdk.services.dynamodb.model.AttributeValue - > listItems = - ((BaseClass) TEST_VALUE).getComplexValue() - .stream() + java.util.List listItems = + ((BaseClass) TEST_VALUE).getComplexValue().stream() .map(m -> { - Map< - String, - software.amazon.awssdk.services.dynamodb.model.AttributeValue - > avMap = new HashMap<>(); - m.forEach((k, v) -> - avMap.put( - k, - software.amazon.awssdk.services.dynamodb.model.AttributeValue - .builder() - .s(v) - .build() - ) - ); - return software.amazon.awssdk.services.dynamodb.model.AttributeValue - .builder() - .m(avMap) - .build(); + Map avMap = new HashMap<>(); + m.forEach((k, v) -> avMap.put(k, + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().ss(v).build())); + return software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().m(avMap).build(); }) .collect(java.util.stream.Collectors.toList()); - attributes.put( - "complexValue", - software.amazon.awssdk.services.dynamodb.model.AttributeValue - .builder() - .l(listItems) - .build() - ); + attributes.put("complexValue", + software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().l(listItems).build()); } } else if (TEST_VALUE instanceof KeysOnly) { attributes.put( 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 9714a5b1f3..8519eb4dd1 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 @@ -1181,19 +1181,11 @@ private void assertVersionCompatibility_2(DynamoDBMapper mapper) { } } - private static final List> COMPLEX_VALUE = - java.util.Arrays.asList( - new java.util.HashMap() { - { - put("innerKey", "innerVal"); - put("innerNum", "42"); - } - }, - new java.util.HashMap() { - { - put("nestedKey", "nestedVal"); - } - } + private static final java.util.List>> COMPLEX_VALUE = + java.util.Collections.singletonList( + new java.util.HashMap>() {{ + put("tags", new java.util.HashSet<>(java.util.Arrays.asList("banana", "apple", "cherry"))); + }} ); @SuppressWarnings("unchecked") diff --git a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/types/BaseClass.java b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/types/BaseClass.java index 41da3c3e02..f1b82513ec 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/types/BaseClass.java +++ b/DynamoDbEncryption/runtimes/java/src/test/sdkv1/com/amazonaws/services/dynamodbv2/testing/types/BaseClass.java @@ -83,7 +83,7 @@ public boolean equals(Object obj) { private Integer version; private double doubleValue; private Set doubleSet; - private List> complexValue; + private List>> complexValue; @DynamoDBHashKey public int getHashKey() { @@ -151,11 +151,11 @@ public void setDoubleSet(Set doubleSet) { this.doubleSet = doubleSet; } - public List> getComplexValue() { + public List>> getComplexValue() { return complexValue; } - public void setComplexValue(List> complexValue) { + public void setComplexValue(List>> complexValue) { this.complexValue = complexValue; } 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 fe1bb5d1a1..91c62051e0 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 @@ -1230,18 +1230,11 @@ public Set generateComplexData(EncryptionMaterialsProvider prov) { .rangeKeyName("rangeKey") .build(); - Map innerMap1 = new HashMap<>(); - innerMap1.put("innerKey", AttributeValue.builder().s("innerVal").build()); - innerMap1.put("innerNum", AttributeValue.builder().s("42").build()); - innerMap1.put("tags", AttributeValue.builder().ss("banana", "apple", "cherry").build()); - Map innerMap2 = new HashMap<>(); - innerMap2.put("nestedKey", AttributeValue.builder().s("nestedVal").build()); + Map setMap = new HashMap<>(); + setMap.put("tags", AttributeValue.builder().ss("banana", "apple", "cherry").build()); AttributeValue complexAttr = AttributeValue .builder() - .l( - AttributeValue.builder().m(innerMap1).build(), - AttributeValue.builder().m(innerMap2).build() - ) + .l(AttributeValue.builder().m(setMap).build()) .build(); Map item; @@ -1646,19 +1639,12 @@ private void assertVersionCompatibility_complex( .hashKeyName("hashKey") .rangeKeyName("rangeKey") .build(); - - Map innerMap1 = new HashMap<>(); - innerMap1.put("innerKey", AttributeValue.builder().s("innerVal").build()); - innerMap1.put("innerNum", AttributeValue.builder().s("42").build()); - innerMap1.put("tags", AttributeValue.builder().ss("banana", "apple", "cherry").build()); - Map innerMap2 = new HashMap<>(); - innerMap2.put("nestedKey", AttributeValue.builder().s("nestedVal").build()); + + Map setMap = new HashMap<>(); + setMap.put("tags", AttributeValue.builder().ss("banana", "apple", "cherry").build()); AttributeValue complexAttr = AttributeValue .builder() - .l( - AttributeValue.builder().m(innerMap1).build(), - AttributeValue.builder().m(innerMap2).build() - ) + .l(AttributeValue.builder().m(setMap).build()) .build(); Map expectedEncrypted = new HashMap<>( From e405d83ec22603e7f378d7e1006f2f8945a09cdd Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sun, 29 Mar 2026 11:45:38 -0700 Subject: [PATCH 09/18] m --- .../datamodeling/LegacyTestVectors.java | 49 ++++++++++++++----- .../datamodeling/TransformerHolisticIT.java | 26 ++++++---- .../datamodeling/sdkv2/HolisticIT.java | 18 ++++--- 3 files changed, 67 insertions(+), 26 deletions(-) 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 83cf046d07..99f00f45d8 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 @@ -406,9 +406,13 @@ public static BaseClass attributeMapToBaseClass( } if (attributeMap.containsKey("complexValue")) { java.util.List>> complex = - attributeMap.get("complexValue").l().stream() + attributeMap + .get("complexValue") + .l() + .stream() .map(av -> { - java.util.Map> m = new java.util.HashMap<>(); + java.util.Map> m = + new java.util.HashMap<>(); av.m().forEach((k, v) -> m.put(k, new java.util.HashSet<>(v.ss()))); return m; }) @@ -458,7 +462,9 @@ public static Map baseClassToV1AttrMap( ) ); if (obj.getComplexValue() != null) { - java.util.List listItems = obj.getComplexValue().stream() + java.util.List listItems = obj + .getComplexValue() + .stream() .map(m -> { Map avMap = new HashMap<>(); m.forEach((k, v) -> avMap.put(k, new AttributeValue().withSS(v))); @@ -564,17 +570,38 @@ > baseClassToAttributeMap(Object TEST_VALUE) { .build() ); if (((BaseClass) TEST_VALUE).getComplexValue() != null) { - java.util.List listItems = - ((BaseClass) TEST_VALUE).getComplexValue().stream() + java.util.List< + software.amazon.awssdk.services.dynamodb.model.AttributeValue + > listItems = + ((BaseClass) TEST_VALUE).getComplexValue() + .stream() .map(m -> { - Map avMap = new HashMap<>(); - m.forEach((k, v) -> avMap.put(k, - software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().ss(v).build())); - return software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().m(avMap).build(); + Map< + String, + software.amazon.awssdk.services.dynamodb.model.AttributeValue + > avMap = new HashMap<>(); + m.forEach((k, v) -> + avMap.put( + k, + software.amazon.awssdk.services.dynamodb.model.AttributeValue + .builder() + .ss(v) + .build() + ) + ); + return software.amazon.awssdk.services.dynamodb.model.AttributeValue + .builder() + .m(avMap) + .build(); }) .collect(java.util.stream.Collectors.toList()); - attributes.put("complexValue", - software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder().l(listItems).build()); + attributes.put( + "complexValue", + software.amazon.awssdk.services.dynamodb.model.AttributeValue + .builder() + .l(listItems) + .build() + ); } } else if (TEST_VALUE instanceof KeysOnly) { attributes.put( 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 8519eb4dd1..717ab5ebd0 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 @@ -405,7 +405,7 @@ public void decryptTestVector(Scenario scenario) throws IOException { case "v1": assertVersionCompatibility_2(mapper); break; - case "v2_complex": + case "v1_complex": assertVersionCompatibility_complex(mapper); break; default: @@ -510,7 +510,7 @@ public void decryptLegacyTestVector(Scenario scenario) throws IOException { // This is why this vector exists but is not tested. // assertTrue(LegacyTestVectors.testDecryptionTestVector(client, legacyEncryptor, UNTOUCHED_TEST_VALUE_2)); break; - case "v2_complex": + case "v1_complex": LegacyTestVectors.decryptBaseClassTestVector( client, legacyEncryptor, @@ -535,7 +535,7 @@ public void decryptLegacyTestVector(Scenario scenario) throws IOException { ); } - if (!"v2_complex".equals(scenario.version)) { + if (!"v1_complex".equals(scenario.version)) { LegacyTestVectors.decryptHashKeyOnlyTestVector( client, legacyEncryptor, @@ -1181,12 +1181,20 @@ private void assertVersionCompatibility_2(DynamoDBMapper mapper) { } } - private static final java.util.List>> COMPLEX_VALUE = - java.util.Collections.singletonList( - new java.util.HashMap>() {{ - put("tags", new java.util.HashSet<>(java.util.Arrays.asList("banana", "apple", "cherry"))); - }} - ); + private static final java.util.List< + java.util.Map> + > COMPLEX_VALUE = java.util.Collections.singletonList( + new java.util.HashMap>() { + { + put( + "tags", + new java.util.HashSet<>( + java.util.Arrays.asList("banana", "apple", "cherry") + ) + ); + } + } + ); @SuppressWarnings("unchecked") private static T withComplexValue(T source) { 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 91c62051e0..ce8b888a5e 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 @@ -648,7 +648,7 @@ public void decryptTestVector(Scenario scenario) case "v1": assertVersionCompatibility_2(provider, tableName); break; - case "v2_complex": + case "v1_complex": assertVersionCompatibility_complex(provider, tableName); break; default: @@ -710,7 +710,7 @@ public void encryptWithTestVector(Scenario scenario) throws IOException { scenario.materialDescription ); Set tables; - if ("v2_complex".equals(scenario.version)) { + if ("v1_complex".equals(scenario.version)) { tables = generateComplexData(provider); } else { tables = generateStandardData(provider); @@ -718,7 +718,7 @@ public void encryptWithTestVector(Scenario scenario) throws IOException { if ( saveToJson && - ("v1".equals(scenario.version) || "v2_complex".equals(scenario.version)) + ("v1".equals(scenario.version) || "v1_complex".equals(scenario.version)) ) { String outputFile = java.nio.file.Paths .get(scenario.ciphertextPath.replace("file://", "")) @@ -1231,7 +1231,10 @@ public Set generateComplexData(EncryptionMaterialsProvider prov) { .build(); Map setMap = new HashMap<>(); - setMap.put("tags", AttributeValue.builder().ss("banana", "apple", "cherry").build()); + setMap.put( + "tags", + AttributeValue.builder().ss("banana", "apple", "cherry").build() + ); AttributeValue complexAttr = AttributeValue .builder() .l(AttributeValue.builder().m(setMap).build()) @@ -1639,9 +1642,12 @@ private void assertVersionCompatibility_complex( .hashKeyName("hashKey") .rangeKeyName("rangeKey") .build(); - + Map setMap = new HashMap<>(); - setMap.put("tags", AttributeValue.builder().ss("banana", "apple", "cherry").build()); + setMap.put( + "tags", + AttributeValue.builder().ss("banana", "apple", "cherry").build() + ); AttributeValue complexAttr = AttributeValue .builder() .l(AttributeValue.builder().m(setMap).build()) From a7d021d2e265c4871be2ce90f99f84042ba7205e Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sun, 29 Mar 2026 11:58:30 -0700 Subject: [PATCH 10/18] m --- .../java/static-aes-hmac-complex-1.json | 28 +++++++++---------- .../vectors/encrypted_item/scenarios.json | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json index e88dbb2f09..60bdbed8f0 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json +++ b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json @@ -4,40 +4,40 @@ "N" : "5" }, "intSet" : { - "B" : "YT/4WCrk0h3ywpKPCn4cXFOKJeZZcd1m2xFdXPqQs3S/rjoALLdG1pvc2XywQxgpB7a4UKDaL5lGcb2l2BejkA==" + "B" : "hSyNrutzz/66hy7Aop/U9tubCBYJkStxMs/p/3kNmgZg1i9S4SpyoDQqIgzrAqESJ9swarmKNk7PAdm+DWTLmQ==" }, "doubleSet" : { - "B" : "pWx7fEGKniYnXit0LdrpC3j4Cc3VdCMrypFzHyWuHCSLx8wKmw4FFMDdC5oewTL9unfs87qL7k238R7ky4of2g==" + "B" : "kha4s0Orm/nlE1Q6YzvHZk+YhU5QVarJLDnmW2Glak6vmqi03wX5X/pQyNKWrHTGPeDsrx5jvdKwYghgVqncCg==" }, "intValue" : { - "B" : "w9XJYu30P/e9cypdUxLkI/eeX20+skX5zCwuNPWNJuc=" + "B" : "uPS1BBRz8jbWjN6OWvS0KqkzwzK6mBevD2XKQLMhTRA=" }, "stringSet" : { - "B" : "VmlhLGf+6XEGsGacVb9vGW5eHRKVgGYv1qeJ3ih9tGlSGsUHtgach2Oz4R1srhvYh4a8jKRX4S9P4nePU7xeaA==" + "B" : "/OCTLd5eHaLdcgGNKwY5FXiPPEHaOB71Izt7UH6E/IesOWJ4ye39UV00g4K84xbIVBVT3Y5aXM0KW1/hSYEeIg==" }, "doubleValue" : { - "B" : "YGjpcbIplQCcc8N3WeWgmO9kcqbhA/5hSCz+Ow/HD5g=" + "B" : "6MibXf75M2xe/DeX5io6BUNGiP052GJhcEJ91n2i7rU=" }, "version" : { "N" : "0" }, "*amzn-ddb-map-sig*" : { - "B" : "CZwERkVud3QnWDMbn0viTLnrLI8wqkCc/Z4irQWHfNg=" + "B" : "qON5xK4vsIAEa43E2Il/GgARq3DdKMSOAnLCbl/nEL0=" }, "rangeKey" : { "N" : "7" }, "stringValue" : { - "B" : "Y5SLBjcna7Lnadg/HC45nj35bXbkVpOZGUIo1Mm0HQkVlHkaUa3WDhhbnffDCxBA" + "B" : "WZRiC0H9mHHZsv81uSB3Qw27nF/Iflf+2QwRcDjRAx5xcWhiUbSTr5mYrp5038yY" }, "*amzn-ddb-map-desc*" : { "B" : "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" }, "byteArrayValue" : { - "B" : "ZUNvrVLblHJA4spvqMFNdWoFh5AKUDYnN/oKfHOSano=" + "B" : "0mFT71NFB/YEZdVA9H0lKhI86Djiy7sezbFFcZ7ua3U=" }, "complexValue" : { - "B" : "liKhRjo+MuAgBFOW1djSFitElqrXbIVCFZUeBobysahGXMOgYLCPHn3eI6JWka/va/RgSsCs2iUuAJg59XFYTEpuXMnjr/FL9Wuxl4naYR0=" + "B" : "wBFWEy3Ao2nhzCxxCLNdY1T5Gbqk5HM8I47r/8sz8zoVtfZaPYvi1wUFjEeIe4isMfCCmvvdBT0GSFCOB/0yCmmcPx0rINxsj5vLcJBQdXc=" } }, { "hashKey" : { @@ -130,7 +130,7 @@ "N" : "6" }, "intSet" : { - "B" : "Jm8klYgp+vOhHSlv1yIeSXFwngnQMhLcFkd8aNNC3phPtlGEtZkaGxaGoKlrw2kg5BWNjd8BQ812DGWrd32Csg==" + "B" : "HuutO2N8WwV9l6RQzHYjIgNgcEiIHRQylrvtUV065HObddI5sQXv5AtXWt/MZDZ048yVApCeZDrOzp6peStbiQ==" }, "doubleSet" : { "NS" : [ "-34.2", "-3", "0", "7.6", "15" ] @@ -139,7 +139,7 @@ "N" : "123" }, "stringSet" : { - "B" : "bZN60XkckRwMF0Xpxs1FYi0o63O5otW/vZZz/QENpPmdI/6OmZ14Hce6hEeA9B2wffZJNtn/nCKGznLx2C8sjQ==" + "B" : "GTfT29jFZLl/yWG+617V+4UHP6zWkMM1YemGOUzrQrmd9TtFSlFPDmdaKmfCO5u0f0o4hic6IRNagl6RUVujRw==" }, "doubleValue" : { "N" : "15" @@ -148,7 +148,7 @@ "N" : "0" }, "*amzn-ddb-map-sig*" : { - "B" : "ygxuzPMMeHAJJ0TUuM2HuNjKBQAryPDIrw9oYBZxhAw=" + "B" : "ChQhebhKmivOac3FvVonKiXShL3iixjAIKi8veZa+Jo=" }, "rangeKey" : { "N" : "8" @@ -160,10 +160,10 @@ "B" : "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" }, "byteArrayValue" : { - "B" : "YJjfl3udiDUL7y8HVsb4J2tX2x27/R/DbaxGoGm4LMw=" + "B" : "cLy/3hMrfSkRmGkhXD4aYC7j5cFlfca//k5gwaUilew=" }, "complexValue" : { - "B" : "11HI3CpWEI/PnmRE0V3rrQdsunVKN9A7r2w+jUoqG62HEwvnhaqQS8zYYBcIrnTJQVa3Y47/uXynE4byRF43SW7Wa0GFJPe0mDUFLPzQbCE=" + "B" : "SwP4pvB4goUzz891QwzMmzFhwnUYvxZzQBGlMUNYmciydYrpmBC8zLOOsVW8r34vIWk76pliPuM53F7MFhnusKAR3rLHBsUCvNzjhOC6JBQ=" } } ] } \ No newline at end of file diff --git a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/scenarios.json b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/scenarios.json index 96ec54746e..3e6cce6cf3 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/scenarios.json +++ b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/scenarios.json @@ -380,7 +380,7 @@ "network": false }, { - "version": "v2_complex", + "version": "v1_complex", "provider": "static", "keys": { "decrypt": "aesKey", From 24cec9ade2675f4cc4e8f6be6030af4d6799f2f0 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sun, 29 Mar 2026 12:03:10 -0700 Subject: [PATCH 11/18] m --- .../datamodeling/TransformerHolisticIT.java | 17 ----------------- 1 file changed, 17 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 717ab5ebd0..e408b1de33 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 @@ -510,23 +510,6 @@ public void decryptLegacyTestVector(Scenario scenario) throws IOException { // This is why this vector exists but is not tested. // assertTrue(LegacyTestVectors.testDecryptionTestVector(client, legacyEncryptor, UNTOUCHED_TEST_VALUE_2)); break; - case "v1_complex": - LegacyTestVectors.decryptBaseClassTestVector( - client, - legacyEncryptor, - withComplexValue(ENCRYPTED_TEST_VALUE_2) - ); - LegacyTestVectors.decryptBaseClassTestVector( - client, - legacyEncryptor, - withComplexValue(MIXED_TEST_VALUE_2) - ); - LegacyTestVectors.decryptBaseClassTestVector( - client, - legacyEncryptor, - withComplexValue(SIGNED_TEST_VALUE_2) - ); - break; default: throw new IllegalStateException( "Version " + From 6eb6eb5f08431ddaa693b597150715467652ab8a Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sun, 29 Mar 2026 12:05:49 -0700 Subject: [PATCH 12/18] m --- .../datamodeling/TransformerHolisticIT.java | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 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 e408b1de33..dd0e93b8a3 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 @@ -518,43 +518,44 @@ public void decryptLegacyTestVector(Scenario scenario) throws IOException { ); } - if (!"v1_complex".equals(scenario.version)) { - LegacyTestVectors.decryptHashKeyOnlyTestVector( + if ("v1_complex".equals(scenario.version)) { + return + } + LegacyTestVectors.decryptHashKeyOnlyTestVector( + client, + legacyEncryptor, + "Foo" + ); + LegacyTestVectors.decryptHashKeyOnlyTestVector( + client, + legacyEncryptor, + "Bar" + ); + LegacyTestVectors.decryptHashKeyOnlyTestVector( + client, + legacyEncryptor, + "Baz" + ); + + for (int x = 1; x <= 3; ++x) { + LegacyTestVectors.decryptKeysOnlyTestVector( client, legacyEncryptor, - "Foo" + 0, + x ); - LegacyTestVectors.decryptHashKeyOnlyTestVector( + LegacyTestVectors.decryptKeysOnlyTestVector( client, legacyEncryptor, - "Bar" + 1, + x ); - LegacyTestVectors.decryptHashKeyOnlyTestVector( + LegacyTestVectors.decryptKeysOnlyTestVector( client, legacyEncryptor, - "Baz" + 4 + x, + x ); - - for (int x = 1; x <= 3; ++x) { - LegacyTestVectors.decryptKeysOnlyTestVector( - client, - legacyEncryptor, - 0, - x - ); - LegacyTestVectors.decryptKeysOnlyTestVector( - client, - legacyEncryptor, - 1, - x - ); - LegacyTestVectors.decryptKeysOnlyTestVector( - client, - legacyEncryptor, - 4 + x, - x - ); - } } } From daef89ce1c9215b0f201422adfcc9b0617b2f7bb Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sun, 29 Mar 2026 12:52:28 -0700 Subject: [PATCH 13/18] m --- .../services/dynamodbv2/datamodeling/TransformerHolisticIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 dd0e93b8a3..64d8725f0e 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 @@ -519,7 +519,7 @@ public void decryptLegacyTestVector(Scenario scenario) throws IOException { } if ("v1_complex".equals(scenario.version)) { - return + return; } LegacyTestVectors.decryptHashKeyOnlyTestVector( client, From d9555396509736122747c77b9e42d4c260c05872 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sun, 29 Mar 2026 13:03:37 -0700 Subject: [PATCH 14/18] m --- .../java/static-aes-hmac-complex-1.json | 339 +++++++++--------- 1 file changed, 174 insertions(+), 165 deletions(-) diff --git a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json index 60bdbed8f0..f3a4a67aac 100644 --- a/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json +++ b/DynamoDbEncryption/runtimes/java/src/test/resources/vectors/encrypted_item/ciphertext/java/static-aes-hmac-complex-1.json @@ -1,169 +1,178 @@ { - "TableName" : [ { - "hashKey" : { - "N" : "5" - }, - "intSet" : { - "B" : "hSyNrutzz/66hy7Aop/U9tubCBYJkStxMs/p/3kNmgZg1i9S4SpyoDQqIgzrAqESJ9swarmKNk7PAdm+DWTLmQ==" - }, - "doubleSet" : { - "B" : "kha4s0Orm/nlE1Q6YzvHZk+YhU5QVarJLDnmW2Glak6vmqi03wX5X/pQyNKWrHTGPeDsrx5jvdKwYghgVqncCg==" - }, - "intValue" : { - "B" : "uPS1BBRz8jbWjN6OWvS0KqkzwzK6mBevD2XKQLMhTRA=" - }, - "stringSet" : { - "B" : "/OCTLd5eHaLdcgGNKwY5FXiPPEHaOB71Izt7UH6E/IesOWJ4ye39UV00g4K84xbIVBVT3Y5aXM0KW1/hSYEeIg==" - }, - "doubleValue" : { - "B" : "6MibXf75M2xe/DeX5io6BUNGiP052GJhcEJ91n2i7rU=" - }, - "version" : { - "N" : "0" - }, - "*amzn-ddb-map-sig*" : { - "B" : "qON5xK4vsIAEa43E2Il/GgARq3DdKMSOAnLCbl/nEL0=" - }, - "rangeKey" : { - "N" : "7" - }, - "stringValue" : { - "B" : "WZRiC0H9mHHZsv81uSB3Qw27nF/Iflf+2QwRcDjRAx5xcWhiUbSTr5mYrp5038yY" - }, - "*amzn-ddb-map-desc*" : { - "B" : "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" - }, - "byteArrayValue" : { - "B" : "0mFT71NFB/YEZdVA9H0lKhI86Djiy7sezbFFcZ7ua3U=" - }, - "complexValue" : { - "B" : "wBFWEy3Ao2nhzCxxCLNdY1T5Gbqk5HM8I47r/8sz8zoVtfZaPYvi1wUFjEeIe4isMfCCmvvdBT0GSFCOB/0yCmmcPx0rINxsj5vLcJBQdXc=" - } - }, { - "hashKey" : { - "N" : "8" - }, - "intSet" : { - "NS" : [ "0", "1", "10", "15", "200" ] - }, - "doubleSet" : { - "NS" : [ "-34.2", "-3", "0", "7.6", "15" ] - }, - "intValue" : { - "N" : "123" - }, - "stringSet" : { - "SS" : [ "?", "Cruel", "Goodbye", "World" ] - }, - "doubleValue" : { - "N" : "15" - }, - "version" : { - "N" : "0" - }, - "*amzn-ddb-map-sig*" : { - "B" : "xBoeUzfWxAsm641nvqJhS7tAaILav/LvusuY39mNYYI=" - }, - "rangeKey" : { - "N" : "10" - }, - "stringValue" : { - "S" : "Hello world!" - }, - "*amzn-ddb-map-desc*" : { - "B" : "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" - }, - "byteArrayValue" : { - "B" : "AAECAwQF" - }, - "complexValue" : { - "L" : [ { - "M" : { - "tags" : { - "SS" : [ "apple", "banana", "cherry" ] + "TableName": [ + { + "hashKey": { + "N": "5" + }, + "intSet": { + "B": "hSyNrutzz/66hy7Aop/U9tubCBYJkStxMs/p/3kNmgZg1i9S4SpyoDQqIgzrAqESJ9swarmKNk7PAdm+DWTLmQ==" + }, + "doubleSet": { + "B": "kha4s0Orm/nlE1Q6YzvHZk+YhU5QVarJLDnmW2Glak6vmqi03wX5X/pQyNKWrHTGPeDsrx5jvdKwYghgVqncCg==" + }, + "intValue": { + "B": "uPS1BBRz8jbWjN6OWvS0KqkzwzK6mBevD2XKQLMhTRA=" + }, + "stringSet": { + "B": "/OCTLd5eHaLdcgGNKwY5FXiPPEHaOB71Izt7UH6E/IesOWJ4ye39UV00g4K84xbIVBVT3Y5aXM0KW1/hSYEeIg==" + }, + "doubleValue": { + "B": "6MibXf75M2xe/DeX5io6BUNGiP052GJhcEJ91n2i7rU=" + }, + "version": { + "N": "0" + }, + "*amzn-ddb-map-sig*": { + "B": "qON5xK4vsIAEa43E2Il/GgARq3DdKMSOAnLCbl/nEL0=" + }, + "rangeKey": { + "N": "7" + }, + "stringValue": { + "B": "WZRiC0H9mHHZsv81uSB3Qw27nF/Iflf+2QwRcDjRAx5xcWhiUbSTr5mYrp5038yY" + }, + "*amzn-ddb-map-desc*": { + "B": "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" + }, + "byteArrayValue": { + "B": "0mFT71NFB/YEZdVA9H0lKhI86Djiy7sezbFFcZ7ua3U=" + }, + "complexValue": { + "B": "wBFWEy3Ao2nhzCxxCLNdY1T5Gbqk5HM8I47r/8sz8zoVtfZaPYvi1wUFjEeIe4isMfCCmvvdBT0GSFCOB/0yCmmcPx0rINxsj5vLcJBQdXc=" + } + }, + { + "hashKey": { + "N": "8" + }, + "intSet": { + "NS": ["0", "1", "10", "15", "200"] + }, + "doubleSet": { + "NS": ["-34.2", "-3", "0", "7.6", "15"] + }, + "intValue": { + "N": "123" + }, + "stringSet": { + "SS": ["?", "Cruel", "Goodbye", "World"] + }, + "doubleValue": { + "N": "15" + }, + "version": { + "N": "0" + }, + "*amzn-ddb-map-sig*": { + "B": "xBoeUzfWxAsm641nvqJhS7tAaILav/LvusuY39mNYYI=" + }, + "rangeKey": { + "N": "10" + }, + "stringValue": { + "S": "Hello world!" + }, + "*amzn-ddb-map-desc*": { + "B": "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" + }, + "byteArrayValue": { + "B": "AAECAwQF" + }, + "complexValue": { + "L": [ + { + "M": { + "tags": { + "SS": ["apple", "banana", "cherry"] + } + } } - } - } ] - } - }, { - "rangeKey" : { - "N" : "9" - }, - "hashKey" : { - "N" : "7" - }, - "stringValue" : { - "S" : "Hello world!" - }, - "intSet" : { - "NS" : [ "0", "1", "10", "15", "200" ] - }, - "doubleSet" : { - "NS" : [ "-34.2", "-3", "0", "7.6", "15" ] - }, - "byteArrayValue" : { - "B" : "AAECAwQF" - }, - "complexValue" : { - "L" : [ { - "M" : { - "tags" : { - "SS" : [ "apple", "banana", "cherry" ] + ] + } + }, + { + "rangeKey": { + "N": "9" + }, + "hashKey": { + "N": "7" + }, + "stringValue": { + "S": "Hello world!" + }, + "intSet": { + "NS": ["0", "1", "10", "15", "200"] + }, + "doubleSet": { + "NS": ["-34.2", "-3", "0", "7.6", "15"] + }, + "byteArrayValue": { + "B": "AAECAwQF" + }, + "complexValue": { + "L": [ + { + "M": { + "tags": { + "SS": ["apple", "banana", "cherry"] + } + } } - } - } ] - }, - "intValue" : { - "N" : "123" - }, - "stringSet" : { - "SS" : [ "?", "Cruel", "Goodbye", "World" ] - }, - "doubleValue" : { - "N" : "15" - }, - "version" : { - "N" : "0" - } - }, { - "hashKey" : { - "N" : "6" - }, - "intSet" : { - "B" : "HuutO2N8WwV9l6RQzHYjIgNgcEiIHRQylrvtUV065HObddI5sQXv5AtXWt/MZDZ048yVApCeZDrOzp6peStbiQ==" - }, - "doubleSet" : { - "NS" : [ "-34.2", "-3", "0", "7.6", "15" ] - }, - "intValue" : { - "N" : "123" - }, - "stringSet" : { - "B" : "GTfT29jFZLl/yWG+617V+4UHP6zWkMM1YemGOUzrQrmd9TtFSlFPDmdaKmfCO5u0f0o4hic6IRNagl6RUVujRw==" - }, - "doubleValue" : { - "N" : "15" - }, - "version" : { - "N" : "0" - }, - "*amzn-ddb-map-sig*" : { - "B" : "ChQhebhKmivOac3FvVonKiXShL3iixjAIKi8veZa+Jo=" - }, - "rangeKey" : { - "N" : "8" - }, - "stringValue" : { - "S" : "Hello world!" - }, - "*amzn-ddb-map-desc*" : { - "B" : "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" - }, - "byteArrayValue" : { - "B" : "cLy/3hMrfSkRmGkhXD4aYC7j5cFlfca//k5gwaUilew=" - }, - "complexValue" : { - "B" : "SwP4pvB4goUzz891QwzMmzFhwnUYvxZzQBGlMUNYmciydYrpmBC8zLOOsVW8r34vIWk76pliPuM53F7MFhnusKAR3rLHBsUCvNzjhOC6JBQ=" + ] + }, + "intValue": { + "N": "123" + }, + "stringSet": { + "SS": ["?", "Cruel", "Goodbye", "World"] + }, + "doubleValue": { + "N": "15" + }, + "version": { + "N": "0" + } + }, + { + "hashKey": { + "N": "6" + }, + "intSet": { + "B": "HuutO2N8WwV9l6RQzHYjIgNgcEiIHRQylrvtUV065HObddI5sQXv5AtXWt/MZDZ048yVApCeZDrOzp6peStbiQ==" + }, + "doubleSet": { + "NS": ["-34.2", "-3", "0", "7.6", "15"] + }, + "intValue": { + "N": "123" + }, + "stringSet": { + "B": "GTfT29jFZLl/yWG+617V+4UHP6zWkMM1YemGOUzrQrmd9TtFSlFPDmdaKmfCO5u0f0o4hic6IRNagl6RUVujRw==" + }, + "doubleValue": { + "N": "15" + }, + "version": { + "N": "0" + }, + "*amzn-ddb-map-sig*": { + "B": "ChQhebhKmivOac3FvVonKiXShL3iixjAIKi8veZa+Jo=" + }, + "rangeKey": { + "N": "8" + }, + "stringValue": { + "S": "Hello world!" + }, + "*amzn-ddb-map-desc*": { + "B": "AAAAAAAAABVhbXpuLWRkYi1tYXAtc3ltLW1vZGUAAAARL0NCQy9QS0NTNVBhZGRpbmc=" + }, + "byteArrayValue": { + "B": "cLy/3hMrfSkRmGkhXD4aYC7j5cFlfca//k5gwaUilew=" + }, + "complexValue": { + "B": "SwP4pvB4goUzz891QwzMmzFhwnUYvxZzQBGlMUNYmciydYrpmBC8zLOOsVW8r34vIWk76pliPuM53F7MFhnusKAR3rLHBsUCvNzjhOC6JBQ=" + } } - } ] -} \ No newline at end of file + ] +} From 97a6209a77286ad855100da37127525ab7745e3e Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sun, 29 Mar 2026 13:41:36 -0700 Subject: [PATCH 15/18] m --- .../datamodeling/TransformerHolisticIT.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) 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 64d8725f0e..48538afbaa 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 @@ -510,6 +510,23 @@ public void decryptLegacyTestVector(Scenario scenario) throws IOException { // This is why this vector exists but is not tested. // assertTrue(LegacyTestVectors.testDecryptionTestVector(client, legacyEncryptor, UNTOUCHED_TEST_VALUE_2)); break; + case "v1_complex": + LegacyTestVectors.decryptBaseClassTestVector( + client, + legacyEncryptor, + withComplexValue(ENCRYPTED_TEST_VALUE_2) + ); + LegacyTestVectors.decryptBaseClassTestVector( + client, + legacyEncryptor, + withComplexValue(MIXED_TEST_VALUE_2) + ); + LegacyTestVectors.decryptBaseClassTestVector( + client, + legacyEncryptor, + withComplexValue(SIGNED_TEST_VALUE_2) + ); + break; default: throw new IllegalStateException( "Version " + From 1319c0db2a7eab18b08a09cdcb080c115096d441 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Sun, 29 Mar 2026 14:11:30 -0700 Subject: [PATCH 16/18] m --- .../datamodeling/TransformerHolisticIT.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 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 48538afbaa..8ce858e813 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 @@ -512,19 +512,19 @@ public void decryptLegacyTestVector(Scenario scenario) throws IOException { break; case "v1_complex": LegacyTestVectors.decryptBaseClassTestVector( - client, - legacyEncryptor, - withComplexValue(ENCRYPTED_TEST_VALUE_2) + client, + legacyEncryptor, + withComplexValue(ENCRYPTED_TEST_VALUE_2) ); LegacyTestVectors.decryptBaseClassTestVector( - client, - legacyEncryptor, - withComplexValue(MIXED_TEST_VALUE_2) + client, + legacyEncryptor, + withComplexValue(MIXED_TEST_VALUE_2) ); LegacyTestVectors.decryptBaseClassTestVector( - client, - legacyEncryptor, - withComplexValue(SIGNED_TEST_VALUE_2) + client, + legacyEncryptor, + withComplexValue(SIGNED_TEST_VALUE_2) ); break; default: From 4cd11e05180b286fc3f5c54a3f625930a6313efe Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Mon, 30 Mar 2026 11:26:55 -0700 Subject: [PATCH 17/18] this should fail --- .../services/dynamodbv2/datamodeling/TransformerHolisticIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 8ce858e813..9be9a1a066 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 @@ -1190,7 +1190,7 @@ private void assertVersionCompatibility_2(DynamoDBMapper mapper) { put( "tags", new java.util.HashSet<>( - java.util.Arrays.asList("banana", "apple", "cherry") + java.util.Arrays.asList("banana", "apple", "cherr") ) ); } From 281f53e8f0c1a43157e84b63848095c7ba880d16 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Mon, 30 Mar 2026 11:33:38 -0700 Subject: [PATCH 18/18] Revert "this should fail" This reverts commit 4cd11e05180b286fc3f5c54a3f625930a6313efe. --- .../services/dynamodbv2/datamodeling/TransformerHolisticIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9be9a1a066..8ce858e813 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 @@ -1190,7 +1190,7 @@ private void assertVersionCompatibility_2(DynamoDBMapper mapper) { put( "tags", new java.util.HashSet<>( - java.util.Arrays.asList("banana", "apple", "cherr") + java.util.Arrays.asList("banana", "apple", "cherry") ) ); }