From b8ad6b037ef84eb24a6da2125d73c14b159a4367 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 13 Nov 2025 21:19:06 -0800 Subject: [PATCH 1/5] update test server --- .../Controllers/ClientController.cs | 23 +++++++++++-------- .../net-v2-v3-server/Models/ClientRequest.cs | 8 +++++++ .../Controllers/ClientController.cs | 5 ++++ .../Models/ClientRequest.cs | 8 +++++++ .../Controllers/ClientController.cs | 6 +++++ .../net-v4-server/Models/ClientRequest.cs | 8 +++++++ 6 files changed, 49 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 diff --git a/test-server/net-v3-transition-server/Controllers/ClientController.cs b/test-server/net-v3-transition-server/Controllers/ClientController.cs index 0746618e..a66fb342 100644 --- a/test-server/net-v3-transition-server/Controllers/ClientController.cs +++ b/test-server/net-v3-transition-server/Controllers/ClientController.cs @@ -67,6 +67,11 @@ 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; + logger.LogInformation("[NET-V3-Transitional] Created StorageMode= 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 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 From a40e6a1afd6455d355e046d9a4a27f01ba80f720 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 13 Nov 2025 21:22:16 -0800 Subject: [PATCH 2/5] update test --- .../amazon/encryption/s3/KC_GCMTests.java | 113 ++++++++++++------ .../amazon/encryption/s3/RoundTripTests.java | 86 +++++++++++-- .../amazon/encryption/s3/TestUtils.java | 1 - 3 files changed, 157 insertions(+), 43 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 99e8d37d..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 @@ -5,48 +5,29 @@ 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; 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; 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. @@ -59,11 +40,21 @@ @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class KC_GCMTests { - private static String sharedObjectKeyBase = "test-kc-gcm-kms"; + 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(); - private static List crossLanguageObjects = new ArrayList<>(); + private static final List crossLanguageObjectsMetaDataMode = new ArrayList<>(); + private static final 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") @@ -78,7 +69,34 @@ 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(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(); + + 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(rsaKey).build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseInsFileMode + language.getLanguageName()), crossLanguageObjectsInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(2) @@ -94,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()), crossLanguageObjects, 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) @@ -110,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()), crossLanguageObjects, 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) @@ -127,7 +145,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) @@ -144,7 +162,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) @@ -162,7 +180,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) @@ -179,7 +197,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) @@ -196,7 +214,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) @@ -213,7 +231,34 @@ 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(final 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(); + + 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(rsaKey).build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } } 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 59382006..67db4fef 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; @@ -595,15 +596,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()); + } + 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()); + } + + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); + keyPairGen.initialize(2048); + 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); + + String encS3ECId = encClient.createClient(CreateClientInput.builder().config(config).build()).getClientId(); + String decS3ECId = decClient.createClient(CreateClientInput.builder().config(config).build()).getClientId(); + + final String objectKey = appendTestSuffix(String.format("rsa-insfile-write-%s-read-%s", + encLang.getLanguageName(), decLang.getLanguageName())); + final String input = "simple-test-input-rsa"; - assertEquals(input, new String(output.getBody().array())); + // Encrypt + 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/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 7aa812bb..d3d25d58 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 34e139133b90446fdc3d2ea550c1b7a060a426b0 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Thu, 13 Nov 2025 23:02:07 -0800 Subject: [PATCH 3/5] auto commit --- .../amazon/encryption/s3/RoundTripTests.java | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 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 67db4fef..cf89b514 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 @@ -596,16 +596,16 @@ 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()); + 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())); + assertEquals(input, new String(output.getBody().array())); + } } @ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {1}") @@ -661,11 +661,7 @@ public void instructionFileWriteAndReadWithRSA(LanguageServerTarget encLang, Lan .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")); - } + 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() From 4b32c6563082580ef4fb3b5081ece7c9d44a6f19 Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Fri, 14 Nov 2025 09:30:22 -0800 Subject: [PATCH 4/5] auto commit --- .../software/amazon/encryption/s3/RoundTripTests.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 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 cf89b514..9a86bd45 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,10 +599,10 @@ public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageSe assertFalse(ptInstFile.asUtf8String().isEmpty()); // Read should be enabled by default GetObjectOutput output = decClient.getObject(GetObjectInput.builder() - .clientID(decS3ECId) - .bucket(BUCKET) - .key(objectKey) - .build()); + .clientID(decS3ECId) + .bucket(BUCKET) + .key(objectKey) + .build()); assertEquals(input, new String(output.getBody().array())); } From 61cff7107325bba282737cf1f84abed9e15b697d Mon Sep 17 00:00:00 2001 From: rishav-karanjit Date: Fri, 14 Nov 2025 09:36:59 -0800 Subject: [PATCH 5/5] auto commit --- .../software/amazon/encryption/s3/RoundTripTests.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 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 9a86bd45..6c26368d 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,10 +599,10 @@ public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageSe assertFalse(ptInstFile.asUtf8String().isEmpty()); // Read should be enabled by default GetObjectOutput output = decClient.getObject(GetObjectInput.builder() - .clientID(decS3ECId) - .bucket(BUCKET) - .key(objectKey) - .build()); + .clientID(decS3ECId) + .bucket(BUCKET) + .key(objectKey) + .build()); assertEquals(input, new String(output.getBody().array())); }