From 95a51d26dc473015e4a9fd8ef22a79616c7383c5 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 13 Nov 2025 12:35:48 -0800 Subject: [PATCH 01/10] Replace submodule with symbolic link for .NET v3 s3ec --- .gitmodules | 4 ---- all-examples/net/v3/s3ec-v3-local | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) mode change 160000 => 120000 all-examples/net/v3/s3ec-v3-local diff --git a/.gitmodules b/.gitmodules index 51e8e255..e93e0092 100644 --- a/.gitmodules +++ b/.gitmodules @@ -67,7 +67,3 @@ path = all-examples/net/v4/s3ec-v4-local url = https://github.com/aws/private-amazon-s3-encryption-client-dotnet-staging.git branch = s3ec-v4-WIP -[submodule "all-examples/net/v3/s3ec-v3-local"] - path = all-examples/net/v3/s3ec-v3-local - url = https://github.com/aws/private-amazon-s3-encryption-client-dotnet-staging.git - branch = rishav/key-commitment diff --git a/all-examples/net/v3/s3ec-v3-local b/all-examples/net/v3/s3ec-v3-local deleted file mode 160000 index ca1149d9..00000000 --- a/all-examples/net/v3/s3ec-v3-local +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ca1149d9b423591c09d35caa649b3f6846e511a6 diff --git a/all-examples/net/v3/s3ec-v3-local b/all-examples/net/v3/s3ec-v3-local new file mode 120000 index 00000000..a2d8df44 --- /dev/null +++ b/all-examples/net/v3/s3ec-v3-local @@ -0,0 +1 @@ +../../../test-server/net-v3-transition-server/s3ec-v3-transition-branch \ No newline at end of file From c0b57c50295c0edecfbb899f2e071f559a1a699f Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 13 Nov 2025 13:27:33 -0800 Subject: [PATCH 02/10] auto commit --- .../amazon/encryption/s3/RoundTripTests.java | 70 +++++++++++++++++++ .../Controllers/ClientController.cs | 4 ++ .../Models/ClientRequest.cs | 8 +++ 3 files changed, 82 insertions(+) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java index 1167e4db..a218d696 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java @@ -609,4 +609,74 @@ public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageSe assertEquals(input, new String(output.getBody().array())); } } + + @ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {1}") + @MethodSource("software.amazon.encryption.s3.TestUtils#crossLanguageClients") + public void rsaWithInstructionFileRoundTrip(LanguageServerTarget encLang, LanguageServerTarget decLang) { + if (!RAW_SUPPORTED.contains(encLang.getLanguageName())) { + throw new TestAbortedException("not encrypting raw keyrings with: " + encLang.getLanguageName()); + } + if (!RAW_SUPPORTED.contains(decLang.getLanguageName())) { + throw new TestAbortedException("not decrypting raw keyrings with: " + decLang.getLanguageName()); + } + S3ECTestServerClient encClient = testServerClientFor(encLang); + S3ECTestServerClient decClient = testServerClientFor(decLang); + final String objectKey = appendTestSuffix(String.format("rsa-with-ins-file-write-%s-read-%s", encLang.getLanguageName(), decLang.getLanguageName())); + final String input = "simple-test-input"; + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); + keyPairGen.initialize(2048); + KeyPair RSA_KEY_PAIR_1 = keyPairGen.generateKeyPair(); + + CreateClientOutput encClientOutput = encClient.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .instructionFileConfig(InstructionFileConfig.builder() + .enableInstructionFilePutObject(true) + .build()) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .keyMaterial(rsaKeyOne).build()) + .build()); + String encS3ECId = encClientOutput.getClientId(); + CreateClientOutput decClientOutput = decClient.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .instructionFileConfig(InstructionFileConfig.builder() + .enableInstructionFilePutObject(true) + .build()) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .keyMaterial(rsaKeyOne).build()) + .build()); + String decS3ECId = decClientOutput.getClientId(); + + // Write with instruction file + encClient.putObject(PutObjectInput.builder() + .clientID(encS3ECId) + .bucket(BUCKET) + .key(objectKey) + .body(ByteBuffer.wrap(input.getBytes(StandardCharsets.UTF_8))) + .build()); + + // Assert using Java plaintext client that an instruction file exists + ResponseBytes ptInstFile; + try (S3Client ptS3Client = S3Client.create()) { + ptInstFile = ptS3Client.getObjectAsBytes(builder -> builder + .bucket(BUCKET) + .key(objectKey + ".instruction") + .build()); + } + // Check for inst file key + if (!encLang.getLanguageName().startsWith("Ruby") && !encLang.getLanguageName().startsWith("PHP")) { + // Ruby and PHP do not include it :( + assertTrue(ptInstFile.response().metadata().containsKey("x-amz-crypto-instr-file")); + assertFalse(ptInstFile.asUtf8String().isEmpty()); + // Read should be enabled by default + GetObjectOutput output = decClient.getObject(GetObjectInput.builder() + .clientID(decS3ECId) + .bucket(BUCKET) + .key(objectKey) + .build()); + + assertEquals(input, new String(output.getBody().array())); + } + } } \ No newline at end of file diff --git a/test-server/net-v3-transition-server/Controllers/ClientController.cs b/test-server/net-v3-transition-server/Controllers/ClientController.cs index 0746618e..e1a57229 100644 --- a/test-server/net-v3-transition-server/Controllers/ClientController.cs +++ b/test-server/net-v3-transition-server/Controllers/ClientController.cs @@ -67,6 +67,10 @@ public IActionResult CreateClient([FromBody] ClientRequest request) logger.LogInformation("[NET-V3-Transitional] Created encryptionAlgorithm= {encryptionAlgorithm}", encryptionAlgorithm); var configuration = new AmazonS3CryptoConfigurationV2(securityProfile, commitmentPolicy, encryptionAlgorithm); + if (request.Config.InstructionFileConfig?.EnableInstructionFilePutObject == true) + { + configuration.StorageMode = CryptoStorageMode.InstructionFile; + } // Create S3 encryption client var encryptionClient = new AmazonS3EncryptionClientV2(configuration, encryptionMaterial); // Add to cache and return client ID diff --git a/test-server/net-v3-transition-server/Models/ClientRequest.cs b/test-server/net-v3-transition-server/Models/ClientRequest.cs index 3c80fc59..07fe8520 100644 --- a/test-server/net-v3-transition-server/Models/ClientRequest.cs +++ b/test-server/net-v3-transition-server/Models/ClientRequest.cs @@ -21,6 +21,7 @@ public class ClientConfig public CommitmentPolicy? CommitmentPolicy { get; set; } [JsonPropertyName("encryptionAlgorithm")] public EncryptionAlgorithm? EncryptionAlgorithm { get; set; } + public InstructionFileConfig? InstructionFileConfig { get; set; } } public class KeyMaterial @@ -44,4 +45,11 @@ public enum EncryptionAlgorithm ALG_AES_256_CBC_IV16_NO_KDF, ALG_AES_256_GCM_IV12_TAG16_NO_KDF, ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY +} + +public class InstructionFileConfig +{ + public string? ClientId { get; set; } + public bool EnableInstructionFilePutObject { get; set; } = false; + public bool DisableInstructionFile { get; set; } = false; } \ No newline at end of file From 7e665e6462ad470de80c9419818f1530cf72e2a8 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 13 Nov 2025 14:20:08 -0800 Subject: [PATCH 03/10] auto commit --- .../Controllers/ClientController.cs | 23 +++++++++++-------- .../net-v2-v3-server/Models/ClientRequest.cs | 8 +++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/test-server/net-v2-v3-server/Controllers/ClientController.cs b/test-server/net-v2-v3-server/Controllers/ClientController.cs index 7e626e56..e33a58e6 100644 --- a/test-server/net-v2-v3-server/Controllers/ClientController.cs +++ b/test-server/net-v2-v3-server/Controllers/ClientController.cs @@ -18,11 +18,11 @@ public IActionResult CreateClient([FromBody] ClientRequest request) { // Return 501 for not implemented features by the server if (request.Config.EnableDelayedAuthenticationMode) - return StatusCode(501, new GenericServerError { Message = "EnableDelayedAuthenticationMode not supported" }); + return StatusCode(501, new GenericServerError { Message = "[NET-current] EnableDelayedAuthenticationMode not supported" }); if (request.Config.SetBufferSize.HasValue) - return StatusCode(501, new GenericServerError { Message = "SetBufferSize not supported" }); + return StatusCode(501, new GenericServerError { Message = "[NET-current] SetBufferSize not supported" }); if (request.Config.KeyMaterial.AesKey != null) - return StatusCode(501, new GenericServerError { Message = "AesKey not supported" }); + return StatusCode(501, new GenericServerError { Message = "[NET-current] AesKey not supported" }); try { @@ -36,7 +36,7 @@ public IActionResult CreateClient([FromBody] ClientRequest request) var kmsKeyId = request.Config.KeyMaterial.KmsKeyId; encryptionMaterial = new EncryptionMaterialsV2(kmsKeyId, KmsType.KmsContext, encryptionContext); logger.LogInformation( - "Created EncryptionMaterialsV2: KMS={KmsKeyId}", + "[NET-current] Created EncryptionMaterialsV2: KMS={KmsKeyId}", kmsKeyId); } else if (request.Config.KeyMaterial.RsaKey != null) @@ -49,7 +49,7 @@ public IActionResult CreateClient([FromBody] ClientRequest request) "Created EncryptionMaterialsV2: RSA"); } else { - return StatusCode(501, new GenericServerError { Message = "Unknown or missing key material!" }); + return StatusCode(501, new GenericServerError { Message = "[NET-current] Unknown or missing key material!" }); } var enableLegacyUnauthenticatedModes = request.Config.EnableLegacyUnauthenticatedModes; @@ -59,16 +59,21 @@ public IActionResult CreateClient([FromBody] ClientRequest request) var enableLegacyMode = enableLegacyUnauthenticatedModes || enableLegacyWrappingAlgorithms; var securityProfile = enableLegacyMode ? SecurityProfile.V2AndLegacy : SecurityProfile.V2; - logger.LogInformation("Created securityProfile= {securityProfile}", securityProfile.ToString()); + logger.LogInformation("[NET-current] Created securityProfile= {securityProfile}", securityProfile.ToString()); var configuration = new AmazonS3CryptoConfigurationV2(securityProfile); + if (request.Config.InstructionFileConfig?.EnableInstructionFilePutObject == true) + { + configuration.StorageMode = CryptoStorageMode.InstructionFile; + logger.LogInformation("[NET-current] Created StorageMode= InstructionFile"); + } // Create S3 encryption client var encryptionClient = new AmazonS3EncryptionClientV2(configuration, encryptionMaterial); // Add to cache and return client ID var clientId = clientCacheService.AddClient(encryptionClient); var response = new ClientResponse { ClientId = clientId }; - logger.LogInformation("Created S3EC client with ID: {clientId}", clientId); + logger.LogInformation("[NET-current] Created S3EC client with ID: {clientId}", clientId); return new ContentResult { @@ -79,10 +84,10 @@ public IActionResult CreateClient([FromBody] ClientRequest request) } catch (Exception ex) { - logger.LogError(ex, "Failed to create S3EC client"); + logger.LogError(ex, "[NET-current] Failed to create S3EC client"); return StatusCode(500, new S3EncryptionClientError { - Message = $"Failed to create client: {ex.Message}" + Message = $"[NET-current] Failed to create client: {ex.Message}" }); } } diff --git a/test-server/net-v2-v3-server/Models/ClientRequest.cs b/test-server/net-v2-v3-server/Models/ClientRequest.cs index 95644524..e51a9c25 100644 --- a/test-server/net-v2-v3-server/Models/ClientRequest.cs +++ b/test-server/net-v2-v3-server/Models/ClientRequest.cs @@ -16,6 +16,7 @@ public class ClientConfig public long? SetBufferSize { get; set; } [Required] public KeyMaterial KeyMaterial { get; set; } = new(); + public InstructionFileConfig? InstructionFileConfig { get; set; } } public class KeyMaterial @@ -23,4 +24,11 @@ public class KeyMaterial public byte[]? RsaKey { get; set; } public byte[]? AesKey { get; set; } public string? KmsKeyId { get; set; } +} + +public class InstructionFileConfig +{ + public string? ClientId { get; set; } + public bool EnableInstructionFilePutObject { get; set; } = false; + public bool DisableInstructionFile { get; set; } = false; } \ No newline at end of file From 9d06fcebdeabcfa98cf57160e19f4e6de75ab052 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 13 Nov 2025 14:22:52 -0800 Subject: [PATCH 04/10] auto commit --- .../amazon/encryption/s3/RoundTripTests.java | 12 +++++++----- .../Controllers/ClientController.cs | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java index a218d696..e9c6a42b 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java @@ -30,6 +30,7 @@ import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.encryption.s3.TestUtils.LanguageServerTarget; import software.amazon.encryption.s3.client.S3ECTestServerClient; import software.amazon.encryption.s3.model.CommitmentPolicy; import software.amazon.encryption.s3.model.CreateClientInput; @@ -612,7 +613,7 @@ public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageSe @ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {1}") @MethodSource("software.amazon.encryption.s3.TestUtils#crossLanguageClients") - public void rsaWithInstructionFileRoundTrip(LanguageServerTarget encLang, LanguageServerTarget decLang) { + public void rsaWithInstructionFileRoundTrip(LanguageServerTarget encLang, LanguageServerTarget decLang) throws Exception { if (!RAW_SUPPORTED.contains(encLang.getLanguageName())) { throw new TestAbortedException("not encrypting raw keyrings with: " + encLang.getLanguageName()); } @@ -621,12 +622,15 @@ public void rsaWithInstructionFileRoundTrip(LanguageServerTarget encLang, Langua } S3ECTestServerClient encClient = testServerClientFor(encLang); S3ECTestServerClient decClient = testServerClientFor(decLang); - final String objectKey = appendTestSuffix(String.format("rsa-with-ins-file-write-%s-read-%s", encLang.getLanguageName(), decLang.getLanguageName())); - final String input = "simple-test-input"; + final String objectKey = appendTestSuffix(String.format("rsa-insfile-write-%s-read-%s", encLang.getLanguageName(), decLang.getLanguageName())); + final String input = "simple-test-input-rsa"; KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(2048); KeyPair RSA_KEY_PAIR_1 = keyPairGen.generateKeyPair(); + KeyMaterial rsaKeyOne = KeyMaterial.builder() + .rsaKey(ByteBuffer.wrap(RSA_KEY_PAIR_1.getPrivate().getEncoded())) + .build(); CreateClientOutput encClientOutput = encClient.createClient(CreateClientInput.builder() .config(S3ECConfig.builder() .instructionFileConfig(InstructionFileConfig.builder() @@ -666,8 +670,6 @@ public void rsaWithInstructionFileRoundTrip(LanguageServerTarget encLang, Langua } // Check for inst file key if (!encLang.getLanguageName().startsWith("Ruby") && !encLang.getLanguageName().startsWith("PHP")) { - // Ruby and PHP do not include it :( - assertTrue(ptInstFile.response().metadata().containsKey("x-amz-crypto-instr-file")); assertFalse(ptInstFile.asUtf8String().isEmpty()); // Read should be enabled by default GetObjectOutput output = decClient.getObject(GetObjectInput.builder() diff --git a/test-server/net-v3-transition-server/Controllers/ClientController.cs b/test-server/net-v3-transition-server/Controllers/ClientController.cs index e1a57229..a66fb342 100644 --- a/test-server/net-v3-transition-server/Controllers/ClientController.cs +++ b/test-server/net-v3-transition-server/Controllers/ClientController.cs @@ -70,6 +70,7 @@ public IActionResult CreateClient([FromBody] ClientRequest request) if (request.Config.InstructionFileConfig?.EnableInstructionFilePutObject == true) { configuration.StorageMode = CryptoStorageMode.InstructionFile; + logger.LogInformation("[NET-V3-Transitional] Created StorageMode= InstructionFile"); } // Create S3 encryption client var encryptionClient = new AmazonS3EncryptionClientV2(configuration, encryptionMaterial); From 234cf95225d1b3db245b4a3b81dc9de436f097de Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 13 Nov 2025 15:55:42 -0800 Subject: [PATCH 05/10] auto commit --- .../amazon/encryption/s3/KC_GCMTests.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java index 99e8d37d..5b5c8e44 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java @@ -13,6 +13,8 @@ import java.lang.annotation.ElementType; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.security.KeyPair; +import java.security.KeyPairGenerator; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -27,6 +29,7 @@ import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; +import org.opentest4j.TestAbortedException; import software.amazon.encryption.s3.client.S3ECTestServerClient; import software.amazon.encryption.s3.model.CommitmentPolicy; import software.amazon.encryption.s3.model.CreateClientInput; @@ -34,6 +37,7 @@ import software.amazon.encryption.s3.model.EncryptionAlgorithm; import software.amazon.encryption.s3.model.GetObjectInput; import software.amazon.encryption.s3.model.GetObjectOutput; +import software.amazon.encryption.s3.model.InstructionFileConfig; import software.amazon.encryption.s3.model.KeyMaterial; import software.amazon.encryption.s3.model.PutObjectInput; import software.amazon.encryption.s3.model.S3ECConfig; @@ -60,10 +64,20 @@ @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class KC_GCMTests { private static String sharedObjectKeyBase = "test-kc-gcm-kms"; + private static String sharedObjectKeyBaseInstructionFile = "test-kc-gcm-kms-instruction-file"; private static KeyMaterial kmsKeyArn = KeyMaterial.builder() .kmsKeyId(TestUtils.KMS_KEY_ARN) .build(); private static List crossLanguageObjects = new ArrayList<>(); + private static List crossLanguageObjectsInstructionFiles = new ArrayList<>(); + private static KeyPair RSA_KEY_PAIR_1; + + @BeforeAll + static void setupKeys() throws Exception { + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); + keyPairGen.initialize(2048); + RSA_KEY_PAIR_1 = keyPairGen.generateKeyPair(); + } @Order(1) @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptAllowDecrypt should encrypt KC-GCM") @@ -81,6 +95,29 @@ void improved_configured_with_require_encrypt_allow_decrypt_should_encrypt_kc_gc TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBase + language.getLanguageName()), crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } + @Order(2) + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should encrypt KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") + void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_gcm_ins_file(TestUtils.LanguageServerTarget language) { + KeyMaterial rsaKeyOne = KeyMaterial.builder() + .rsaKey(ByteBuffer.wrap(RSA_KEY_PAIR_1.getPrivate().getEncoded())) + .build(); + + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .instructionFileConfig(InstructionFileConfig.builder() + .enableInstructionFilePutObject(true) + .build()) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .keyMaterial(rsaKeyOne).build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseInstructionFile + language.getLanguageName()), crossLanguageObjectsInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } + @Order(2) @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should encrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") @@ -215,5 +252,32 @@ void improved_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.Langua TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } + + @Order(16) + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should encrypt KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") + void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_gcm_ins_file(TestUtils.LanguageServerTarget language) { + if (!RAW_SUPPORTED.contains(language.getLanguageName())) { + throw new TestAbortedException("not encrypting raw keyrings with: " + language.getLanguageName()); + } + + KeyMaterial rsaKeyOne = KeyMaterial.builder() + .rsaKey(ByteBuffer.wrap(RSA_KEY_PAIR_1.getPrivate().getEncoded())) + .build(); + + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .instructionFileConfig(InstructionFileConfig.builder() + .enableInstructionFilePutObject(true) + .build()) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .keyMaterial(rsaKeyOne).build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } } From 5612cedc6d3f279d4ef62f73e812dc68ce021214 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 13 Nov 2025 18:45:18 -0800 Subject: [PATCH 06/10] auto commit --- .../amazon/encryption/s3/KC_GCMTests.java | 57 ++++++------------- .../amazon/encryption/s3/RoundTripTests.java | 14 ++--- 2 files changed, 24 insertions(+), 47 deletions(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java index 5b5c8e44..0fa7f47f 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java @@ -5,26 +5,16 @@ package software.amazon.encryption.s3; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; import static software.amazon.encryption.s3.TestUtils.*; -import java.lang.annotation.ElementType; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.stream.Stream; -import com.amazonaws.services.s3.model.KMSEncryptionMaterials; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.MethodOrderer; @@ -35,22 +25,9 @@ import software.amazon.encryption.s3.model.CreateClientInput; import software.amazon.encryption.s3.model.CreateClientOutput; import software.amazon.encryption.s3.model.EncryptionAlgorithm; -import software.amazon.encryption.s3.model.GetObjectInput; -import software.amazon.encryption.s3.model.GetObjectOutput; import software.amazon.encryption.s3.model.InstructionFileConfig; import software.amazon.encryption.s3.model.KeyMaterial; -import software.amazon.encryption.s3.model.PutObjectInput; import software.amazon.encryption.s3.model.S3ECConfig; -import software.amazon.encryption.s3.model.S3EncryptionClientError; - -import com.amazonaws.services.s3.AmazonS3Encryption; -import com.amazonaws.services.s3.AmazonS3EncryptionClient; -import com.amazonaws.services.s3.model.CryptoConfiguration; -import com.amazonaws.services.s3.model.CryptoMode; -import com.amazonaws.services.s3.model.CryptoStorageMode; -import software.amazon.encryption.s3.TestUtils.*; -import com.amazonaws.services.s3.model.EncryptionMaterialsProvider; -import com.amazonaws.services.s3.model.KMSEncryptionMaterialsProvider; /** * Exhaustive tests for S3 Encryption Client round-trip operations. @@ -68,8 +45,8 @@ class KC_GCMTests { private static KeyMaterial kmsKeyArn = KeyMaterial.builder() .kmsKeyId(TestUtils.KMS_KEY_ARN) .build(); - private static List crossLanguageObjects = new ArrayList<>(); - private static List crossLanguageObjectsInstructionFiles = new ArrayList<>(); + private static final List crossLanguageObjectsMetaDataMode = new ArrayList<>(); + private static final List crossLanguageObjectsInstructionFiles = new ArrayList<>(); private static KeyPair RSA_KEY_PAIR_1; @BeforeAll @@ -92,14 +69,14 @@ void improved_configured_with_require_encrypt_allow_decrypt_should_encrypt_kc_gc .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBase + language.getLanguageName()), crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBase + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(2) @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should encrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_gcm_ins_file(TestUtils.LanguageServerTarget language) { - KeyMaterial rsaKeyOne = KeyMaterial.builder() + KeyMaterial rsaKey = KeyMaterial.builder() .rsaKey(ByteBuffer.wrap(RSA_KEY_PAIR_1.getPrivate().getEncoded())) .build(); @@ -111,7 +88,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_ .build()) .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY) .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) - .keyMaterial(rsaKeyOne).build()) + .keyMaterial(rsaKey).build()) .build()); String S3ECId = clientOutput.getClientId(); @@ -131,7 +108,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_ .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBase + language.getLanguageName()), crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBase + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(2) @@ -147,7 +124,7 @@ void improved_configured_with_the_default_should_encrypt_kc_gcm(TestUtils.Langua .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBase + language.getLanguageName()), crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBase + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(10) @@ -164,7 +141,7 @@ void transition_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.Lang .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(11) @@ -181,7 +158,7 @@ void transition_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_g .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(12) @@ -199,7 +176,7 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_gcm .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(13) @@ -216,7 +193,7 @@ void improved_configured_with_require_encrypt_allow_decrypt_should_decrypt_kc_gc .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(14) @@ -233,7 +210,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_ .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(15) @@ -250,18 +227,18 @@ void improved_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.Langua .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(16) @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should encrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") - void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_gcm_ins_file(TestUtils.LanguageServerTarget language) { + void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_gcm_ins_file(final TestUtils.LanguageServerTarget language) { if (!RAW_SUPPORTED.contains(language.getLanguageName())) { - throw new TestAbortedException("not encrypting raw keyrings with: " + language.getLanguageName()); + throw new TestAbortedException("Not encrypting raw keyring with: " + language.getLanguageName()); } - KeyMaterial rsaKeyOne = KeyMaterial.builder() + KeyMaterial rsaKey = KeyMaterial.builder() .rsaKey(ByteBuffer.wrap(RSA_KEY_PAIR_1.getPrivate().getEncoded())) .build(); @@ -273,7 +250,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_ .build()) .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY) .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) - .keyMaterial(rsaKeyOne).build()) + .keyMaterial(rsaKey).build()) .build()); String S3ECId = clientOutput.getClientId(); diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java index e9c6a42b..5e06d4db 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java @@ -613,12 +613,12 @@ public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageSe @ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {1}") @MethodSource("software.amazon.encryption.s3.TestUtils#crossLanguageClients") - public void rsaWithInstructionFileRoundTrip(LanguageServerTarget encLang, LanguageServerTarget decLang) throws Exception { + public void instructionFileWriteAndReadWithRSA(LanguageServerTarget encLang, LanguageServerTarget decLang) throws Exception { if (!RAW_SUPPORTED.contains(encLang.getLanguageName())) { - throw new TestAbortedException("not encrypting raw keyrings with: " + encLang.getLanguageName()); + throw new TestAbortedException("not encrypting raw keyring with: " + encLang.getLanguageName()); } if (!RAW_SUPPORTED.contains(decLang.getLanguageName())) { - throw new TestAbortedException("not decrypting raw keyrings with: " + decLang.getLanguageName()); + throw new TestAbortedException("not decrypting raw keyring with: " + decLang.getLanguageName()); } S3ECTestServerClient encClient = testServerClientFor(encLang); S3ECTestServerClient decClient = testServerClientFor(decLang); @@ -636,8 +636,8 @@ public void rsaWithInstructionFileRoundTrip(LanguageServerTarget encLang, Langua .instructionFileConfig(InstructionFileConfig.builder() .enableInstructionFilePutObject(true) .build()) - .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY) - .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) .keyMaterial(rsaKeyOne).build()) .build()); String encS3ECId = encClientOutput.getClientId(); @@ -646,8 +646,8 @@ public void rsaWithInstructionFileRoundTrip(LanguageServerTarget encLang, Langua .instructionFileConfig(InstructionFileConfig.builder() .enableInstructionFilePutObject(true) .build()) - .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY) - .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) .keyMaterial(rsaKeyOne).build()) .build()); String decS3ECId = decClientOutput.getClientId(); From 74bddeb8c50b47f81f3e78a4e7487ede6b0991d5 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 13 Nov 2025 18:46:00 -0800 Subject: [PATCH 07/10] auto commit --- .../src/it/java/software/amazon/encryption/s3/TestUtils.java | 1 - 1 file changed, 1 deletion(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java index c20fd5a6..adcc4a83 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java @@ -6,7 +6,6 @@ package software.amazon.encryption.s3; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; import java.net.Socket; import java.net.URI; From 0332165f50cdd62e6224aa0ec50fe1b801c3aa27 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 13 Nov 2025 18:51:18 -0800 Subject: [PATCH 08/10] auto commit --- .../amazon/encryption/s3/RoundTripTests.java | 108 +++++++++--------- 1 file changed, 53 insertions(+), 55 deletions(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java index 5e06d4db..e14844cb 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java @@ -599,86 +599,84 @@ public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageSe if (!encLang.getLanguageName().startsWith("Ruby") && !encLang.getLanguageName().startsWith("PHP")) { // Ruby and PHP do not include it :( assertTrue(ptInstFile.response().metadata().containsKey("x-amz-crypto-instr-file")); - assertFalse(ptInstFile.asUtf8String().isEmpty()); - // Read should be enabled by default - GetObjectOutput output = decClient.getObject(GetObjectInput.builder() - .clientID(decS3ECId) - .bucket(BUCKET) - .key(objectKey) - .build()); - - assertEquals(input, new String(output.getBody().array())); } + assertFalse(ptInstFile.asUtf8String().isEmpty()); + // Read should be enabled by default + GetObjectOutput output = decClient.getObject(GetObjectInput.builder() + .clientID(decS3ECId) + .bucket(BUCKET) + .key(objectKey) + .build()); + + assertEquals(input, new String(output.getBody().array())); } @ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {1}") @MethodSource("software.amazon.encryption.s3.TestUtils#crossLanguageClients") public void instructionFileWriteAndReadWithRSA(LanguageServerTarget encLang, LanguageServerTarget decLang) throws Exception { + // Early validation if (!RAW_SUPPORTED.contains(encLang.getLanguageName())) { throw new TestAbortedException("not encrypting raw keyring with: " + encLang.getLanguageName()); } if (!RAW_SUPPORTED.contains(decLang.getLanguageName())) { throw new TestAbortedException("not decrypting raw keyring with: " + decLang.getLanguageName()); } - S3ECTestServerClient encClient = testServerClientFor(encLang); - S3ECTestServerClient decClient = testServerClientFor(decLang); - final String objectKey = appendTestSuffix(String.format("rsa-insfile-write-%s-read-%s", encLang.getLanguageName(), decLang.getLanguageName())); - final String input = "simple-test-input-rsa"; + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(2048); - KeyPair RSA_KEY_PAIR_1 = keyPairGen.generateKeyPair(); + KeyMaterial rsaKeyMaterial = KeyMaterial.builder() + .rsaKey(ByteBuffer.wrap(keyPairGen.generateKeyPair().getPrivate().getEncoded())) + .build(); + + S3ECConfig config = S3ECConfig.builder() + .instructionFileConfig(InstructionFileConfig.builder() + .enableInstructionFilePutObject(true) + .build()) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .keyMaterial(rsaKeyMaterial) + .build(); + + // Create clients + S3ECTestServerClient encClient = testServerClientFor(encLang); + S3ECTestServerClient decClient = testServerClientFor(decLang); - KeyMaterial rsaKeyOne = KeyMaterial.builder() - .rsaKey(ByteBuffer.wrap(RSA_KEY_PAIR_1.getPrivate().getEncoded())) - .build(); - CreateClientOutput encClientOutput = encClient.createClient(CreateClientInput.builder() - .config(S3ECConfig.builder() - .instructionFileConfig(InstructionFileConfig.builder() - .enableInstructionFilePutObject(true) - .build()) - .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) - .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) - .keyMaterial(rsaKeyOne).build()) - .build()); - String encS3ECId = encClientOutput.getClientId(); - CreateClientOutput decClientOutput = decClient.createClient(CreateClientInput.builder() - .config(S3ECConfig.builder() - .instructionFileConfig(InstructionFileConfig.builder() - .enableInstructionFilePutObject(true) - .build()) - .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) - .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) - .keyMaterial(rsaKeyOne).build()) - .build()); - String decS3ECId = decClientOutput.getClientId(); + String encS3ECId = encClient.createClient(CreateClientInput.builder().config(config).build()).getClientId(); + String decS3ECId = decClient.createClient(CreateClientInput.builder().config(config).build()).getClientId(); - // Write with instruction file + final String objectKey = appendTestSuffix(String.format("rsa-insfile-write-%s-read-%s", + encLang.getLanguageName(), decLang.getLanguageName())); + final String input = "simple-test-input-rsa"; + + // Encrypt encClient.putObject(PutObjectInput.builder() - .clientID(encS3ECId) - .bucket(BUCKET) - .key(objectKey) - .body(ByteBuffer.wrap(input.getBytes(StandardCharsets.UTF_8))) - .build()); + .clientID(encS3ECId) + .bucket(BUCKET) + .key(objectKey) + .body(ByteBuffer.wrap(input.getBytes(StandardCharsets.UTF_8))) + .build()); // Assert using Java plaintext client that an instruction file exists ResponseBytes ptInstFile; try (S3Client ptS3Client = S3Client.create()) { ptInstFile = ptS3Client.getObjectAsBytes(builder -> builder - .bucket(BUCKET) - .key(objectKey + ".instruction") - .build()); + .bucket(BUCKET) + .key(objectKey + ".instruction") + .build()); } // Check for inst file key if (!encLang.getLanguageName().startsWith("Ruby") && !encLang.getLanguageName().startsWith("PHP")) { - assertFalse(ptInstFile.asUtf8String().isEmpty()); - // Read should be enabled by default - GetObjectOutput output = decClient.getObject(GetObjectInput.builder() - .clientID(decS3ECId) - .bucket(BUCKET) - .key(objectKey) - .build()); - - assertEquals(input, new String(output.getBody().array())); + // Ruby and PHP do not include it :( + assertTrue(ptInstFile.response().metadata().containsKey("x-amz-crypto-instr-file")); } + assertFalse(ptInstFile.asUtf8String().isEmpty()); + // Read should be enabled by default + GetObjectOutput output = decClient.getObject(GetObjectInput.builder() + .clientID(decS3ECId) + .bucket(BUCKET) + .key(objectKey) + .build()); + + assertEquals(input, new String(output.getBody().array())); } } \ No newline at end of file From b34b3ca94b2ff306504eb895d4c8e989b8be1953 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 13 Nov 2025 19:33:08 -0800 Subject: [PATCH 09/10] auto commit --- .../amazon/encryption/s3/KC_GCMTests.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java index 0fa7f47f..c0f1dee7 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java @@ -40,8 +40,8 @@ @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class KC_GCMTests { - private static String sharedObjectKeyBase = "test-kc-gcm-kms"; - private static String sharedObjectKeyBaseInstructionFile = "test-kc-gcm-kms-instruction-file"; + private static final String sharedObjectKeyBaseMetaDataMode = "test-kc-gcm-kms"; + private static final String sharedObjectKeyBaseInsFileMode = "test-kc-gcm-kms-instruction-file"; private static KeyMaterial kmsKeyArn = KeyMaterial.builder() .kmsKeyId(TestUtils.KMS_KEY_ARN) .build(); @@ -69,13 +69,17 @@ void improved_configured_with_require_encrypt_allow_decrypt_should_encrypt_kc_gc .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBase + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(2) @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should encrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_gcm_ins_file(TestUtils.LanguageServerTarget language) { + if (!RAW_SUPPORTED.contains(language.getLanguageName())) { + throw new TestAbortedException("Not encrypting raw keyring with: " + language.getLanguageName()); + } + KeyMaterial rsaKey = KeyMaterial.builder() .rsaKey(ByteBuffer.wrap(RSA_KEY_PAIR_1.getPrivate().getEncoded())) .build(); @@ -92,7 +96,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_ .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseInstructionFile + language.getLanguageName()), crossLanguageObjectsInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseInsFileMode + language.getLanguageName()), crossLanguageObjectsInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(2) @@ -108,7 +112,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_ .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBase + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(2) @@ -124,7 +128,7 @@ void improved_configured_with_the_default_should_encrypt_kc_gcm(TestUtils.Langua .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBase + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(10) From f4c5e8577cdb64b7be6b5a638f30b9eeb89763a2 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 13 Nov 2025 19:37:30 -0800 Subject: [PATCH 10/10] auto commit --- .../java/software/amazon/encryption/s3/KC_GCMTests.java | 2 +- test-server/net-v4-server/Controllers/ClientController.cs | 6 ++++++ test-server/net-v4-server/Models/ClientRequest.cs | 8 ++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java index c0f1dee7..ee4279d6 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/KC_GCMTests.java @@ -79,7 +79,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_ if (!RAW_SUPPORTED.contains(language.getLanguageName())) { throw new TestAbortedException("Not encrypting raw keyring with: " + language.getLanguageName()); } - + KeyMaterial rsaKey = KeyMaterial.builder() .rsaKey(ByteBuffer.wrap(RSA_KEY_PAIR_1.getPrivate().getEncoded())) .build(); diff --git a/test-server/net-v4-server/Controllers/ClientController.cs b/test-server/net-v4-server/Controllers/ClientController.cs index 5298d758..b9fbe3f9 100644 --- a/test-server/net-v4-server/Controllers/ClientController.cs +++ b/test-server/net-v4-server/Controllers/ClientController.cs @@ -79,6 +79,12 @@ public IActionResult CreateClient([FromBody] ClientRequest request) ? new AmazonS3CryptoConfigurationV4() : new AmazonS3CryptoConfigurationV4(securityProfile, commitmentPolicy, encryptionAlgorithm); + if (request.Config.InstructionFileConfig?.EnableInstructionFilePutObject == true) + { + configuration.StorageMode = CryptoStorageMode.InstructionFile; + logger.LogInformation("[NET-V3-Transitional] Created StorageMode= InstructionFile"); + } + // Create S3 encryption client var encryptionClient = new AmazonS3EncryptionClientV4(configuration, encryptionMaterial); // Add to cache and return client ID diff --git a/test-server/net-v4-server/Models/ClientRequest.cs b/test-server/net-v4-server/Models/ClientRequest.cs index a5eff6f7..76623b9d 100644 --- a/test-server/net-v4-server/Models/ClientRequest.cs +++ b/test-server/net-v4-server/Models/ClientRequest.cs @@ -21,6 +21,7 @@ public class ClientConfig public CommitmentPolicy? CommitmentPolicy { get; set; } [JsonPropertyName("encryptionAlgorithm")] public EncryptionAlgorithm? EncryptionAlgorithm { get; set; } + public InstructionFileConfig? InstructionFileConfig { get; set; } } public class KeyMaterial @@ -44,4 +45,11 @@ public enum EncryptionAlgorithm ALG_AES_256_CBC_IV16_NO_KDF, ALG_AES_256_GCM_IV12_TAG16_NO_KDF, ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY +} + +public class InstructionFileConfig +{ + public string? ClientId { get; set; } + public bool EnableInstructionFilePutObject { get; set; } = false; + public bool DisableInstructionFile { get; set; } = false; } \ No newline at end of file