From 53a2865e8e3197e695b22766ea1753774360d3f8 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Thu, 16 Oct 2025 17:45:18 -0700 Subject: [PATCH 01/37] chore: s3ec v3 transtion and v4 improved tests --- .gitmodules | 5 +- .../amazon/encryption/s3/TestUtils.java | 4 +- .../java-v3-transition-server/Makefile | 3 +- .../s3/CreateClientOperationImpl.java | 60 ++++++++++++++++--- test-server/java-v4-server/Makefile | 3 +- test-server/java-v4-server/build.gradle.kts | 2 +- .../s3/CreateClientOperationImpl.java | 58 +++++++++++++++--- 7 files changed, 108 insertions(+), 27 deletions(-) diff --git a/.gitmodules b/.gitmodules index 0bf186eb..a0b240d5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -18,11 +18,12 @@ [submodule "test-server/java-v3-transition-server/s3ec-staging"] path = test-server/java-v3-transition-server/s3ec-staging url = git@github.com:aws/private-amazon-s3-encryption-client-java-staging.git - branch = s3ec/transitional + branch = imabhichow/s3ec-transition [submodule "test-server/java-v4-server/s3ec-staging"] path = test-server/java-v4-server/s3ec-staging url = git@github.com:aws/private-amazon-s3-encryption-client-java-staging.git - branch = s3ec/improved + branch = imabhichow/add-kc +; branch = s3ec/improved [submodule "test-server/specification"] path = test-server/specification url = git@github.com:awslabs/private-aws-encryption-sdk-specification-staging.git 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 78cb6eb2..4c950699 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 @@ -109,7 +109,7 @@ public class TestUtils { public static final Set TRANSITION_VERSIONS = Set.of( - // JAVA_V3_TRANSITION, + JAVA_V3_TRANSITION, // GO_V3_TRANSITION, // NET_V2_TRANSITION, // CPP_V2_TRANSITION, @@ -119,7 +119,7 @@ public class TestUtils { public static final Set IMPROVED_VERSIONS = Set.of( - // JAVA_V4, + JAVA_V4, // PYTHON_V3, GO_V4, // NET_V3, diff --git a/test-server/java-v3-transition-server/Makefile b/test-server/java-v3-transition-server/Makefile index b4371d0a..d76bbd99 100644 --- a/test-server/java-v3-transition-server/Makefile +++ b/test-server/java-v3-transition-server/Makefile @@ -7,8 +7,7 @@ PORT := 8094 build-s3ec: @echo "Building S3EC from source..." - cd s3ec-staging && mvn --batch-mode -no-transfer-progress clean compile - cd s3ec-staging && mvn -B -ntp install -DskipTests + cd s3ec-staging && mvn --batch-mode -no-transfer-progress clean compile && mvn -B -ntp install -DskipTests @echo "S3EC build completed." start-server: build-s3ec diff --git a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index d992c435..ffaefaf9 100644 --- a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -1,20 +1,19 @@ package software.amazon.encryption.s3; -import software.amazon.awssdk.core.traits.Trait; import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.encryption.s3.S3EncryptionClient; +import software.amazon.encryption.s3.algorithms.AlgorithmSuite; import software.amazon.encryption.s3.materials.AesKeyring; import software.amazon.encryption.s3.materials.Keyring; import software.amazon.encryption.s3.materials.KmsKeyring; import software.amazon.encryption.s3.materials.PartialRsaKeyPair; import software.amazon.encryption.s3.materials.RsaKeyring; -import software.amazon.smithy.java.core.schema.Schema; -import software.amazon.smithy.java.server.RequestContext; 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.GenericServerError; import software.amazon.encryption.s3.model.KeyMaterial; import software.amazon.encryption.s3.service.CreateClientOperation; +import software.amazon.smithy.java.server.RequestContext; import javax.crypto.spec.SecretKeySpec; import java.io.PrintWriter; @@ -23,11 +22,12 @@ import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; -import java.util.Arrays; import java.util.Map; -import java.util.Optional; import java.util.UUID; +import static software.amazon.encryption.s3.CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT; +import static software.amazon.encryption.s3.model.EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; + public class CreateClientOperationImpl implements CreateClientOperation { private Map clientCache_; @@ -88,9 +88,27 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c } else { throw new RuntimeException("No KeyMaterial found!"); } - S3Client s3Client = S3EncryptionClient.builder() - .keyring(keyring) - .build(); + // V3-Transitional (FireEgg Transition) server configuration + S3EncryptionClient.Builder clientBuilder = S3EncryptionClient.builder() + .keyring(keyring); + + // Configure commitment policy if provided (FireEgg feature) + if (input.getConfig().getCommitmentPolicy() != null) { + CommitmentPolicy policy = getCommitmentPolicy(input); + clientBuilder.commitmentPolicy(policy); + } + // V3-Transitional default: No commitment policy (null) for backward compatibility + + // Configure encryption algorithm if provided (FireEgg feature) + if (input.getConfig().getEncryptionAlgorithm() != null) { + AlgorithmSuite algorithm = getAlgorithmSuite(input); + clientBuilder.encryptionAlgorithm(algorithm); + } else { + // V3-Transitional default: Legacy algorithm for backward compatibility + clientBuilder.encryptionAlgorithm(AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); + } + + S3Client s3Client = clientBuilder.build(); UUID uuid = UUID.randomUUID(); String uuidString = uuid.toString(); clientCache_.put(uuidString, s3Client); @@ -106,4 +124,28 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c .build(); } } + + private static AlgorithmSuite getAlgorithmSuite(CreateClientInput input) { + if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF)) { + return AlgorithmSuite.ALG_AES_256_CBC_IV16_NO_KDF; + } else if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF)) { + return AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; + } else if (input.getConfig().getEncryptionAlgorithm().equals(ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)) { + return AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; + } else { + throw new RuntimeException("Unknown encryption algorithm: " + input.getConfig().getEncryptionAlgorithm()); + } + } + + private static software.amazon.encryption.s3.CommitmentPolicy getCommitmentPolicy(CreateClientInput input) { + if (input.getConfig().getCommitmentPolicy().equals(software.amazon.encryption.s3.model.CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)) { + return FORBID_ENCRYPT_ALLOW_DECRYPT; + } else if (input.getConfig().getCommitmentPolicy().equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT)) { + return null; + } else if (input.getConfig().getCommitmentPolicy().equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)) { + return null; + } else { + throw new RuntimeException("Unknown commitment policy: " + input.getConfig().getCommitmentPolicy()); + } + } } diff --git a/test-server/java-v4-server/Makefile b/test-server/java-v4-server/Makefile index 922499f7..f9123626 100644 --- a/test-server/java-v4-server/Makefile +++ b/test-server/java-v4-server/Makefile @@ -7,8 +7,7 @@ PORT := 8090 build-s3ec: @echo "Building S3EC from source..." - cd s3ec-staging && mvn --batch-mode -no-transfer-progress clean compile - cd s3ec-staging && mvn -B -ntp install -DskipTests + cd s3ec-staging && mvn --batch-mode -no-transfer-progress clean compile && mvn -B -ntp install -DskipTests @echo "S3EC build completed." start-server: build-s3ec diff --git a/test-server/java-v4-server/build.gradle.kts b/test-server/java-v4-server/build.gradle.kts index de3ea1f3..fcb3c3ca 100644 --- a/test-server/java-v4-server/build.gradle.kts +++ b/test-server/java-v4-server/build.gradle.kts @@ -14,7 +14,7 @@ dependencies { implementation("software.amazon.smithy.java:aws-server-restjson:$smithyJavaVersion") // S3EC from local Maven repository (installed by mvn install) - implementation("software.amazon.encryption.s3:amazon-s3-encryption-client-java:3.4.0-IMPROVED") + implementation("software.amazon.encryption.s3:amazon-s3-encryption-client-java:3.4.0-add-kc") } // Use that application plugin to start the service via the `run` task. diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index d992c435..fd4a6091 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -1,20 +1,19 @@ package software.amazon.encryption.s3; -import software.amazon.awssdk.core.traits.Trait; import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.encryption.s3.S3EncryptionClient; +import software.amazon.encryption.s3.algorithms.AlgorithmSuite; import software.amazon.encryption.s3.materials.AesKeyring; import software.amazon.encryption.s3.materials.Keyring; import software.amazon.encryption.s3.materials.KmsKeyring; import software.amazon.encryption.s3.materials.PartialRsaKeyPair; import software.amazon.encryption.s3.materials.RsaKeyring; -import software.amazon.smithy.java.core.schema.Schema; -import software.amazon.smithy.java.server.RequestContext; 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.GenericServerError; import software.amazon.encryption.s3.model.KeyMaterial; import software.amazon.encryption.s3.service.CreateClientOperation; +import software.amazon.smithy.java.server.RequestContext; import javax.crypto.spec.SecretKeySpec; import java.io.PrintWriter; @@ -23,11 +22,14 @@ import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; -import java.util.Arrays; import java.util.Map; -import java.util.Optional; import java.util.UUID; +import static software.amazon.encryption.s3.CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT; +import static software.amazon.encryption.s3.CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT; +import static software.amazon.encryption.s3.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT; +import static software.amazon.encryption.s3.model.EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; + public class CreateClientOperationImpl implements CreateClientOperation { private Map clientCache_; @@ -88,9 +90,23 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c } else { throw new RuntimeException("No KeyMaterial found!"); } - S3Client s3Client = S3EncryptionClient.builder() - .keyring(keyring) - .build(); + // V4-Improved (FireEgg Improved) server configuration + S3EncryptionClient.Builder clientBuilder = S3EncryptionClient.builder() + .keyring(keyring); + + // Configure commitment policy if provided (FireEgg feature) + if (input.getConfig().getCommitmentPolicy() != null) { + software.amazon.encryption.s3.CommitmentPolicy policy = getCommitmentPolicy(input); + clientBuilder.commitmentPolicy(policy); + } + + // Configure encryption algorithm if provided (FireEgg feature) + if (input.getConfig().getEncryptionAlgorithm() != null) { + AlgorithmSuite algorithm = getAlgorithmSuite(input); + clientBuilder.encryptionAlgorithm(algorithm); + } + + S3Client s3Client = clientBuilder.build(); UUID uuid = UUID.randomUUID(); String uuidString = uuid.toString(); clientCache_.put(uuidString, s3Client); @@ -106,4 +122,28 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c .build(); } } + + private static AlgorithmSuite getAlgorithmSuite(CreateClientInput input) { + if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF)) { + return AlgorithmSuite.ALG_AES_256_CBC_IV16_NO_KDF; + } else if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF)) { + return AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; + } else if (input.getConfig().getEncryptionAlgorithm().equals(ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)) { + return AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; + } else { + throw new RuntimeException("Unknown encryption algorithm: " + input.getConfig().getEncryptionAlgorithm()); + } + } + + private static software.amazon.encryption.s3.CommitmentPolicy getCommitmentPolicy(CreateClientInput input) { + if (input.getConfig().getCommitmentPolicy().equals(software.amazon.encryption.s3.model.CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)) { + return FORBID_ENCRYPT_ALLOW_DECRYPT; + } else if (input.getConfig().getCommitmentPolicy().equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT)) { + return REQUIRE_ENCRYPT_ALLOW_DECRYPT; + } else if (input.getConfig().getCommitmentPolicy().equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)) { + return REQUIRE_ENCRYPT_REQUIRE_DECRYPT; + } else { + throw new RuntimeException("Unknown commitment policy: " + input.getConfig().getCommitmentPolicy()); + } + } } From 1e5b2eae236dd599dbc085e123bb8b9ce920af8f Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Mon, 27 Oct 2025 08:40:57 -0700 Subject: [PATCH 02/37] comment cpp checkout --- .github/workflows/test.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8c8a9616..ddf8cfe1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,14 +27,14 @@ jobs: # ask Ryan to edit this PAT's permissions to add access to a new private repo. token: ${{ secrets.PAT_FOR_PRIVATE_RUBY }} - - name: Checkout CPP code - uses: actions/checkout@v5 - with: - submodules: recursive - token: ${{ secrets.PAT_FOR_CPP }} - repository: awslabs/aws-sdk-cpp-staging - ref: fire-egg-dev - path: test-server/cpp-v2-transition-server/aws-sdk-cpp/ +# - name: Checkout CPP code +# uses: actions/checkout@v5 +# with: +# submodules: recursive +# token: ${{ secrets.PAT_FOR_CPP }} +# repository: awslabs/aws-sdk-cpp-staging +# ref: fire-egg-dev +# path: test-server/cpp-v2-transition-server/aws-sdk-cpp/ - name: Checkout .NET V2 code uses: actions/checkout@v5 From e0e7ab360479af1cbeb137499ad0191d05767773 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Mon, 27 Oct 2025 09:14:43 -0700 Subject: [PATCH 03/37] bump s3ec-java commits --- test-server/java-v3-transition-server/s3ec-staging | 2 +- test-server/java-v4-server/s3ec-staging | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test-server/java-v3-transition-server/s3ec-staging b/test-server/java-v3-transition-server/s3ec-staging index d20064ea..ca2e4ea7 160000 --- a/test-server/java-v3-transition-server/s3ec-staging +++ b/test-server/java-v3-transition-server/s3ec-staging @@ -1 +1 @@ -Subproject commit d20064ea735016288b362bfbf9b0d7cd12115feb +Subproject commit ca2e4ea7c18f5ab5c1000d725ca8c982dd83d4d9 diff --git a/test-server/java-v4-server/s3ec-staging b/test-server/java-v4-server/s3ec-staging index a48d2b8d..9752c509 160000 --- a/test-server/java-v4-server/s3ec-staging +++ b/test-server/java-v4-server/s3ec-staging @@ -1 +1 @@ -Subproject commit a48d2b8d951246fef0363dd3ef2bd82c4bf04988 +Subproject commit 9752c5096540894e046348b8db24b9ce712829e3 From 5dbb01906eab931094d3af5941ebb29505bd0b42 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Tue, 30 Sep 2025 15:58:08 -0700 Subject: [PATCH 04/37] chore: add duvet reports for s3ec-java (transition & improved) --- .../.duvet/.gitignore | 3 +++ .../.duvet/config.toml | 21 +++++++++++++++++++ .../java-v3-transition-server/.gitignore | 1 + .../java-v3-transition-server/Makefile | 6 ++++++ test-server/java-v4-server/.duvet/.gitignore | 3 +++ test-server/java-v4-server/.duvet/config.toml | 21 +++++++++++++++++++ test-server/java-v4-server/.gitignore | 1 + test-server/java-v4-server/Makefile | 6 ++++++ 8 files changed, 62 insertions(+) create mode 100644 test-server/java-v3-transition-server/.duvet/.gitignore create mode 100644 test-server/java-v3-transition-server/.duvet/config.toml create mode 100644 test-server/java-v3-transition-server/.gitignore create mode 100644 test-server/java-v4-server/.duvet/.gitignore create mode 100644 test-server/java-v4-server/.duvet/config.toml create mode 100644 test-server/java-v4-server/.gitignore diff --git a/test-server/java-v3-transition-server/.duvet/.gitignore b/test-server/java-v3-transition-server/.duvet/.gitignore new file mode 100644 index 00000000..93956e36 --- /dev/null +++ b/test-server/java-v3-transition-server/.duvet/.gitignore @@ -0,0 +1,3 @@ +reports/ +requirements/ +specification/ \ No newline at end of file diff --git a/test-server/java-v3-transition-server/.duvet/config.toml b/test-server/java-v3-transition-server/.duvet/config.toml new file mode 100644 index 00000000..b38762ab --- /dev/null +++ b/test-server/java-v3-transition-server/.duvet/config.toml @@ -0,0 +1,21 @@ +'$schema' = "https://awslabs.github.io/duvet/config/v0.4.0.json" + +[[source]] +pattern = "**/*.java" + +# Include required specifications here +[[specification]] +source = "../specification/s3-encryption/data-format/content-metadata.md" +[[specification]] +source = "../specification/s3-encryption/data-format/metadata-strategy.md" +[[specification]] +source = "../specification/s3-encryption/encryption.md" +[[specification]] +source = "../specification/s3-encryption/key-derivation.md" + +[report.html] +enabled = true + +# Enable snapshots to prevent requirement coverage regressions +[report.snapshot] +enabled = false diff --git a/test-server/java-v3-transition-server/.gitignore b/test-server/java-v3-transition-server/.gitignore new file mode 100644 index 00000000..e660fd93 --- /dev/null +++ b/test-server/java-v3-transition-server/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/test-server/java-v3-transition-server/Makefile b/test-server/java-v3-transition-server/Makefile index d76bbd99..1b354c3d 100644 --- a/test-server/java-v3-transition-server/Makefile +++ b/test-server/java-v3-transition-server/Makefile @@ -27,3 +27,9 @@ stop-server: wait-for-server: $(MAKE) -C .. wait-for-port PORT=$(PORT) + +duvet: + duvet report + +view-report-mac: + open .duvet/reports/report.html \ No newline at end of file diff --git a/test-server/java-v4-server/.duvet/.gitignore b/test-server/java-v4-server/.duvet/.gitignore new file mode 100644 index 00000000..93956e36 --- /dev/null +++ b/test-server/java-v4-server/.duvet/.gitignore @@ -0,0 +1,3 @@ +reports/ +requirements/ +specification/ \ No newline at end of file diff --git a/test-server/java-v4-server/.duvet/config.toml b/test-server/java-v4-server/.duvet/config.toml new file mode 100644 index 00000000..b38762ab --- /dev/null +++ b/test-server/java-v4-server/.duvet/config.toml @@ -0,0 +1,21 @@ +'$schema' = "https://awslabs.github.io/duvet/config/v0.4.0.json" + +[[source]] +pattern = "**/*.java" + +# Include required specifications here +[[specification]] +source = "../specification/s3-encryption/data-format/content-metadata.md" +[[specification]] +source = "../specification/s3-encryption/data-format/metadata-strategy.md" +[[specification]] +source = "../specification/s3-encryption/encryption.md" +[[specification]] +source = "../specification/s3-encryption/key-derivation.md" + +[report.html] +enabled = true + +# Enable snapshots to prevent requirement coverage regressions +[report.snapshot] +enabled = false diff --git a/test-server/java-v4-server/.gitignore b/test-server/java-v4-server/.gitignore new file mode 100644 index 00000000..e660fd93 --- /dev/null +++ b/test-server/java-v4-server/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/test-server/java-v4-server/Makefile b/test-server/java-v4-server/Makefile index f9123626..fa3f9ce8 100644 --- a/test-server/java-v4-server/Makefile +++ b/test-server/java-v4-server/Makefile @@ -27,3 +27,9 @@ stop-server: wait-for-server: $(MAKE) -C .. wait-for-port PORT=$(PORT) + +duvet: + duvet report + +view-report-mac: + open .duvet/reports/report.html \ No newline at end of file From ddfdb9bbf877e8d3c4bea45b1c9b320b1504d744 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Mon, 27 Oct 2025 10:44:55 -0700 Subject: [PATCH 05/37] format --- test-server/java-v3-transition-server/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-server/java-v3-transition-server/Makefile b/test-server/java-v3-transition-server/Makefile index 1b354c3d..3f0358c9 100644 --- a/test-server/java-v3-transition-server/Makefile +++ b/test-server/java-v3-transition-server/Makefile @@ -11,13 +11,13 @@ build-s3ec: @echo "S3EC build completed." start-server: build-s3ec - @echo "Starting Java V3 server..." + @echo "Starting Java V3 Transition server..." AWS_ACCESS_KEY_ID="$$AWS_ACCESS_KEY_ID" \ AWS_SECRET_ACCESS_KEY="$$AWS_SECRET_ACCESS_KEY" \ AWS_SESSION_TOKEN="$$AWS_SESSION_TOKEN" \ AWS_REGION="us-west-2" \ ./gradlew --build-cache --parallel run & echo $$! > $(PID_FILE) - @echo "Java V3 server starting..." + @echo "Java V3 Transition server starting..." stop-server: @if [ -f $(PID_FILE) ]; then \ From 009d1b21a4badbb0be357a688327b2420cfd94fd Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Mon, 27 Oct 2025 13:16:39 -0700 Subject: [PATCH 06/37] git-ignore --- test-server/java-v3-server/.duvet/config.toml | 2 +- test-server/java-v3-transition-server/.duvet/.gitignore | 3 --- test-server/java-v3-transition-server/.duvet/config.toml | 6 +++++- test-server/java-v4-server/.duvet/.gitignore | 3 --- test-server/java-v4-server/.duvet/config.toml | 6 +++++- 5 files changed, 11 insertions(+), 9 deletions(-) delete mode 100644 test-server/java-v3-transition-server/.duvet/.gitignore delete mode 100644 test-server/java-v4-server/.duvet/.gitignore diff --git a/test-server/java-v3-server/.duvet/config.toml b/test-server/java-v3-server/.duvet/config.toml index b38762ab..0a83ed64 100644 --- a/test-server/java-v3-server/.duvet/config.toml +++ b/test-server/java-v3-server/.duvet/config.toml @@ -1,7 +1,7 @@ '$schema' = "https://awslabs.github.io/duvet/config/v0.4.0.json" [[source]] -pattern = "**/*.java" +pattern = "s3ec-staging/*.java" # Include required specifications here [[specification]] diff --git a/test-server/java-v3-transition-server/.duvet/.gitignore b/test-server/java-v3-transition-server/.duvet/.gitignore deleted file mode 100644 index 93956e36..00000000 --- a/test-server/java-v3-transition-server/.duvet/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -reports/ -requirements/ -specification/ \ No newline at end of file diff --git a/test-server/java-v3-transition-server/.duvet/config.toml b/test-server/java-v3-transition-server/.duvet/config.toml index b38762ab..eef14984 100644 --- a/test-server/java-v3-transition-server/.duvet/config.toml +++ b/test-server/java-v3-transition-server/.duvet/config.toml @@ -1,7 +1,7 @@ '$schema' = "https://awslabs.github.io/duvet/config/v0.4.0.json" [[source]] -pattern = "**/*.java" +pattern = "s3ec-staging/*.java" # Include required specifications here [[specification]] @@ -11,7 +11,11 @@ source = "../specification/s3-encryption/data-format/metadata-strategy.md" [[specification]] source = "../specification/s3-encryption/encryption.md" [[specification]] +source = "../specification/s3-encryption/decryption.md" +[[specification]] source = "../specification/s3-encryption/key-derivation.md" +[[specification]] +source = "../specification/s3-encryption/key-commitment.md" [report.html] enabled = true diff --git a/test-server/java-v4-server/.duvet/.gitignore b/test-server/java-v4-server/.duvet/.gitignore deleted file mode 100644 index 93956e36..00000000 --- a/test-server/java-v4-server/.duvet/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -reports/ -requirements/ -specification/ \ No newline at end of file diff --git a/test-server/java-v4-server/.duvet/config.toml b/test-server/java-v4-server/.duvet/config.toml index b38762ab..eef14984 100644 --- a/test-server/java-v4-server/.duvet/config.toml +++ b/test-server/java-v4-server/.duvet/config.toml @@ -1,7 +1,7 @@ '$schema' = "https://awslabs.github.io/duvet/config/v0.4.0.json" [[source]] -pattern = "**/*.java" +pattern = "s3ec-staging/*.java" # Include required specifications here [[specification]] @@ -11,7 +11,11 @@ source = "../specification/s3-encryption/data-format/metadata-strategy.md" [[specification]] source = "../specification/s3-encryption/encryption.md" [[specification]] +source = "../specification/s3-encryption/decryption.md" +[[specification]] source = "../specification/s3-encryption/key-derivation.md" +[[specification]] +source = "../specification/s3-encryption/key-commitment.md" [report.html] enabled = true From a570537e657c9fe00544caa3eec328bde0712832 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Mon, 27 Oct 2025 16:10:28 -0700 Subject: [PATCH 07/37] update java submodule --- test-server/java-v3-transition-server/s3ec-staging | 2 +- test-server/java-v4-server/s3ec-staging | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test-server/java-v3-transition-server/s3ec-staging b/test-server/java-v3-transition-server/s3ec-staging index ca2e4ea7..c8527040 160000 --- a/test-server/java-v3-transition-server/s3ec-staging +++ b/test-server/java-v3-transition-server/s3ec-staging @@ -1 +1 @@ -Subproject commit ca2e4ea7c18f5ab5c1000d725ca8c982dd83d4d9 +Subproject commit c852704026ebc1c46bd11b6d5ab6d9a37ec1985d diff --git a/test-server/java-v4-server/s3ec-staging b/test-server/java-v4-server/s3ec-staging index 9752c509..c8f9fe5d 160000 --- a/test-server/java-v4-server/s3ec-staging +++ b/test-server/java-v4-server/s3ec-staging @@ -1 +1 @@ -Subproject commit 9752c5096540894e046348b8db24b9ce712829e3 +Subproject commit c8f9fe5d62e7aadff152fb8e34ff303e4bbd8a92 From 39fc5483e047cada346b4f383a1a228839d8a950 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Wed, 29 Oct 2025 15:50:53 -0700 Subject: [PATCH 08/37] fix configuration --- .../amazon/encryption/s3/CreateClientOperationImpl.java | 2 +- .../amazon/encryption/s3/CreateClientOperationImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index ffaefaf9..75b7eb9f 100644 --- a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -130,7 +130,7 @@ private static AlgorithmSuite getAlgorithmSuite(CreateClientInput input) { return AlgorithmSuite.ALG_AES_256_CBC_IV16_NO_KDF; } else if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF)) { return AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; - } else if (input.getConfig().getEncryptionAlgorithm().equals(ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)) { + } else if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)) { return AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; } else { throw new RuntimeException("Unknown encryption algorithm: " + input.getConfig().getEncryptionAlgorithm()); diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index fd4a6091..a01dfab8 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -128,7 +128,7 @@ private static AlgorithmSuite getAlgorithmSuite(CreateClientInput input) { return AlgorithmSuite.ALG_AES_256_CBC_IV16_NO_KDF; } else if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF)) { return AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; - } else if (input.getConfig().getEncryptionAlgorithm().equals(ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)) { + } else if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)) { return AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; } else { throw new RuntimeException("Unknown encryption algorithm: " + input.getConfig().getEncryptionAlgorithm()); From c755778d44b27e35e200381b76e0bec36c7a289c Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Wed, 29 Oct 2025 16:02:47 -0700 Subject: [PATCH 09/37] Revert "chore: reenable c++ (#52)" This reverts commit 8c6db9eb44b082a28ac143ae9824fe272a3e2166. --- test-server/Makefile | 3 ++- test-server/cpp-v2-server/Makefile | 24 +++++++++---------- test-server/cpp-v2-server/main.cpp | 2 +- test-server/cpp-v2-transition-server/Makefile | 22 ++++++++--------- test-server/cpp-v2-transition-server/main.cpp | 2 +- .../amazon/encryption/s3/TestUtils.java | 8 +++---- 6 files changed, 31 insertions(+), 30 deletions(-) diff --git a/test-server/Makefile b/test-server/Makefile index a166030a..cd667505 100644 --- a/test-server/Makefile +++ b/test-server/Makefile @@ -9,6 +9,7 @@ all: start-all-servers run-tests ci: start-all-servers run-tests stop-servers SERVER_DIRS := $(shell find . -maxdepth 1 -type d -name '*-server' | sed 's|^\./||' | $(if $(FILTER),grep -E "$$(echo '$(FILTER)' | sed 's/,/|/g')",cat) | sort) +# SERVER_DIRS := cpp-v3-server START_SERVER_TARGETS := $(addprefix start-, $(SERVER_DIRS)) WAIT_SERVER_TARGETS := $(addprefix wait-, $(SERVER_DIRS)) @@ -124,4 +125,4 @@ duvet: @for dir in $(SERVER_DIRS); do \ echo "Running make duvet in $$dir..."; \ $(MAKE) -C $$dir duvet; \ - done + done \ No newline at end of file diff --git a/test-server/cpp-v2-server/Makefile b/test-server/cpp-v2-server/Makefile index cc562c1a..9399b631 100644 --- a/test-server/cpp-v2-server/Makefile +++ b/test-server/cpp-v2-server/Makefile @@ -6,20 +6,20 @@ PID_FILE := server.pid PORT := 8085 build/s3ec-server: - brew install libmicrohttpd nlohmann-json ossp-uuid - git clone --recurse-submodules https://github.com/aws/aws-sdk-cpp.git - cd aws-sdk-cpp - mkdir -p build && cd build && cmake .. +# brew install libmicrohttpd nlohmann-json ossp-uuid +# git clone --recurse-submodules https://github.com/aws/aws-sdk-cpp.git +# cd aws-sdk-cpp +# mkdir -p build && cd build && cmake .. start-server: | build/s3ec-server - @echo "Starting Cpp V2 server..." - cd build && make && \ - AWS_ACCESS_KEY_ID="$$AWS_ACCESS_KEY_ID" \ - AWS_SECRET_ACCESS_KEY="$$AWS_SECRET_ACCESS_KEY" \ - AWS_SESSION_TOKEN="$$AWS_SESSION_TOKEN" \ - AWS_REGION="us-west-2" \ - ./s3ec-server & echo $$! > $(PID_FILE) - @echo "Cpp V2 server starting..." +# @echo "Starting Cpp V2 server..." +# cd build && make && \ +# AWS_ACCESS_KEY_ID="$$AWS_ACCESS_KEY_ID" \ +# AWS_SECRET_ACCESS_KEY="$$AWS_SECRET_ACCESS_KEY" \ +# AWS_SESSION_TOKEN="$$AWS_SESSION_TOKEN" \ +# AWS_REGION="us-west-2" \ +# ./s3ec-server & echo $$! > $(PID_FILE) +# @echo "Cpp V2 server starting..." stop-server: @if [ -f $(PID_FILE) ]; then \ diff --git a/test-server/cpp-v2-server/main.cpp b/test-server/cpp-v2-server/main.cpp index c4f2c240..c89ea8c3 100644 --- a/test-server/cpp-v2-server/main.cpp +++ b/test-server/cpp-v2-server/main.cpp @@ -61,7 +61,7 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, auto materials = std::make_shared(kms_key_id); CryptoConfigurationV2 config(materials); - if (legacy1 || legacy2) + if (legacy1 || legacy2) { config.SetSecurityProfile(SecurityProfile::V2_AND_LEGACY); auto encryption_client = std::make_shared(config); diff --git a/test-server/cpp-v2-transition-server/Makefile b/test-server/cpp-v2-transition-server/Makefile index 0a63b2ed..b879358d 100644 --- a/test-server/cpp-v2-transition-server/Makefile +++ b/test-server/cpp-v2-transition-server/Makefile @@ -6,18 +6,18 @@ PID_FILE := server.pid PORT := 8097 build/s3ec-server: - brew install libmicrohttpd nlohmann-json ossp-uuid - mkdir -p build && cd build && cmake .. +# brew install libmicrohttpd nlohmann-json ossp-uuid +# mkdir -p build && cd build && cmake .. start-server: | build/s3ec-server - @echo "Starting Cpp V2 server..." - cd build && make && \ - AWS_ACCESS_KEY_ID="$$AWS_ACCESS_KEY_ID" \ - AWS_SECRET_ACCESS_KEY="$$AWS_SECRET_ACCESS_KEY" \ - AWS_SESSION_TOKEN="$$AWS_SESSION_TOKEN" \ - AWS_REGION="us-west-2" \ - ./s3ec-server & echo $$! > $(PID_FILE) - @echo "Cpp V2 server starting..." +# @echo "Starting Cpp V2 server..." +# cd build && make && \ +# AWS_ACCESS_KEY_ID="$$AWS_ACCESS_KEY_ID" \ +# AWS_SECRET_ACCESS_KEY="$$AWS_SECRET_ACCESS_KEY" \ +# AWS_SESSION_TOKEN="$$AWS_SESSION_TOKEN" \ +# AWS_REGION="us-west-2" \ +# ./s3ec-server & echo $$! > $(PID_FILE) +# @echo "Cpp V2 server starting..." stop-server: @if [ -f $(PID_FILE) ]; then \ @@ -26,7 +26,7 @@ stop-server: fi wait-for-server: - $(MAKE) -C .. wait-for-port PORT=$(PORT) +# $(MAKE) -C .. wait-for-port PORT=$(PORT) duvet: duvet report diff --git a/test-server/cpp-v2-transition-server/main.cpp b/test-server/cpp-v2-transition-server/main.cpp index e8ce8e5c..4dd505bf 100644 --- a/test-server/cpp-v2-transition-server/main.cpp +++ b/test-server/cpp-v2-transition-server/main.cpp @@ -61,7 +61,7 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, auto materials = std::make_shared(kms_key_id); CryptoConfigurationV2 config(materials); - if (legacy1 || legacy2) + if (legacy1 || legacy2) { config.SetSecurityProfile(SecurityProfile::V2_AND_LEGACY); auto encryption_client = std::make_shared(config); 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 f6e5ba75..4c950699 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 @@ -102,7 +102,7 @@ public class TestUtils { JAVA_V3_CURRENT, GO_V3_CURRENT, NET_V2_CURRENT, - CPP_V2_CURRENT, + // CPP_V2_CURRENT, RUBY_V2_CURRENT, PHP_V2_CURRENT ); @@ -112,7 +112,7 @@ public class TestUtils { JAVA_V3_TRANSITION, // GO_V3_TRANSITION, // NET_V2_TRANSITION, - CPP_V2_TRANSITION, + // CPP_V2_TRANSITION, // PHP_V2_TRANSITION, RUBY_V2_TRANSITION ); @@ -137,7 +137,7 @@ public class TestUtils { servers.put(GO_V3_CURRENT, new LanguageServerTarget(GO_V3_CURRENT, "8082")); servers.put(NET_V2_CURRENT, new LanguageServerTarget(NET_V2_CURRENT, "8083")); servers.put(NET_V3, new LanguageServerTarget(NET_V3, "8084")); - servers.put(CPP_V2_CURRENT, new LanguageServerTarget(CPP_V2_CURRENT, "8085")); + // servers.put(CPP_V2_CURRENT, new LanguageServerTarget(CPP_V2_CURRENT, "8085")); // servers.put(RUBY_V2_CURRENT, new LanguageServerTarget(RUBY_V2_CURRENT, "8086")); servers.put(PHP_V2_CURRENT, new LanguageServerTarget(PHP_V2_CURRENT, "8087")); servers.put(GO_V4, new LanguageServerTarget(GO_V4, "8089")); @@ -147,7 +147,7 @@ public class TestUtils { servers.put(JAVA_V3_TRANSITION, new LanguageServerTarget(JAVA_V3_TRANSITION, "8094")); // servers.put(GO_V3_TRANSITION, new LanguageServerTarget(GO_V3_TRANSITION, "8095")); // servers.put(NET_V2_TRANSITION, new LanguageServerTarget(NET_V2_TRANSITION, "8096")); - servers.put(CPP_V2_TRANSITION, new LanguageServerTarget(CPP_V2_TRANSITION, "8097")); + // servers.put(CPP_V2_TRANSITION, new LanguageServerTarget(CPP_V2_TRANSITION, "8097")); servers.put(RUBY_V2_TRANSITION, new LanguageServerTarget(RUBY_V2_TRANSITION, "8098")); servers.put(PHP_V2_TRANSITION, new LanguageServerTarget(PHP_V2_TRANSITION, "8099")); servers.put(JAVA_V4, new LanguageServerTarget(JAVA_V4, "8090")); From d72d8517b58e143219930239af010e7ea8f79aba Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Thu, 30 Oct 2025 07:07:56 -0700 Subject: [PATCH 10/37] remove java transiton for now --- .../src/it/java/software/amazon/encryption/s3/TestUtils.java | 4 ++-- test-server/java-v4-server/s3ec-staging | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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 4c950699..acf7ef6f 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 @@ -109,7 +109,7 @@ public class TestUtils { public static final Set TRANSITION_VERSIONS = Set.of( - JAVA_V3_TRANSITION, +// JAVA_V3_TRANSITION, // GO_V3_TRANSITION, // NET_V2_TRANSITION, // CPP_V2_TRANSITION, @@ -144,7 +144,7 @@ public class TestUtils { servers.put(RUBY_V3, new LanguageServerTarget(RUBY_V3, "8092")); servers.put(PHP_V3, new LanguageServerTarget(PHP_V3, "8093")); // TODO: Create and add transition servers - servers.put(JAVA_V3_TRANSITION, new LanguageServerTarget(JAVA_V3_TRANSITION, "8094")); +// servers.put(JAVA_V3_TRANSITION, new LanguageServerTarget(JAVA_V3_TRANSITION, "8094")); // servers.put(GO_V3_TRANSITION, new LanguageServerTarget(GO_V3_TRANSITION, "8095")); // servers.put(NET_V2_TRANSITION, new LanguageServerTarget(NET_V2_TRANSITION, "8096")); // servers.put(CPP_V2_TRANSITION, new LanguageServerTarget(CPP_V2_TRANSITION, "8097")); diff --git a/test-server/java-v4-server/s3ec-staging b/test-server/java-v4-server/s3ec-staging index c8f9fe5d..f1a533c1 160000 --- a/test-server/java-v4-server/s3ec-staging +++ b/test-server/java-v4-server/s3ec-staging @@ -1 +1 @@ -Subproject commit c8f9fe5d62e7aadff152fb8e34ff303e4bbd8a92 +Subproject commit f1a533c119fac51144a37d4ecfb24ff9978e3f16 From 0dc303f50e7697e74470ddfe2faaa58410a78a27 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Thu, 30 Oct 2025 07:48:31 -0700 Subject: [PATCH 11/37] fix configuration --- .../amazon/encryption/s3/CreateClientOperationImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index a01dfab8..13c3a51f 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -91,7 +91,7 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c throw new RuntimeException("No KeyMaterial found!"); } // V4-Improved (FireEgg Improved) server configuration - S3EncryptionClient.Builder clientBuilder = S3EncryptionClient.builder() + S3EncryptionClient.Builder clientBuilder = S3EncryptionClient.builderV4() .keyring(keyring); // Configure commitment policy if provided (FireEgg feature) From 88c2bc517db4b34bf67095309b0d1ef16b1b3549 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Thu, 30 Oct 2025 08:34:58 -0700 Subject: [PATCH 12/37] fix configuration --- .../s3/CreateClientOperationImpl.java | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index 13c3a51f..2b99e5d2 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -28,7 +28,6 @@ import static software.amazon.encryption.s3.CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT; import static software.amazon.encryption.s3.CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT; import static software.amazon.encryption.s3.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT; -import static software.amazon.encryption.s3.model.EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; public class CreateClientOperationImpl implements CreateClientOperation { private Map clientCache_; @@ -90,23 +89,27 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c } else { throw new RuntimeException("No KeyMaterial found!"); } - // V4-Improved (FireEgg Improved) server configuration - S3EncryptionClient.Builder clientBuilder = S3EncryptionClient.builderV4() - .keyring(keyring); - - // Configure commitment policy if provided (FireEgg feature) + // Configure commitment policy if provided + software.amazon.encryption.s3.CommitmentPolicy policy = REQUIRE_ENCRYPT_ALLOW_DECRYPT; if (input.getConfig().getCommitmentPolicy() != null) { - software.amazon.encryption.s3.CommitmentPolicy policy = getCommitmentPolicy(input); - clientBuilder.commitmentPolicy(policy); + policy = getCommitmentPolicy(input.getConfig().getCommitmentPolicy()); } - // Configure encryption algorithm if provided (FireEgg feature) + // Configure encryption algorithm if provided + AlgorithmSuite algorithm = AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; if (input.getConfig().getEncryptionAlgorithm() != null) { - AlgorithmSuite algorithm = getAlgorithmSuite(input); - clientBuilder.encryptionAlgorithm(algorithm); + algorithm = getAlgorithmSuite(input.getConfig().getEncryptionAlgorithm()); } - S3Client s3Client = clientBuilder.build(); + // V4-Improved server configuration + S3EncryptionClient s3Client = S3EncryptionClient.builderV4() + .keyring(keyring) + .commitmentPolicy(policy) + .encryptionAlgorithm(algorithm) + .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) + .enableLegacyUnauthenticatedModes(input.getConfig().isEnableLegacyUnauthenticatedModes()) + .build(); + UUID uuid = UUID.randomUUID(); String uuidString = uuid.toString(); clientCache_.put(uuidString, s3Client); @@ -123,27 +126,27 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c } } - private static AlgorithmSuite getAlgorithmSuite(CreateClientInput input) { - if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF)) { + private static AlgorithmSuite getAlgorithmSuite(EncryptionAlgorithm input) { + if (input.equals(EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF)) { return AlgorithmSuite.ALG_AES_256_CBC_IV16_NO_KDF; - } else if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF)) { + } else if (input.equals(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF)) { return AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; - } else if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)) { + } else if (input.equals(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)) { return AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; } else { - throw new RuntimeException("Unknown encryption algorithm: " + input.getConfig().getEncryptionAlgorithm()); + throw new RuntimeException("Unknown encryption algorithm: " + input); } } - private static software.amazon.encryption.s3.CommitmentPolicy getCommitmentPolicy(CreateClientInput input) { - if (input.getConfig().getCommitmentPolicy().equals(software.amazon.encryption.s3.model.CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)) { + private static software.amazon.encryption.s3.CommitmentPolicy getCommitmentPolicy(software.amazon.encryption.s3.model.CommitmentPolicy input) { + if (input.equals(software.amazon.encryption.s3.model.CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)) { return FORBID_ENCRYPT_ALLOW_DECRYPT; - } else if (input.getConfig().getCommitmentPolicy().equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT)) { + } else if (input.equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT)) { return REQUIRE_ENCRYPT_ALLOW_DECRYPT; - } else if (input.getConfig().getCommitmentPolicy().equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)) { + } else if (input.equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)) { return REQUIRE_ENCRYPT_REQUIRE_DECRYPT; } else { - throw new RuntimeException("Unknown commitment policy: " + input.getConfig().getCommitmentPolicy()); + throw new RuntimeException("Unknown commitment policy: " + input); } } } From edd534e0e912e303ac40859ce5e2cacd159dca77 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Thu, 30 Oct 2025 09:06:34 -0700 Subject: [PATCH 13/37] Update test configuration --- .../amazon/encryption/s3/CBCDecryptTests.java | 2 ++ .../encryption/s3/ExhaustiveRoundTripTests1_25.java | 4 ++++ .../java/software/amazon/encryption/s3/GCMTests.java | 2 ++ .../software/amazon/encryption/s3/KC_GCMTests.java | 1 + .../amazon/encryption/s3/RoundTripTests.java | 12 ++++++++++++ 5 files changed, 21 insertions(+) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java index 4de6aef4..093ba2ab 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java @@ -107,6 +107,7 @@ void transition_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_cbc( .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .enableLegacyUnauthenticatedModes(true) .enableLegacyWrappingAlgorithms(true) .build()) @@ -124,6 +125,7 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_cbc(Te .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .enableLegacyUnauthenticatedModes(true) .enableLegacyWrappingAlgorithms(true) .build()) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/ExhaustiveRoundTripTests1_25.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/ExhaustiveRoundTripTests1_25.java index eb48d6bd..100925a9 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/ExhaustiveRoundTripTests1_25.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/ExhaustiveRoundTripTests1_25.java @@ -26,6 +26,7 @@ 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.KeyMaterial; @@ -99,6 +100,7 @@ public void GIVEN_CBCEncryptedData_AND_ImprovedClientDecryptingWithForbidEncrypt .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .enableLegacyWrappingAlgorithms(true) .build() ) @@ -135,6 +137,7 @@ public void GIVEN_GCMEncryptedData_AND_ImprovedClientDecryptingWithForbidEncrypt .enableLegacyWrappingAlgorithms(true) .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String s3ECId = output1.getClientId(); @@ -203,6 +206,7 @@ public void GIVEN_KCGCMEncryptedData_AND_ImprovedClientDecryptingWithForbidEncry .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String decS3ECId = decClientOutput.getClientId(); diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java index deb1571d..2ebd1e9f 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java @@ -74,6 +74,7 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_should_encrypt_gcm(Te .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String S3ECId = clientOutput.getClientId(); @@ -123,6 +124,7 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_gcm(Te .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String S3ECId = clientOutput.getClientId(); 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 9e77e20e..12c2dece 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 @@ -157,6 +157,7 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_gcm .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .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 e8dc4bae..306a242e 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 @@ -26,6 +26,7 @@ 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.KeyMaterial; @@ -63,6 +64,7 @@ public void crossLanguageTestKms(LanguageServerTarget encLang, LanguageServerTar .builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build() ) .build()); @@ -78,6 +80,7 @@ public void crossLanguageTestKms(LanguageServerTarget encLang, LanguageServerTar .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build() ) .build()); @@ -113,6 +116,7 @@ public void crossLanguageTestKmsWithEncCtx(LanguageServerTarget encLang, Languag .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build() ) .build()); @@ -130,6 +134,7 @@ public void crossLanguageTestKmsWithEncCtx(LanguageServerTarget encLang, Languag .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build() ) .build()); @@ -169,6 +174,7 @@ public void crossLanguageTestKmsWithSubsetEncCtxFails(LanguageServerTarget encLa .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String encS3ECId = encClientOutput.getClientId(); @@ -185,6 +191,7 @@ public void crossLanguageTestKmsWithSubsetEncCtxFails(LanguageServerTarget encLa .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build() ) .build()); @@ -225,6 +232,7 @@ public void crossLanguageTestKmsWithIncorrectEncCtxFails(LanguageServerTarget en .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build() ) .build()); @@ -242,6 +250,7 @@ public void crossLanguageTestKmsWithIncorrectEncCtxFails(LanguageServerTarget en .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build() ) .build()); @@ -281,6 +290,7 @@ public void kmsV1Legacy(TestUtils.LanguageServerTarget language) { .enableLegacyWrappingAlgorithms(true) .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String s3ECId = output1.getClientId(); @@ -324,6 +334,7 @@ public void kmsV1LegacyWithEncCtx(TestUtils.LanguageServerTarget language) { .enableLegacyWrappingAlgorithms(true) .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String s3ECId = output1.getClientId(); @@ -374,6 +385,7 @@ public void kmsV1LegacyFailsWhenLegacyDisabled(TestUtils.LanguageServerTarget la .enableLegacyWrappingAlgorithms(false) .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String s3ECId = output1.getClientId(); From 12614dc488d22c5d4e94e84dfbf17c3becf08f26 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Wed, 5 Nov 2025 15:16:32 -0800 Subject: [PATCH 14/37] Duvet --- .gitmodules | 4 +++ test-server/java-v4-server/.duvet/config.toml | 25 ------------------- test-server/java-v4-server/Makefile | 15 +++++++++-- test-server/java-v4-server/s3ec-staging | 2 +- test-server/java-v4-server/specification | 1 + 5 files changed, 19 insertions(+), 28 deletions(-) delete mode 100644 test-server/java-v4-server/.duvet/config.toml create mode 160000 test-server/java-v4-server/specification diff --git a/.gitmodules b/.gitmodules index a0b240d5..76aaafb8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -24,6 +24,10 @@ url = git@github.com:aws/private-amazon-s3-encryption-client-java-staging.git branch = imabhichow/add-kc ; branch = s3ec/improved +[submodule "test-server/java-v4-server/specification"] + path = test-server/java-v4-server/specification + url = git@github.com:awslabs/private-aws-encryption-sdk-specification-staging.git + branch = fire-egg-staging [submodule "test-server/specification"] path = test-server/specification url = git@github.com:awslabs/private-aws-encryption-sdk-specification-staging.git diff --git a/test-server/java-v4-server/.duvet/config.toml b/test-server/java-v4-server/.duvet/config.toml deleted file mode 100644 index eef14984..00000000 --- a/test-server/java-v4-server/.duvet/config.toml +++ /dev/null @@ -1,25 +0,0 @@ -'$schema' = "https://awslabs.github.io/duvet/config/v0.4.0.json" - -[[source]] -pattern = "s3ec-staging/*.java" - -# Include required specifications here -[[specification]] -source = "../specification/s3-encryption/data-format/content-metadata.md" -[[specification]] -source = "../specification/s3-encryption/data-format/metadata-strategy.md" -[[specification]] -source = "../specification/s3-encryption/encryption.md" -[[specification]] -source = "../specification/s3-encryption/decryption.md" -[[specification]] -source = "../specification/s3-encryption/key-derivation.md" -[[specification]] -source = "../specification/s3-encryption/key-commitment.md" - -[report.html] -enabled = true - -# Enable snapshots to prevent requirement coverage regressions -[report.snapshot] -enabled = false diff --git a/test-server/java-v4-server/Makefile b/test-server/java-v4-server/Makefile index fa3f9ce8..c6ba56fc 100644 --- a/test-server/java-v4-server/Makefile +++ b/test-server/java-v4-server/Makefile @@ -28,8 +28,19 @@ stop-server: wait-for-server: $(MAKE) -C .. wait-for-port PORT=$(PORT) -duvet: - duvet report +duvet: | duvet_extract duvet_report + +duvet_extract: + rm -rf .duvet + $(foreach file, $(shell find specification/s3-encryption -name '*.md' ! -path "*/materials/*"), duvet extract -o .duvet/requirements -f MARKDOWN $(file);) + +duvet_report: + duvet \ + report \ + --spec-pattern ".duvet/requirements/**/*.toml" \ + --source-pattern "s3ec-staging/src/**/*.java" \ + --source-pattern "s3ec-staging/compliance_exceptions/*.txt" \ + --html .duvet/reports/report.html view-report-mac: open .duvet/reports/report.html \ No newline at end of file diff --git a/test-server/java-v4-server/s3ec-staging b/test-server/java-v4-server/s3ec-staging index f1a533c1..c101d149 160000 --- a/test-server/java-v4-server/s3ec-staging +++ b/test-server/java-v4-server/s3ec-staging @@ -1 +1 @@ -Subproject commit f1a533c119fac51144a37d4ecfb24ff9978e3f16 +Subproject commit c101d14946a8279387b73482a31c03c2f269c9a4 diff --git a/test-server/java-v4-server/specification b/test-server/java-v4-server/specification new file mode 160000 index 00000000..129b9c5e --- /dev/null +++ b/test-server/java-v4-server/specification @@ -0,0 +1 @@ +Subproject commit 129b9c5e53a8c4f6be10a52c9d3dcdf765000d78 From d0457ad6d14df978a1c88b90e9cbbf51f449a590 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Wed, 5 Nov 2025 15:28:05 -0800 Subject: [PATCH 15/37] Rebase --- test-server/Makefile | 3 +-- test-server/cpp-v2-server/Makefile | 24 +++++++++---------- test-server/cpp-v2-server/main.cpp | 2 +- test-server/cpp-v2-transition-server/Makefile | 22 ++++++++--------- test-server/cpp-v2-transition-server/main.cpp | 2 +- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/test-server/Makefile b/test-server/Makefile index 93a4fd8f..be8df10b 100644 --- a/test-server/Makefile +++ b/test-server/Makefile @@ -9,7 +9,6 @@ all: start-all-servers wait-all-servers run-tests ci: start-all-servers wait-all-servers run-tests stop-servers SERVER_DIRS := $(shell find . -maxdepth 1 -type d -name '*-server' | sed 's|^\./||' | $(if $(FILTER),grep -E "$$(echo '$(FILTER)' | sed 's/,/|/g')",cat) | sort) -# SERVER_DIRS := cpp-v3-server START_SERVER_TARGETS := $(addprefix start-, $(SERVER_DIRS)) WAIT_SERVER_TARGETS := $(addprefix wait-, $(SERVER_DIRS)) @@ -125,4 +124,4 @@ duvet: @for dir in $(SERVER_DIRS); do \ echo "Running make duvet in $$dir..."; \ $(MAKE) -C $$dir duvet; \ - done \ No newline at end of file + done diff --git a/test-server/cpp-v2-server/Makefile b/test-server/cpp-v2-server/Makefile index 9399b631..cc562c1a 100644 --- a/test-server/cpp-v2-server/Makefile +++ b/test-server/cpp-v2-server/Makefile @@ -6,20 +6,20 @@ PID_FILE := server.pid PORT := 8085 build/s3ec-server: -# brew install libmicrohttpd nlohmann-json ossp-uuid -# git clone --recurse-submodules https://github.com/aws/aws-sdk-cpp.git -# cd aws-sdk-cpp -# mkdir -p build && cd build && cmake .. + brew install libmicrohttpd nlohmann-json ossp-uuid + git clone --recurse-submodules https://github.com/aws/aws-sdk-cpp.git + cd aws-sdk-cpp + mkdir -p build && cd build && cmake .. start-server: | build/s3ec-server -# @echo "Starting Cpp V2 server..." -# cd build && make && \ -# AWS_ACCESS_KEY_ID="$$AWS_ACCESS_KEY_ID" \ -# AWS_SECRET_ACCESS_KEY="$$AWS_SECRET_ACCESS_KEY" \ -# AWS_SESSION_TOKEN="$$AWS_SESSION_TOKEN" \ -# AWS_REGION="us-west-2" \ -# ./s3ec-server & echo $$! > $(PID_FILE) -# @echo "Cpp V2 server starting..." + @echo "Starting Cpp V2 server..." + cd build && make && \ + AWS_ACCESS_KEY_ID="$$AWS_ACCESS_KEY_ID" \ + AWS_SECRET_ACCESS_KEY="$$AWS_SECRET_ACCESS_KEY" \ + AWS_SESSION_TOKEN="$$AWS_SESSION_TOKEN" \ + AWS_REGION="us-west-2" \ + ./s3ec-server & echo $$! > $(PID_FILE) + @echo "Cpp V2 server starting..." stop-server: @if [ -f $(PID_FILE) ]; then \ diff --git a/test-server/cpp-v2-server/main.cpp b/test-server/cpp-v2-server/main.cpp index c89ea8c3..c4f2c240 100644 --- a/test-server/cpp-v2-server/main.cpp +++ b/test-server/cpp-v2-server/main.cpp @@ -61,7 +61,7 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, auto materials = std::make_shared(kms_key_id); CryptoConfigurationV2 config(materials); - if (legacy1 || legacy2) { + if (legacy1 || legacy2) config.SetSecurityProfile(SecurityProfile::V2_AND_LEGACY); auto encryption_client = std::make_shared(config); diff --git a/test-server/cpp-v2-transition-server/Makefile b/test-server/cpp-v2-transition-server/Makefile index b879358d..0a63b2ed 100644 --- a/test-server/cpp-v2-transition-server/Makefile +++ b/test-server/cpp-v2-transition-server/Makefile @@ -6,18 +6,18 @@ PID_FILE := server.pid PORT := 8097 build/s3ec-server: -# brew install libmicrohttpd nlohmann-json ossp-uuid -# mkdir -p build && cd build && cmake .. + brew install libmicrohttpd nlohmann-json ossp-uuid + mkdir -p build && cd build && cmake .. start-server: | build/s3ec-server -# @echo "Starting Cpp V2 server..." -# cd build && make && \ -# AWS_ACCESS_KEY_ID="$$AWS_ACCESS_KEY_ID" \ -# AWS_SECRET_ACCESS_KEY="$$AWS_SECRET_ACCESS_KEY" \ -# AWS_SESSION_TOKEN="$$AWS_SESSION_TOKEN" \ -# AWS_REGION="us-west-2" \ -# ./s3ec-server & echo $$! > $(PID_FILE) -# @echo "Cpp V2 server starting..." + @echo "Starting Cpp V2 server..." + cd build && make && \ + AWS_ACCESS_KEY_ID="$$AWS_ACCESS_KEY_ID" \ + AWS_SECRET_ACCESS_KEY="$$AWS_SECRET_ACCESS_KEY" \ + AWS_SESSION_TOKEN="$$AWS_SESSION_TOKEN" \ + AWS_REGION="us-west-2" \ + ./s3ec-server & echo $$! > $(PID_FILE) + @echo "Cpp V2 server starting..." stop-server: @if [ -f $(PID_FILE) ]; then \ @@ -26,7 +26,7 @@ stop-server: fi wait-for-server: -# $(MAKE) -C .. wait-for-port PORT=$(PORT) + $(MAKE) -C .. wait-for-port PORT=$(PORT) duvet: duvet report diff --git a/test-server/cpp-v2-transition-server/main.cpp b/test-server/cpp-v2-transition-server/main.cpp index f4f42817..58d807ef 100644 --- a/test-server/cpp-v2-transition-server/main.cpp +++ b/test-server/cpp-v2-transition-server/main.cpp @@ -86,7 +86,7 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, auto materials = std::make_shared(kms_key_id); CryptoConfigurationV2 config(materials); - if (legacy1 || legacy2) { + if (legacy1 || legacy2) config.SetSecurityProfile(SecurityProfile::V2_AND_LEGACY); auto encryption_client = std::make_shared(config); From 131d905b1045a998252365ed3fbd6b730c0059a9 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Thu, 6 Nov 2025 12:52:26 -0800 Subject: [PATCH 16/37] nit - format --- .../src/it/java/software/amazon/encryption/s3/GCMTests.java | 4 ++-- .../it/java/software/amazon/encryption/s3/KC_GCMTests.java | 2 +- .../it/java/software/amazon/encryption/s3/RoundTripTests.java | 2 +- .../amazon/encryption/s3/CreateClientOperationImpl.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java index 2ebd1e9f..6eef0b5f 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java @@ -74,7 +74,7 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_should_encrypt_gcm(Te .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) - .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String S3ECId = clientOutput.getClientId(); @@ -124,7 +124,7 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_gcm(Te .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) - .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String S3ECId = clientOutput.getClientId(); 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 12c2dece..99e8d37d 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 @@ -157,7 +157,7 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_gcm .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) - .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .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 306a242e..b427002a 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 @@ -191,7 +191,7 @@ public void crossLanguageTestKmsWithSubsetEncCtxFails(LanguageServerTarget encLa .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) - .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build() ) .build()); diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index 2b99e5d2..a662f6bc 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -90,7 +90,7 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c throw new RuntimeException("No KeyMaterial found!"); } // Configure commitment policy if provided - software.amazon.encryption.s3.CommitmentPolicy policy = REQUIRE_ENCRYPT_ALLOW_DECRYPT; + software.amazon.encryption.s3.CommitmentPolicy policy = CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT; if (input.getConfig().getCommitmentPolicy() != null) { policy = getCommitmentPolicy(input.getConfig().getCommitmentPolicy()); } From 9acf8ad41fe557d4303f2843a2b64f14d195162c Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Fri, 7 Nov 2025 12:34:04 -0800 Subject: [PATCH 17/37] Change java-v4-port --- .../src/it/java/software/amazon/encryption/s3/TestUtils.java | 2 +- test-server/java-v4-server/Makefile | 2 +- test-server/java-v4-server/README.md | 2 +- .../java/software/amazon/encryption/s3/S3ECJavaTestServer.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) 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 45344780..8f20cca0 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 @@ -171,7 +171,7 @@ public class TestUtils { // servers.put(NET_V2_TRANSITION, new LanguageServerTarget(NET_V2_TRANSITION, "8096")); // servers.put(RUBY_V2_TRANSITION, new LanguageServerTarget(RUBY_V2_TRANSITION, "8098")); servers.put(PHP_V2_TRANSITION, new LanguageServerTarget(PHP_V2_TRANSITION, "8099")); - servers.put(JAVA_V4, new LanguageServerTarget(JAVA_V4, "8090")); + servers.put(JAVA_V4, new LanguageServerTarget(JAVA_V4, "8088")); servers.put(NET_V3_TRANSITION, new LanguageServerTarget(NET_V3_TRANSITION, "8100")); serverMap = filterServers(servers); } diff --git a/test-server/java-v4-server/Makefile b/test-server/java-v4-server/Makefile index c6ba56fc..82fc87b5 100644 --- a/test-server/java-v4-server/Makefile +++ b/test-server/java-v4-server/Makefile @@ -3,7 +3,7 @@ .PHONY: start-server stop-server wait-for-server build-s3ec PID_FILE := server.pid -PORT := 8090 +PORT := 8088 build-s3ec: @echo "Building S3EC from source..." diff --git a/test-server/java-v4-server/README.md b/test-server/java-v4-server/README.md index d011daa2..70d60914 100644 --- a/test-server/java-v4-server/README.md +++ b/test-server/java-v4-server/README.md @@ -18,6 +18,6 @@ To run the server: gradle run ``` -This will start the server running on port `8090`. +This will start the server running on port `8088`. The server is used as part of the testing framework to verify cross-language compatibility of the S3 Encryption Client implementations. diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/S3ECJavaTestServer.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/S3ECJavaTestServer.java index 7b73ffd1..c3fee4f1 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/S3ECJavaTestServer.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/S3ECJavaTestServer.java @@ -15,7 +15,7 @@ import software.amazon.encryption.s3.service.S3ECTestServer; public class S3ECJavaTestServer implements Runnable { - static final URI endpoint = URI.create("http://localhost:8090"); + static final URI endpoint = URI.create("http://localhost:8088"); public static void main(String[] args) { new S3ECJavaTestServer().run(); From 398fc4e9d1b9a8968149d6352ad7a0a12fbce9bd Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Fri, 7 Nov 2025 13:33:02 -0800 Subject: [PATCH 18/37] duvet changes --- test-server/java-v3-server/.duvet/config.toml | 8 +++--- test-server/java-v3-server/Makefile | 1 + test-server/java-v3-server/specification | 1 + .../.duvet/.gitignore | 3 +++ .../.duvet/config.toml | 14 +++++----- .../java-v3-transition-server/Makefile | 1 + .../java-v3-transition-server/specification | 1 + test-server/java-v4-server/.duvet/.gitignore | 3 +++ test-server/java-v4-server/.duvet/config.toml | 27 +++++++++++++++++++ test-server/java-v4-server/Makefile | 15 ++--------- test-server/java-v4-server/specification | 2 +- 11 files changed, 52 insertions(+), 24 deletions(-) create mode 120000 test-server/java-v3-server/specification create mode 100644 test-server/java-v3-transition-server/.duvet/.gitignore create mode 120000 test-server/java-v3-transition-server/specification create mode 100644 test-server/java-v4-server/.duvet/.gitignore create mode 100644 test-server/java-v4-server/.duvet/config.toml mode change 160000 => 120000 test-server/java-v4-server/specification diff --git a/test-server/java-v3-server/.duvet/config.toml b/test-server/java-v3-server/.duvet/config.toml index 0a83ed64..f03424b2 100644 --- a/test-server/java-v3-server/.duvet/config.toml +++ b/test-server/java-v3-server/.duvet/config.toml @@ -5,13 +5,13 @@ pattern = "s3ec-staging/*.java" # Include required specifications here [[specification]] -source = "../specification/s3-encryption/data-format/content-metadata.md" +source = "specification/s3-encryption/data-format/content-metadata.md" [[specification]] -source = "../specification/s3-encryption/data-format/metadata-strategy.md" +source = "specification/s3-encryption/data-format/metadata-strategy.md" [[specification]] -source = "../specification/s3-encryption/encryption.md" +source = "specification/s3-encryption/encryption.md" [[specification]] -source = "../specification/s3-encryption/key-derivation.md" +source = "specification/s3-encryption/key-derivation.md" [report.html] enabled = true diff --git a/test-server/java-v3-server/Makefile b/test-server/java-v3-server/Makefile index 445be2ac..b23578be 100644 --- a/test-server/java-v3-server/Makefile +++ b/test-server/java-v3-server/Makefile @@ -24,6 +24,7 @@ wait-for-server: $(MAKE) -C .. wait-for-port PORT=$(PORT) duvet: + ln -sf ../specification specification duvet report view-report-mac: diff --git a/test-server/java-v3-server/specification b/test-server/java-v3-server/specification new file mode 120000 index 00000000..b173f708 --- /dev/null +++ b/test-server/java-v3-server/specification @@ -0,0 +1 @@ +../specification \ No newline at end of file diff --git a/test-server/java-v3-transition-server/.duvet/.gitignore b/test-server/java-v3-transition-server/.duvet/.gitignore new file mode 100644 index 00000000..93956e36 --- /dev/null +++ b/test-server/java-v3-transition-server/.duvet/.gitignore @@ -0,0 +1,3 @@ +reports/ +requirements/ +specification/ \ No newline at end of file diff --git a/test-server/java-v3-transition-server/.duvet/config.toml b/test-server/java-v3-transition-server/.duvet/config.toml index eef14984..d07014da 100644 --- a/test-server/java-v3-transition-server/.duvet/config.toml +++ b/test-server/java-v3-transition-server/.duvet/config.toml @@ -5,17 +5,19 @@ pattern = "s3ec-staging/*.java" # Include required specifications here [[specification]] -source = "../specification/s3-encryption/data-format/content-metadata.md" +source = "specification/s3-encryption/client.md" [[specification]] -source = "../specification/s3-encryption/data-format/metadata-strategy.md" +source = "specification/s3-encryption/decryption.md" [[specification]] -source = "../specification/s3-encryption/encryption.md" +source = "specification/s3-encryption/encryption.md" [[specification]] -source = "../specification/s3-encryption/decryption.md" +source = "specification/s3-encryption/key-commitment.md" [[specification]] -source = "../specification/s3-encryption/key-derivation.md" +source = "specification/s3-encryption/key-derivation.md" [[specification]] -source = "../specification/s3-encryption/key-commitment.md" +source = "specification/s3-encryption/data-format/content-metadata.md" +[[specification]] +source = "specification/s3-encryption/data-format/metadata-strategy.md" [report.html] enabled = true diff --git a/test-server/java-v3-transition-server/Makefile b/test-server/java-v3-transition-server/Makefile index 3f0358c9..8385f61e 100644 --- a/test-server/java-v3-transition-server/Makefile +++ b/test-server/java-v3-transition-server/Makefile @@ -29,6 +29,7 @@ wait-for-server: $(MAKE) -C .. wait-for-port PORT=$(PORT) duvet: + ln -sf ../specification specification duvet report view-report-mac: diff --git a/test-server/java-v3-transition-server/specification b/test-server/java-v3-transition-server/specification new file mode 120000 index 00000000..b173f708 --- /dev/null +++ b/test-server/java-v3-transition-server/specification @@ -0,0 +1 @@ +../specification \ No newline at end of file diff --git a/test-server/java-v4-server/.duvet/.gitignore b/test-server/java-v4-server/.duvet/.gitignore new file mode 100644 index 00000000..93956e36 --- /dev/null +++ b/test-server/java-v4-server/.duvet/.gitignore @@ -0,0 +1,3 @@ +reports/ +requirements/ +specification/ \ No newline at end of file diff --git a/test-server/java-v4-server/.duvet/config.toml b/test-server/java-v4-server/.duvet/config.toml new file mode 100644 index 00000000..d07014da --- /dev/null +++ b/test-server/java-v4-server/.duvet/config.toml @@ -0,0 +1,27 @@ +'$schema' = "https://awslabs.github.io/duvet/config/v0.4.0.json" + +[[source]] +pattern = "s3ec-staging/*.java" + +# Include required specifications here +[[specification]] +source = "specification/s3-encryption/client.md" +[[specification]] +source = "specification/s3-encryption/decryption.md" +[[specification]] +source = "specification/s3-encryption/encryption.md" +[[specification]] +source = "specification/s3-encryption/key-commitment.md" +[[specification]] +source = "specification/s3-encryption/key-derivation.md" +[[specification]] +source = "specification/s3-encryption/data-format/content-metadata.md" +[[specification]] +source = "specification/s3-encryption/data-format/metadata-strategy.md" + +[report.html] +enabled = true + +# Enable snapshots to prevent requirement coverage regressions +[report.snapshot] +enabled = false diff --git a/test-server/java-v4-server/Makefile b/test-server/java-v4-server/Makefile index 82fc87b5..734a7808 100644 --- a/test-server/java-v4-server/Makefile +++ b/test-server/java-v4-server/Makefile @@ -28,19 +28,8 @@ stop-server: wait-for-server: $(MAKE) -C .. wait-for-port PORT=$(PORT) -duvet: | duvet_extract duvet_report - -duvet_extract: - rm -rf .duvet - $(foreach file, $(shell find specification/s3-encryption -name '*.md' ! -path "*/materials/*"), duvet extract -o .duvet/requirements -f MARKDOWN $(file);) - -duvet_report: - duvet \ - report \ - --spec-pattern ".duvet/requirements/**/*.toml" \ - --source-pattern "s3ec-staging/src/**/*.java" \ - --source-pattern "s3ec-staging/compliance_exceptions/*.txt" \ - --html .duvet/reports/report.html +duvet: + duvet report view-report-mac: open .duvet/reports/report.html \ No newline at end of file diff --git a/test-server/java-v4-server/specification b/test-server/java-v4-server/specification deleted file mode 160000 index 129b9c5e..00000000 --- a/test-server/java-v4-server/specification +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 129b9c5e53a8c4f6be10a52c9d3dcdf765000d78 diff --git a/test-server/java-v4-server/specification b/test-server/java-v4-server/specification new file mode 120000 index 00000000..b173f708 --- /dev/null +++ b/test-server/java-v4-server/specification @@ -0,0 +1 @@ +../specification \ No newline at end of file From cd342a18038042fdd23b52db7242be0e3225cd90 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Fri, 7 Nov 2025 14:16:36 -0800 Subject: [PATCH 19/37] Dotnet change --- .../net-v3-transition-server/Controllers/ClientController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-server/net-v3-transition-server/Controllers/ClientController.cs b/test-server/net-v3-transition-server/Controllers/ClientController.cs index b2fc2d4e..8dff8943 100644 --- a/test-server/net-v3-transition-server/Controllers/ClientController.cs +++ b/test-server/net-v3-transition-server/Controllers/ClientController.cs @@ -46,8 +46,8 @@ public IActionResult CreateClient([FromBody] ClientRequest request) logger.LogInformation("[NET-V3-Transitional] Created securityProfile= {securityProfile}", securityProfile.ToString()); // Currently, tests does not send EncryptionAlgorithm. Tests only validates EncryptionAlgorithm from metadata of the response. - // var encryptionAlgorithm = MapEncryptionAlgorithm(request.Config.EncryptionAlgorithm); - var encryptionAlgorithm = commitmentPolicy == Amazon.Extensions.S3.Encryption.CommitmentPolicy.ForbidEncryptAllowDecrypt ? ContentEncryptionAlgorithm.AesGcm : ContentEncryptionAlgorithm.AesGcmWithCommitment; + var encryptionAlgorithm = MapEncryptionAlgorithm(request.Config.EncryptionAlgorithm); + // var encryptionAlgorithm = commitmentPolicy == Amazon.Extensions.S3.Encryption.CommitmentPolicy.ForbidEncryptAllowDecrypt ? ContentEncryptionAlgorithm.AesGcm : ContentEncryptionAlgorithm.AesGcmWithCommitment; logger.LogInformation("[NET-V3-Transitional] Created commitmentPolicy= {commitmentPolicy}", commitmentPolicy); logger.LogInformation("[NET-V3-Transitional] Created encryptionAlgorithm= {encryptionAlgorithm}", encryptionAlgorithm); From 2b1b8104cbfc33eb8bcde5e1528251b4a5adf059 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Fri, 7 Nov 2025 14:20:21 -0800 Subject: [PATCH 20/37] remove symlink --- test-server/java-v3-server/Makefile | 1 - test-server/java-v3-transition-server/Makefile | 1 - 2 files changed, 2 deletions(-) diff --git a/test-server/java-v3-server/Makefile b/test-server/java-v3-server/Makefile index b23578be..445be2ac 100644 --- a/test-server/java-v3-server/Makefile +++ b/test-server/java-v3-server/Makefile @@ -24,7 +24,6 @@ wait-for-server: $(MAKE) -C .. wait-for-port PORT=$(PORT) duvet: - ln -sf ../specification specification duvet report view-report-mac: diff --git a/test-server/java-v3-transition-server/Makefile b/test-server/java-v3-transition-server/Makefile index 8385f61e..3f0358c9 100644 --- a/test-server/java-v3-transition-server/Makefile +++ b/test-server/java-v3-transition-server/Makefile @@ -29,7 +29,6 @@ wait-for-server: $(MAKE) -C .. wait-for-port PORT=$(PORT) duvet: - ln -sf ../specification specification duvet report view-report-mac: From e0ee48339c534fab4de69acc92ccf0c836788c4e Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Fri, 7 Nov 2025 15:24:04 -0800 Subject: [PATCH 21/37] Fix Tests --- .../it/java/software/amazon/encryption/s3/RoundTripTests.java | 2 ++ test-server/net-v3-transition-server/Models/ClientRequest.cs | 1 + 2 files changed, 3 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 0d2543e3..ed107f75 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 @@ -455,6 +455,7 @@ public void instructionFileReadV2Format(TestUtils.LanguageServerTarget language) .enableLegacyWrappingAlgorithms(true) .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String s3ECId = output1.getClientId(); @@ -519,6 +520,7 @@ public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageSe .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String decS3ECId = decOutput.getClientId(); diff --git a/test-server/net-v3-transition-server/Models/ClientRequest.cs b/test-server/net-v3-transition-server/Models/ClientRequest.cs index 05b9a37e..cd5fa406 100644 --- a/test-server/net-v3-transition-server/Models/ClientRequest.cs +++ b/test-server/net-v3-transition-server/Models/ClientRequest.cs @@ -40,6 +40,7 @@ public enum CommitmentPolicy FORBID_ENCRYPT_ALLOW_DECRYPT } +[JsonConverter(typeof(JsonStringEnumConverter))] public enum EncryptionAlgorithm { ALG_AES_256_CBC_IV16_NO_KDF, From 87b3bb1473b5906d5c2ca75e406644b40b128a1c Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Mon, 10 Nov 2025 04:48:27 -0800 Subject: [PATCH 22/37] chore: enable java-v3-transition test server --- .../build.gradle.kts | 2 +- .../java-v3-transition-server/s3ec-staging | 2 +- .../s3/CreateClientOperationImpl.java | 244 ++++++++--------- .../encryption/s3/GetObjectOperationImpl.java | 88 ++++--- .../amazon/encryption/s3/MetadataUtils.java | 54 ++-- .../encryption/s3/PutObjectOperationImpl.java | 58 ++-- .../encryption/s3/S3ECJavaTestServer.java | 17 +- test-server/java-v4-server/s3ec-staging | 2 +- .../s3/CreateClientOperationImpl.java | 247 +++++++++--------- .../encryption/s3/GetObjectOperationImpl.java | 94 +++---- .../amazon/encryption/s3/MetadataUtils.java | 54 ++-- .../encryption/s3/PutObjectOperationImpl.java | 65 +++-- .../encryption/s3/S3ECJavaTestServer.java | 20 +- 13 files changed, 473 insertions(+), 474 deletions(-) diff --git a/test-server/java-v3-transition-server/build.gradle.kts b/test-server/java-v3-transition-server/build.gradle.kts index 5b3a9234..7f249d65 100644 --- a/test-server/java-v3-transition-server/build.gradle.kts +++ b/test-server/java-v3-transition-server/build.gradle.kts @@ -14,7 +14,7 @@ dependencies { implementation("software.amazon.smithy.java:aws-server-restjson:$smithyJavaVersion") // S3EC from local Maven repository (installed by mvn install) - implementation("software.amazon.encryption.s3:amazon-s3-encryption-client-java:3.4.0-TRANSITION") + implementation("software.amazon.encryption.s3:amazon-s3-encryption-client-java:3.4.0-read-kc") } // Use that application plugin to start the service via the `run` task. diff --git a/test-server/java-v3-transition-server/s3ec-staging b/test-server/java-v3-transition-server/s3ec-staging index c8527040..9042d648 160000 --- a/test-server/java-v3-transition-server/s3ec-staging +++ b/test-server/java-v3-transition-server/s3ec-staging @@ -1 +1 @@ -Subproject commit c852704026ebc1c46bd11b6d5ab6d9a37ec1985d +Subproject commit 9042d64860d240146a11a379e38b78f812dc7358 diff --git a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index f874c977..8b9cb0f4 100644 --- a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -3,7 +3,6 @@ import software.amazon.awssdk.services.s3.S3Client; import software.amazon.encryption.s3.algorithms.AlgorithmSuite; import software.amazon.encryption.s3.internal.InstructionFileConfig; -import software.amazon.encryption.s3.S3EncryptionClient; import software.amazon.encryption.s3.materials.AesKeyring; import software.amazon.encryption.s3.materials.Keyring; import software.amazon.encryption.s3.materials.KmsKeyring; @@ -28,136 +27,137 @@ import java.util.UUID; import static software.amazon.encryption.s3.CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT; -import static software.amazon.encryption.s3.model.EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; +import static software.amazon.encryption.s3.CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT; +import static software.amazon.encryption.s3.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT; public class CreateClientOperationImpl implements CreateClientOperation { - private Map clientCache_; - - public CreateClientOperationImpl(Map clientCache) { - clientCache_ = clientCache; - } - - // Copied from S3EC. - private boolean onlyOneNonNull(Object... values) { - boolean haveOneNonNull = false; - for (Object o : values) { - if (o != null) { - if (haveOneNonNull) { - return false; + private Map clientCache_; + + public CreateClientOperationImpl(Map clientCache) { + clientCache_ = clientCache; + } + + // Copied from S3EC. + private boolean onlyOneNonNull(Object... values) { + boolean haveOneNonNull = false; + for (Object o : values) { + if (o != null) { + if (haveOneNonNull) { + return false; + } + + haveOneNonNull = true; + } } - haveOneNonNull = true; - } + return haveOneNonNull; } - return haveOneNonNull; - } - - @Override - public CreateClientOutput createClient(CreateClientInput input, RequestContext context) { - try { - KeyMaterial key = input.getConfig().getKeyMaterial(); - if (!onlyOneNonNull(key.getAesKey(), key.getKmsKeyId(), key.getRsaKey())) { - throw new RuntimeException("KeyMaterial must be only one, non-null input!"); - } - Keyring keyring; - if (key.getAesKey() != null) { - byte[] keyBytes = new byte[key.getAesKey().remaining()]; - key.getAesKey().get(keyBytes); - keyring = AesKeyring.builder() - .wrappingKey(new SecretKeySpec(keyBytes, "AES")) - .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) - .build(); - } else if (key.getRsaKey() != null) { + @Override + public CreateClientOutput createClient(CreateClientInput input, RequestContext context) { try { - byte[] keyBytes = new byte[key.getRsaKey().remaining()]; - key.getRsaKey().get(keyBytes); - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - keyring = RsaKeyring.builder() - .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) - .wrappingKeyPair(PartialRsaKeyPair.builder() - .privateKey(keyFactory.generatePrivate(keySpec)).build()) - .build(); - } catch (NoSuchAlgorithmException | InvalidKeySpecException nse) { - throw new RuntimeException(nse); - } - } else if (key.getKmsKeyId() != null) { - keyring = KmsKeyring.builder() - .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) - .wrappingKeyId(key.getKmsKeyId()) - .build(); - } else { - throw new RuntimeException("No KeyMaterial found!"); - } - - boolean instFilePut = false; - if (input.getConfig().getInstructionFileConfig() != null) { - instFilePut = input.getConfig().getInstructionFileConfig().isEnableInstructionFilePutObject(); + KeyMaterial key = input.getConfig().getKeyMaterial(); + if (!onlyOneNonNull(key.getAesKey(), key.getKmsKeyId(), key.getRsaKey())) { + throw new RuntimeException("KeyMaterial must be only one, non-null input!"); + } + Keyring keyring; + if (key.getAesKey() != null) { + byte[] keyBytes = new byte[key.getAesKey().remaining()]; + key.getAesKey().get(keyBytes); + keyring = AesKeyring.builder() + .wrappingKey(new SecretKeySpec(keyBytes, "AES")) + .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) + .build(); + } else if (key.getRsaKey() != null) { + try { + byte[] keyBytes = new byte[key.getRsaKey().remaining()]; + key.getRsaKey().get(keyBytes); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + keyring = RsaKeyring.builder() + .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) + .wrappingKeyPair(PartialRsaKeyPair.builder() + .privateKey(keyFactory.generatePrivate(keySpec)).build()) + .build(); + } catch (NoSuchAlgorithmException | InvalidKeySpecException nse) { + throw new RuntimeException(nse); + } + } else if (key.getKmsKeyId() != null) { + keyring = KmsKeyring.builder() + .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) + .wrappingKeyId(key.getKmsKeyId()) + .build(); + } else { + throw new RuntimeException("No KeyMaterial found!"); + } + + boolean instFilePut = false; + if (input.getConfig().getInstructionFileConfig() != null) { + instFilePut = input.getConfig().getInstructionFileConfig().isEnableInstructionFilePutObject(); + } + + // Configure commitment policy if provided + software.amazon.encryption.s3.CommitmentPolicy policy = FORBID_ENCRYPT_ALLOW_DECRYPT; + if (input.getConfig().getCommitmentPolicy() != null) { + policy = getCommitmentPolicy(input.getConfig().getCommitmentPolicy()); + } + + // Configure encryption algorithm if provided + AlgorithmSuite algorithm = AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; + if (input.getConfig().getEncryptionAlgorithm() != null) { + algorithm = getAlgorithmSuite(input.getConfig().getEncryptionAlgorithm()); + } + + // V3-Transitonal server configuration + S3EncryptionClient s3Client = S3EncryptionClient.builderV4() + .instructionFileConfig(InstructionFileConfig.builder() + .instructionFileClient(S3Client.create()) + .enableInstructionFilePutObject(instFilePut) + .build()) + .keyring(keyring) + .commitmentPolicy(policy) + .encryptionAlgorithm(algorithm) + .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) + .enableLegacyUnauthenticatedModes(input.getConfig().isEnableLegacyUnauthenticatedModes()) + .build(); + + UUID uuid = UUID.randomUUID(); + String uuidString = uuid.toString(); + clientCache_.put(uuidString, s3Client); + return CreateClientOutput.builder() + .clientId(uuidString) + .build(); + } catch (Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + String stackTrace = sw.toString(); + throw GenericServerError.builder() + .message(stackTrace) + .build(); } - - // V3-Transitional server configuration - S3EncryptionClient.Builder clientBuilder = S3EncryptionClient.builder() - .instructionFileConfig(InstructionFileConfig.builder() - .instructionFileClient(S3Client.create()) - .enableInstructionFilePutObject(instFilePut) - .build()) - .keyring(keyring); - - // Configure commitment policy if provided ( feature) - if (input.getConfig().getCommitmentPolicy() != null) { - CommitmentPolicy policy = getCommitmentPolicy(input); - clientBuilder.commitmentPolicy(policy); - } - // V3-Transitional default: No commitment policy (null) for backward compatibility - - // Configure encryption algorithm if provided ( feature) - if (input.getConfig().getEncryptionAlgorithm() != null) { - AlgorithmSuite algorithm = getAlgorithmSuite(input); - clientBuilder.encryptionAlgorithm(algorithm); - } else { - // V3-Transitional default: Legacy algorithm for backward compatibility - clientBuilder.encryptionAlgorithm(AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); - } - - S3Client s3Client = clientBuilder.build(); - UUID uuid = UUID.randomUUID(); - String uuidString = uuid.toString(); - clientCache_.put(uuidString, s3Client); - return CreateClientOutput.builder() - .clientId(uuidString) - .build(); - } catch (Exception e) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - String stackTrace = sw.toString(); - throw GenericServerError.builder() - .message(stackTrace) - .build(); } - } - - private static AlgorithmSuite getAlgorithmSuite(CreateClientInput input) { - if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF)) { - return AlgorithmSuite.ALG_AES_256_CBC_IV16_NO_KDF; - } else if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF)) { - return AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; - } else if (input.getConfig().getEncryptionAlgorithm().equals(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)) { - return AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; - } else { - throw new RuntimeException("Unknown encryption algorithm: " + input.getConfig().getEncryptionAlgorithm()); + + private static AlgorithmSuite getAlgorithmSuite(EncryptionAlgorithm input) { + if (input.equals(EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF)) { + return AlgorithmSuite.ALG_AES_256_CBC_IV16_NO_KDF; + } else if (input.equals(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF)) { + return AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; + } else if (input.equals(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)) { + return AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; + } else { + throw new RuntimeException("Unknown encryption algorithm: " + input); + } } - } - - private static software.amazon.encryption.s3.CommitmentPolicy getCommitmentPolicy(CreateClientInput input) { - if (input.getConfig().getCommitmentPolicy().equals(software.amazon.encryption.s3.model.CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)) { - return FORBID_ENCRYPT_ALLOW_DECRYPT; - } else if (input.getConfig().getCommitmentPolicy().equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT)) { - return null; - } else if (input.getConfig().getCommitmentPolicy().equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)) { - return null; - } else { - throw new RuntimeException("Unknown commitment policy: " + input.getConfig().getCommitmentPolicy()); + + private static software.amazon.encryption.s3.CommitmentPolicy getCommitmentPolicy(software.amazon.encryption.s3.model.CommitmentPolicy input) { + if (input.equals(software.amazon.encryption.s3.model.CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)) { + return FORBID_ENCRYPT_ALLOW_DECRYPT; + } else if (input.equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT)) { + return REQUIRE_ENCRYPT_ALLOW_DECRYPT; + } else if (input.equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)) { + return REQUIRE_ENCRYPT_REQUIRE_DECRYPT; + } else { + throw new RuntimeException("Unknown commitment policy: " + input); + } } - } } diff --git a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java index e7c5493f..86749489 100644 --- a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java +++ b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java @@ -23,50 +23,52 @@ import static software.amazon.encryption.s3.MetadataUtils.metadataMapToList; public class GetObjectOperationImpl implements GetObjectOperation { - private Map clientCache_; - public GetObjectOperationImpl(Map clientCache) { - clientCache_ = clientCache; - } - @Override - public GetObjectOutput getObject(GetObjectInput input, RequestContext context) { - try { - S3Client s3Client = clientCache_.get(input.getClientID()); - Map ecMap = metadataListToMap(input.getMetadata()); + private Map clientCache_; - try { - ResponseBytes resp = s3Client.getObjectAsBytes(builder -> builder - .bucket(input.getBucket()) - .key(input.getKey()) - .overrideConfiguration(withAdditionalConfiguration(ecMap))); + public GetObjectOperationImpl(Map clientCache) { + clientCache_ = clientCache; + } + + @Override + public GetObjectOutput getObject(GetObjectInput input, RequestContext context) { + try { + S3Client s3Client = clientCache_.get(input.getClientID()); + Map ecMap = metadataListToMap(input.getMetadata()); + + try { + ResponseBytes resp = s3Client.getObjectAsBytes(builder -> builder + .bucket(input.getBucket()) + .key(input.getKey()) + .overrideConfiguration(withAdditionalConfiguration(ecMap))); - List mdAsList = metadataMapToList(resp.response().metadata()); - // Can't use asBB else it gets mad bc cant access backing array - ByteBuffer bb = ByteBuffer.wrap(resp.asByteArray()); - GetObjectOutput output = GetObjectOutput.builder() - .body(bb) - .metadata(mdAsList) - .build(); - return output; - } catch (S3EncryptionClientException s3EncryptionClientException) { - // Modeled exceptions MUST be returned as such - StringWriter sw = new StringWriter(); - s3EncryptionClientException.printStackTrace(new PrintWriter(sw)); - String stackTrace = sw.toString(); - throw S3EncryptionClientError.builder() - .message(stackTrace) - .build(); - } - } catch (Exception e) { - // Don't wrap modeled errors - if (e instanceof S3EncryptionClientError) { - throw e; - } - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - String stackTrace = sw.toString(); - throw GenericServerError.builder() - .message(stackTrace) - .build(); + List mdAsList = metadataMapToList(resp.response().metadata()); + // Can't use asBB else it gets mad bc cant access backing array + ByteBuffer bb = ByteBuffer.wrap(resp.asByteArray()); + GetObjectOutput output = GetObjectOutput.builder() + .body(bb) + .metadata(mdAsList) + .build(); + return output; + } catch (S3EncryptionClientException s3EncryptionClientException) { + // Modeled exceptions MUST be returned as such + StringWriter sw = new StringWriter(); + s3EncryptionClientException.printStackTrace(new PrintWriter(sw)); + String stackTrace = sw.toString(); + throw S3EncryptionClientError.builder() + .message(stackTrace) + .build(); + } + } catch (Exception e) { + // Don't wrap modeled errors + if (e instanceof S3EncryptionClientError) { + throw e; + } + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + String stackTrace = sw.toString(); + throw GenericServerError.builder() + .message(stackTrace) + .build(); + } } - } } diff --git a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/MetadataUtils.java b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/MetadataUtils.java index 036289ec..9eba6a3d 100644 --- a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/MetadataUtils.java +++ b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/MetadataUtils.java @@ -9,35 +9,35 @@ public class MetadataUtils { - /** - * Annoyingly, Smithy doesn't provide an interface for map types - * in HTTP headers, so we have to do the serde ourselves - */ - public static List metadataMapToList(Map md) { - List mdAsList = new ArrayList<>(md.size()); - for (Map.Entry keyValue : md.entrySet()) { - mdAsList.add("[" + keyValue.getKey() + "]:[" + keyValue.getValue() + "]"); + /** + * Annoyingly, Smithy doesn't provide an interface for map types + * in HTTP headers, so we have to do the serde ourselves + */ + public static List metadataMapToList(Map md) { + List mdAsList = new ArrayList<>(md.size()); + for (Map.Entry keyValue : md.entrySet()) { + mdAsList.add("[" + keyValue.getKey() + "]:[" + keyValue.getValue() + "]"); + } + return mdAsList; } - return mdAsList; - } - public static Map metadataListToMap(List mdList) { - Map md = new HashMap<>(); - for (String entry : mdList) { - // Split on "]:[" to separate key and value - String[] parts = entry.split("]:\\["); - if (parts.length == 2) { - // Remove remaining brackets from start and end - String key = parts[0].substring(1); - String value = parts[1].substring(0, parts[1].length() - 1); - md.put(key, value); - } else { - throw GenericServerError.builder() - .message("Malformed metadata list entry: " + entry) - .build(); - } + public static Map metadataListToMap(List mdList) { + Map md = new HashMap<>(); + for (String entry : mdList) { + // Split on "]:[" to separate key and value + String[] parts = entry.split("]:\\["); + if (parts.length == 2) { + // Remove remaining brackets from start and end + String key = parts[0].substring(1); + String value = parts[1].substring(0, parts[1].length() - 1); + md.put(key, value); + } else { + throw GenericServerError.builder() + .message("Malformed metadata list entry: " + entry) + .build(); + } + } + return md; } - return md; - } } diff --git a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/PutObjectOperationImpl.java b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/PutObjectOperationImpl.java index 4c772673..ca76e83f 100644 --- a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/PutObjectOperationImpl.java +++ b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/PutObjectOperationImpl.java @@ -20,36 +20,36 @@ public class PutObjectOperationImpl implements PutObjectOperation { - private Map clientCache_; + private Map clientCache_; - public PutObjectOperationImpl(Map clientCache) { - clientCache_ = clientCache; - } + public PutObjectOperationImpl(Map clientCache) { + clientCache_ = clientCache; + } - @Override - public PutObjectOutput putObject(PutObjectInput input, RequestContext context) { - try { - final Map metadata = metadataListToMap(input.getMetadata()); - S3Client s3Client = clientCache_.get(input.getClientID()); - s3Client.putObject(builder -> builder - .bucket(input.getBucket()) - .key(input.getKey()) - .overrideConfiguration(withAdditionalConfiguration(metadata)), - RequestBody.fromByteBuffer(input.getBody()) - ); - // The real S3 doesn't provide bucket/key/metadata, so Test doesn't need to either, but we do anyway - return PutObjectOutput.builder() - .bucket(input.getBucket()) - .key(input.getKey()) - .metadata(input.getMetadata()) - .build(); - } catch (Exception e) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - String stackTrace = sw.toString(); - throw GenericServerError.builder() - .message(stackTrace) - .build(); + @Override + public PutObjectOutput putObject(PutObjectInput input, RequestContext context) { + try { + final Map metadata = metadataListToMap(input.getMetadata()); + S3Client s3Client = clientCache_.get(input.getClientID()); + s3Client.putObject(builder -> builder + .bucket(input.getBucket()) + .key(input.getKey()) + .overrideConfiguration(withAdditionalConfiguration(metadata)), + RequestBody.fromByteBuffer(input.getBody()) + ); + // The real S3 doesn't provide bucket/key/metadata, so Test doesn't need to either, but we do anyway + return PutObjectOutput.builder() + .bucket(input.getBucket()) + .key(input.getKey()) + .metadata(input.getMetadata()) + .build(); + } catch (Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + String stackTrace = sw.toString(); + throw GenericServerError.builder() + .message(stackTrace) + .build(); + } } - } } diff --git a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/S3ECJavaTestServer.java b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/S3ECJavaTestServer.java index 32af5fc1..a992cabd 100644 --- a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/S3ECJavaTestServer.java +++ b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/S3ECJavaTestServer.java @@ -11,6 +11,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; + import software.amazon.smithy.java.server.Server; import software.amazon.encryption.s3.service.S3ECTestServer; @@ -29,14 +30,14 @@ public void run() { Map clientCache = new ConcurrentHashMap<>(); Server server = Server.builder() - .endpoints(endpoint) - .addService( - S3ECTestServer.builder() - .addCreateClientOperation(new CreateClientOperationImpl(clientCache)) - .addGetObjectOperation(new GetObjectOperationImpl(clientCache)) - .addPutObjectOperation(new PutObjectOperationImpl(clientCache)) - .build()) - .build(); + .endpoints(endpoint) + .addService( + S3ECTestServer.builder() + .addCreateClientOperation(new CreateClientOperationImpl(clientCache)) + .addGetObjectOperation(new GetObjectOperationImpl(clientCache)) + .addPutObjectOperation(new PutObjectOperationImpl(clientCache)) + .build()) + .build(); System.out.println("Starting server..."); server.start(); try { diff --git a/test-server/java-v4-server/s3ec-staging b/test-server/java-v4-server/s3ec-staging index c101d149..4a4d639e 160000 --- a/test-server/java-v4-server/s3ec-staging +++ b/test-server/java-v4-server/s3ec-staging @@ -1 +1 @@ -Subproject commit c101d14946a8279387b73482a31c03c2f269c9a4 +Subproject commit 4a4d639ee05d6a57826231b1d78689c81672e2a1 diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index 3607bbf0..b6747d8e 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -1,9 +1,8 @@ package software.amazon.encryption.s3; -import software.amazon.awssdk.core.traits.Trait; import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.encryption.s3.internal.InstructionFileConfig; import software.amazon.encryption.s3.algorithms.AlgorithmSuite; +import software.amazon.encryption.s3.internal.InstructionFileConfig; import software.amazon.encryption.s3.materials.AesKeyring; import software.amazon.encryption.s3.materials.Keyring; import software.amazon.encryption.s3.materials.KmsKeyring; @@ -32,135 +31,135 @@ import static software.amazon.encryption.s3.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT; public class CreateClientOperationImpl implements CreateClientOperation { - private Map clientCache_; - - public CreateClientOperationImpl(Map clientCache) { - clientCache_ = clientCache; - } - - // Copied from S3EC. - private boolean onlyOneNonNull(Object... values) { - boolean haveOneNonNull = false; - for (Object o : values) { - if (o != null) { - if (haveOneNonNull) { - return false; + private final Map clientCache_; + + public CreateClientOperationImpl(Map clientCache) { + clientCache_ = clientCache; + } + + // Copied from S3EC. + private boolean onlyOneNonNull(Object... values) { + boolean haveOneNonNull = false; + for (Object o : values) { + if (o != null) { + if (haveOneNonNull) { + return false; + } + + haveOneNonNull = true; + } } - haveOneNonNull = true; - } + return haveOneNonNull; } - return haveOneNonNull; - } - - @Override - public CreateClientOutput createClient(CreateClientInput input, RequestContext context) { - try { - KeyMaterial key = input.getConfig().getKeyMaterial(); - if (!onlyOneNonNull(key.getAesKey(), key.getKmsKeyId(), key.getRsaKey())) { - throw new RuntimeException("KeyMaterial must be only one, non-null input!"); - } - Keyring keyring; - if (key.getAesKey() != null) { - byte[] keyBytes = new byte[key.getAesKey().remaining()]; - key.getAesKey().get(keyBytes); - keyring = AesKeyring.builder() - .wrappingKey(new SecretKeySpec(keyBytes, "AES")) - .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) - .build(); - } else if (key.getRsaKey() != null) { + @Override + public CreateClientOutput createClient(CreateClientInput input, RequestContext context) { try { - byte[] keyBytes = new byte[key.getRsaKey().remaining()]; - key.getRsaKey().get(keyBytes); - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - keyring = RsaKeyring.builder() - .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) - .wrappingKeyPair(PartialRsaKeyPair.builder() - .privateKey(keyFactory.generatePrivate(keySpec)).build()) - .build(); - } catch (NoSuchAlgorithmException | InvalidKeySpecException nse) { - throw new RuntimeException(nse); - } - } else if (key.getKmsKeyId() != null) { - keyring = KmsKeyring.builder() - .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) - .wrappingKeyId(key.getKmsKeyId()) - .build(); - } else { - throw new RuntimeException("No KeyMaterial found!"); - } - - - // Client Creation - boolean instFilePut = false; - if (input.getConfig().getInstructionFileConfig() != null) { - instFilePut = input.getConfig().getInstructionFileConfig().isEnableInstructionFilePutObject(); + KeyMaterial key = input.getConfig().getKeyMaterial(); + if (!onlyOneNonNull(key.getAesKey(), key.getKmsKeyId(), key.getRsaKey())) { + throw new RuntimeException("KeyMaterial must be only one, non-null input!"); + } + Keyring keyring; + if (key.getAesKey() != null) { + byte[] keyBytes = new byte[key.getAesKey().remaining()]; + key.getAesKey().get(keyBytes); + keyring = AesKeyring.builder() + .wrappingKey(new SecretKeySpec(keyBytes, "AES")) + .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) + .build(); + } else if (key.getRsaKey() != null) { + try { + byte[] keyBytes = new byte[key.getRsaKey().remaining()]; + key.getRsaKey().get(keyBytes); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + keyring = RsaKeyring.builder() + .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) + .wrappingKeyPair(PartialRsaKeyPair.builder() + .privateKey(keyFactory.generatePrivate(keySpec)).build()) + .build(); + } catch (NoSuchAlgorithmException | InvalidKeySpecException nse) { + throw new RuntimeException(nse); + } + } else if (key.getKmsKeyId() != null) { + keyring = KmsKeyring.builder() + .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) + .wrappingKeyId(key.getKmsKeyId()) + .build(); + } else { + throw new RuntimeException("No KeyMaterial found!"); + } + + + // Client Creation + boolean instFilePut = false; + if (input.getConfig().getInstructionFileConfig() != null) { + instFilePut = input.getConfig().getInstructionFileConfig().isEnableInstructionFilePutObject(); + } + + // Configure commitment policy if provided + software.amazon.encryption.s3.CommitmentPolicy policy = CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT; + if (input.getConfig().getCommitmentPolicy() != null) { + policy = getCommitmentPolicy(input.getConfig().getCommitmentPolicy()); + } + + // Configure encryption algorithm if provided + AlgorithmSuite algorithm = AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; + if (input.getConfig().getEncryptionAlgorithm() != null) { + algorithm = getAlgorithmSuite(input.getConfig().getEncryptionAlgorithm()); + } + + // V4-Improved server configuration + S3EncryptionClient s3Client = S3EncryptionClient.builderV4() + .instructionFileConfig(InstructionFileConfig.builder() + .instructionFileClient(S3Client.create()) + .enableInstructionFilePutObject(instFilePut) + .build()) + .keyring(keyring) + .commitmentPolicy(policy) + .encryptionAlgorithm(algorithm) + .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) + .enableLegacyUnauthenticatedModes(input.getConfig().isEnableLegacyUnauthenticatedModes()) + .build(); + + UUID uuid = UUID.randomUUID(); + String uuidString = uuid.toString(); + clientCache_.put(uuidString, s3Client); + return CreateClientOutput.builder() + .clientId(uuidString) + .build(); + } catch (Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + String stackTrace = sw.toString(); + throw GenericServerError.builder() + .message(stackTrace) + .build(); } - - // Configure commitment policy if provided - software.amazon.encryption.s3.CommitmentPolicy policy = CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT; - if (input.getConfig().getCommitmentPolicy() != null) { - policy = getCommitmentPolicy(input.getConfig().getCommitmentPolicy()); - } - - // Configure encryption algorithm if provided - AlgorithmSuite algorithm = AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; - if (input.getConfig().getEncryptionAlgorithm() != null) { - algorithm = getAlgorithmSuite(input.getConfig().getEncryptionAlgorithm()); - } - - // V4-Improved server configuration - S3EncryptionClient s3Client = S3EncryptionClient.builderV4() - .instructionFileConfig(InstructionFileConfig.builder() - .instructionFileClient(S3Client.create()) - .enableInstructionFilePutObject(instFilePut) - .build()) - .keyring(keyring) - .commitmentPolicy(policy) - .encryptionAlgorithm(algorithm) - .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) - .enableLegacyUnauthenticatedModes(input.getConfig().isEnableLegacyUnauthenticatedModes()) - .build(); - - UUID uuid = UUID.randomUUID(); - String uuidString = uuid.toString(); - clientCache_.put(uuidString, s3Client); - return CreateClientOutput.builder() - .clientId(uuidString) - .build(); - } catch (Exception e) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - String stackTrace = sw.toString(); - throw GenericServerError.builder() - .message(stackTrace) - .build(); } - } - - private static AlgorithmSuite getAlgorithmSuite(EncryptionAlgorithm input) { - if (input.equals(EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF)) { - return AlgorithmSuite.ALG_AES_256_CBC_IV16_NO_KDF; - } else if (input.equals(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF)) { - return AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; - } else if (input.equals(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)) { - return AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; - } else { - throw new RuntimeException("Unknown encryption algorithm: " + input); + + private static AlgorithmSuite getAlgorithmSuite(EncryptionAlgorithm input) { + if (input.equals(EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF)) { + return AlgorithmSuite.ALG_AES_256_CBC_IV16_NO_KDF; + } else if (input.equals(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF)) { + return AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; + } else if (input.equals(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)) { + return AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; + } else { + throw new RuntimeException("Unknown encryption algorithm: " + input); + } } - } - - private static software.amazon.encryption.s3.CommitmentPolicy getCommitmentPolicy(software.amazon.encryption.s3.model.CommitmentPolicy input) { - if (input.equals(software.amazon.encryption.s3.model.CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)) { - return FORBID_ENCRYPT_ALLOW_DECRYPT; - } else if (input.equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT)) { - return REQUIRE_ENCRYPT_ALLOW_DECRYPT; - } else if (input.equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)) { - return REQUIRE_ENCRYPT_REQUIRE_DECRYPT; - } else { - throw new RuntimeException("Unknown commitment policy: " + input); + + private static software.amazon.encryption.s3.CommitmentPolicy getCommitmentPolicy(software.amazon.encryption.s3.model.CommitmentPolicy input) { + if (input.equals(software.amazon.encryption.s3.model.CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)) { + return FORBID_ENCRYPT_ALLOW_DECRYPT; + } else if (input.equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT)) { + return REQUIRE_ENCRYPT_ALLOW_DECRYPT; + } else if (input.equals(software.amazon.encryption.s3.model.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)) { + return REQUIRE_ENCRYPT_REQUIRE_DECRYPT; + } else { + throw new RuntimeException("Unknown commitment policy: " + input); + } } - } } diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java index e7c5493f..17e9a8ee 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java @@ -3,70 +3,70 @@ 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.S3EncryptionClientException; -import software.amazon.smithy.java.server.RequestContext; import software.amazon.encryption.s3.model.GenericServerError; import software.amazon.encryption.s3.model.GetObjectInput; import software.amazon.encryption.s3.model.GetObjectOutput; import software.amazon.encryption.s3.model.S3EncryptionClientError; import software.amazon.encryption.s3.service.GetObjectOperation; +import software.amazon.smithy.java.server.RequestContext; import java.io.PrintWriter; import java.io.StringWriter; import java.nio.ByteBuffer; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; -import static software.amazon.encryption.s3.S3EncryptionClient.withAdditionalConfiguration; import static software.amazon.encryption.s3.MetadataUtils.metadataListToMap; import static software.amazon.encryption.s3.MetadataUtils.metadataMapToList; +import static software.amazon.encryption.s3.S3EncryptionClient.withAdditionalConfiguration; public class GetObjectOperationImpl implements GetObjectOperation { - private Map clientCache_; - public GetObjectOperationImpl(Map clientCache) { - clientCache_ = clientCache; - } - @Override - public GetObjectOutput getObject(GetObjectInput input, RequestContext context) { - try { - S3Client s3Client = clientCache_.get(input.getClientID()); - Map ecMap = metadataListToMap(input.getMetadata()); + private final Map clientCache_; + + public GetObjectOperationImpl(Map clientCache) { + clientCache_ = clientCache; + } + + @Override + public GetObjectOutput getObject(GetObjectInput input, RequestContext context) { + try { + S3Client s3Client = clientCache_.get(input.getClientID()); + Map ecMap = metadataListToMap(input.getMetadata()); - try { - ResponseBytes resp = s3Client.getObjectAsBytes(builder -> builder - .bucket(input.getBucket()) - .key(input.getKey()) - .overrideConfiguration(withAdditionalConfiguration(ecMap))); + try { + ResponseBytes resp = s3Client.getObjectAsBytes(builder -> builder + .bucket(input.getBucket()) + .key(input.getKey()) + .overrideConfiguration(withAdditionalConfiguration(ecMap))); - List mdAsList = metadataMapToList(resp.response().metadata()); - // Can't use asBB else it gets mad bc cant access backing array - ByteBuffer bb = ByteBuffer.wrap(resp.asByteArray()); - GetObjectOutput output = GetObjectOutput.builder() - .body(bb) - .metadata(mdAsList) - .build(); - return output; - } catch (S3EncryptionClientException s3EncryptionClientException) { - // Modeled exceptions MUST be returned as such - StringWriter sw = new StringWriter(); - s3EncryptionClientException.printStackTrace(new PrintWriter(sw)); - String stackTrace = sw.toString(); - throw S3EncryptionClientError.builder() - .message(stackTrace) - .build(); - } - } catch (Exception e) { - // Don't wrap modeled errors - if (e instanceof S3EncryptionClientError) { - throw e; - } - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - String stackTrace = sw.toString(); - throw GenericServerError.builder() - .message(stackTrace) - .build(); + List mdAsList = metadataMapToList(resp.response().metadata()); + // Can't use asBB else it gets mad bc cant access backing array + ByteBuffer bb = ByteBuffer.wrap(resp.asByteArray()); + GetObjectOutput output = GetObjectOutput.builder() + .body(bb) + .metadata(mdAsList) + .build(); + return output; + } catch (S3EncryptionClientException s3EncryptionClientException) { + // Modeled exceptions MUST be returned as such + StringWriter sw = new StringWriter(); + s3EncryptionClientException.printStackTrace(new PrintWriter(sw)); + String stackTrace = sw.toString(); + throw S3EncryptionClientError.builder() + .message(stackTrace) + .build(); + } + } catch (Exception e) { + // Don't wrap modeled errors + if (e instanceof S3EncryptionClientError) { + throw e; + } + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + String stackTrace = sw.toString(); + throw GenericServerError.builder() + .message(stackTrace) + .build(); + } } - } } diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/MetadataUtils.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/MetadataUtils.java index 036289ec..9eba6a3d 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/MetadataUtils.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/MetadataUtils.java @@ -9,35 +9,35 @@ public class MetadataUtils { - /** - * Annoyingly, Smithy doesn't provide an interface for map types - * in HTTP headers, so we have to do the serde ourselves - */ - public static List metadataMapToList(Map md) { - List mdAsList = new ArrayList<>(md.size()); - for (Map.Entry keyValue : md.entrySet()) { - mdAsList.add("[" + keyValue.getKey() + "]:[" + keyValue.getValue() + "]"); + /** + * Annoyingly, Smithy doesn't provide an interface for map types + * in HTTP headers, so we have to do the serde ourselves + */ + public static List metadataMapToList(Map md) { + List mdAsList = new ArrayList<>(md.size()); + for (Map.Entry keyValue : md.entrySet()) { + mdAsList.add("[" + keyValue.getKey() + "]:[" + keyValue.getValue() + "]"); + } + return mdAsList; } - return mdAsList; - } - public static Map metadataListToMap(List mdList) { - Map md = new HashMap<>(); - for (String entry : mdList) { - // Split on "]:[" to separate key and value - String[] parts = entry.split("]:\\["); - if (parts.length == 2) { - // Remove remaining brackets from start and end - String key = parts[0].substring(1); - String value = parts[1].substring(0, parts[1].length() - 1); - md.put(key, value); - } else { - throw GenericServerError.builder() - .message("Malformed metadata list entry: " + entry) - .build(); - } + public static Map metadataListToMap(List mdList) { + Map md = new HashMap<>(); + for (String entry : mdList) { + // Split on "]:[" to separate key and value + String[] parts = entry.split("]:\\["); + if (parts.length == 2) { + // Remove remaining brackets from start and end + String key = parts[0].substring(1); + String value = parts[1].substring(0, parts[1].length() - 1); + md.put(key, value); + } else { + throw GenericServerError.builder() + .message("Malformed metadata list entry: " + entry) + .build(); + } + } + return md; } - return md; - } } diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/PutObjectOperationImpl.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/PutObjectOperationImpl.java index 4c772673..d399f13d 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/PutObjectOperationImpl.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/PutObjectOperationImpl.java @@ -2,54 +2,51 @@ import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.PutObjectResponse; -import software.amazon.smithy.java.server.RequestContext; import software.amazon.encryption.s3.model.GenericServerError; import software.amazon.encryption.s3.model.PutObjectInput; import software.amazon.encryption.s3.model.PutObjectOutput; import software.amazon.encryption.s3.service.PutObjectOperation; +import software.amazon.smithy.java.server.RequestContext; import java.io.PrintWriter; import java.io.StringWriter; -import java.util.ArrayList; import java.util.Map; -import java.util.stream.Collectors; -import static software.amazon.encryption.s3.S3EncryptionClient.withAdditionalConfiguration; import static software.amazon.encryption.s3.MetadataUtils.metadataListToMap; +import static software.amazon.encryption.s3.S3EncryptionClient.withAdditionalConfiguration; public class PutObjectOperationImpl implements PutObjectOperation { - private Map clientCache_; + private final Map clientCache_; - public PutObjectOperationImpl(Map clientCache) { - clientCache_ = clientCache; - } + public PutObjectOperationImpl(Map clientCache) { + clientCache_ = clientCache; + } - @Override - public PutObjectOutput putObject(PutObjectInput input, RequestContext context) { - try { - final Map metadata = metadataListToMap(input.getMetadata()); - S3Client s3Client = clientCache_.get(input.getClientID()); - s3Client.putObject(builder -> builder - .bucket(input.getBucket()) - .key(input.getKey()) - .overrideConfiguration(withAdditionalConfiguration(metadata)), - RequestBody.fromByteBuffer(input.getBody()) - ); - // The real S3 doesn't provide bucket/key/metadata, so Test doesn't need to either, but we do anyway - return PutObjectOutput.builder() - .bucket(input.getBucket()) - .key(input.getKey()) - .metadata(input.getMetadata()) - .build(); - } catch (Exception e) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - String stackTrace = sw.toString(); - throw GenericServerError.builder() - .message(stackTrace) - .build(); + @Override + public PutObjectOutput putObject(PutObjectInput input, RequestContext context) { + try { + final Map metadata = metadataListToMap(input.getMetadata()); + S3Client s3Client = clientCache_.get(input.getClientID()); + s3Client.putObject(builder -> builder + .bucket(input.getBucket()) + .key(input.getKey()) + .overrideConfiguration(withAdditionalConfiguration(metadata)), + RequestBody.fromByteBuffer(input.getBody()) + ); + // The real S3 doesn't provide bucket/key/metadata, so Test doesn't need to either, but we do anyway + return PutObjectOutput.builder() + .bucket(input.getBucket()) + .key(input.getKey()) + .metadata(input.getMetadata()) + .build(); + } catch (Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + String stackTrace = sw.toString(); + throw GenericServerError.builder() + .message(stackTrace) + .build(); + } } - } } diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/S3ECJavaTestServer.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/S3ECJavaTestServer.java index c3fee4f1..d394b72b 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/S3ECJavaTestServer.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/S3ECJavaTestServer.java @@ -6,13 +6,13 @@ package software.amazon.encryption.s3; import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.encryption.s3.service.S3ECTestServer; +import software.amazon.smithy.java.server.Server; import java.net.URI; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; -import software.amazon.smithy.java.server.Server; -import software.amazon.encryption.s3.service.S3ECTestServer; public class S3ECJavaTestServer implements Runnable { static final URI endpoint = URI.create("http://localhost:8088"); @@ -29,14 +29,14 @@ public void run() { Map clientCache = new ConcurrentHashMap<>(); Server server = Server.builder() - .endpoints(endpoint) - .addService( - S3ECTestServer.builder() - .addCreateClientOperation(new CreateClientOperationImpl(clientCache)) - .addGetObjectOperation(new GetObjectOperationImpl(clientCache)) - .addPutObjectOperation(new PutObjectOperationImpl(clientCache)) - .build()) - .build(); + .endpoints(endpoint) + .addService( + S3ECTestServer.builder() + .addCreateClientOperation(new CreateClientOperationImpl(clientCache)) + .addGetObjectOperation(new GetObjectOperationImpl(clientCache)) + .addPutObjectOperation(new PutObjectOperationImpl(clientCache)) + .build()) + .build(); System.out.println("Starting server..."); server.start(); try { From 4ccaab4b8cf23a45db55b9358b87a205131c9245 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Mon, 10 Nov 2025 08:43:48 -0800 Subject: [PATCH 23/37] chore: enable java-v3-transition test server --- .../src/it/java/software/amazon/encryption/s3/TestUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 8f20cca0..7affb448 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 @@ -128,7 +128,7 @@ public class TestUtils { public static final Set TRANSITION_VERSIONS = Set.of( - // JAVA_V3_TRANSITION, + JAVA_V3_TRANSITION, // GO_V3_TRANSITION, // NET_V2_TRANSITION, NET_V3_TRANSITION, @@ -166,7 +166,7 @@ public class TestUtils { // servers.put(RUBY_V3, new LanguageServerTarget(RUBY_V3, "8092")); servers.put(PHP_V3, new LanguageServerTarget(PHP_V3, "8093")); // TODO: Create and add transition servers - // servers.put(JAVA_V3_TRANSITION, new LanguageServerTarget(JAVA_V3_TRANSITION, "8094")); + servers.put(JAVA_V3_TRANSITION, new LanguageServerTarget(JAVA_V3_TRANSITION, "8094")); // servers.put(GO_V3_TRANSITION, new LanguageServerTarget(GO_V3_TRANSITION, "8095")); // servers.put(NET_V2_TRANSITION, new LanguageServerTarget(NET_V2_TRANSITION, "8096")); // servers.put(RUBY_V2_TRANSITION, new LanguageServerTarget(RUBY_V2_TRANSITION, "8098")); From ff8e92b843880143bfd28beadc821e3e57a65a7f Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Mon, 10 Nov 2025 11:25:49 -0800 Subject: [PATCH 24/37] update .gitmodule branch --- .gitmodules | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index fe27b90e..d7bed379 100644 --- a/.gitmodules +++ b/.gitmodules @@ -18,12 +18,11 @@ [submodule "test-server/java-v3-transition-server/s3ec-staging"] path = test-server/java-v3-transition-server/s3ec-staging url = git@github.com:aws/private-amazon-s3-encryption-client-java-staging.git - branch = imabhichow/s3ec-transition + branch = imabhichow/transition-read-kc [submodule "test-server/java-v4-server/s3ec-staging"] path = test-server/java-v4-server/s3ec-staging url = git@github.com:aws/private-amazon-s3-encryption-client-java-staging.git branch = imabhichow/add-kc -; branch = s3ec/improved [submodule "test-server/java-v4-server/specification"] path = test-server/java-v4-server/specification url = git@github.com:awslabs/private-aws-encryption-sdk-specification-staging.git From b7bf8646fea4ce3e5a17bd887d12379a61f484f3 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Wed, 12 Nov 2025 01:13:43 -0800 Subject: [PATCH 25/37] chore: add ranged get tests --- .../amazon/encryption/s3/CBCDecryptTests.java | 104 ++++++++++--- .../amazon/encryption/s3/GCMTests.java | 124 +++++++++++---- .../amazon/encryption/s3/KC_GCMTests.java | 142 ++++++++++++++---- .../amazon/encryption/s3/TestUtils.java | 75 +++++++++ .../encryption/s3/GetObjectOperationImpl.java | 1 + .../java-v3-transition-server/s3ec-staging | 2 +- .../encryption/s3/GetObjectOperationImpl.java | 1 + test-server/java-v4-server/s3ec-staging | 2 +- .../encryption/s3/GetObjectOperationImpl.java | 1 + test-server/model/object.smithy | 4 + 10 files changed, 370 insertions(+), 86 deletions(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java index 093ba2ab..c6ae6e36 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java @@ -5,46 +5,30 @@ 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 static software.amazon.encryption.s3.TestUtils.appendTestSuffix; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import java.util.Arrays; -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.Nested; -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.GetObjectInput; -import software.amazon.encryption.s3.model.GetObjectOutput; -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 software.amazon.encryption.s3.model.EncryptionAlgorithm; 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; +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.KeyMaterial; +import software.amazon.encryption.s3.model.S3ECConfig; + /** * Exhaustive tests for S3 Encryption Client round-trip operations. * These tests cover various combinations of client versions, commitment policies, and encryption modes. @@ -181,4 +165,74 @@ void improved_configured_with_the_default_should_fail_to_decrypt_cbc(TestUtils.L TestUtils.Decrypt_fails(decClient, decS3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); } + + // Ranged Get Tests - using existing CBC encrypted object with ranged-get-supported clients + + @ParameterizedTest(name = "{0}: Transition clients can ranged get CBC") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetTransitionClientsForTest") + void transition_configured_with_forbid_encrypt_allow_decrypt_ranged_get_cbc(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT) + .enableLegacyUnauthenticatedModes(true) + .enableLegacyWrappingAlgorithms(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); + } + + @ParameterizedTest(name = "{0}: Improved (Forbid) clients can ranged get CBC") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_forbid_encrypt_allow_decrypt_should_ranged_get_cbc(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient decClient = TestUtils.testServerClientFor(language); + CreateClientOutput decClientOutput = decClient.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .enableLegacyUnauthenticatedModes(true) + .enableLegacyWrappingAlgorithms(true) + .build()) + .build()); + String decS3ECId = decClientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(decClient, decS3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); + } + + @ParameterizedTest(name = "{0}: Improved (Require/Allow) clients can ranged get CBC") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_require_encrypt_allow_decrypt_should_ranged_get_cbc(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient decClient = TestUtils.testServerClientFor(language); + CreateClientOutput decClientOutput = decClient.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT) + .enableLegacyUnauthenticatedModes(true) + .enableLegacyWrappingAlgorithms(true) + .build()) + .build()); + String decS3ECId = decClientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(decClient, decS3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); + } + + @ParameterizedTest(name = "{0}: Improved (Require/Require) clients CANNOT ranged get CBC") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_require_encrypt_require_decrypt_should_ranged_get_cbc(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient decClient = TestUtils.testServerClientFor(language); + CreateClientOutput decClientOutput = decClient.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String decS3ECId = decClientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(decClient, decS3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); + } } diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java index 6eef0b5f..8f62a0a5 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java @@ -5,48 +5,24 @@ 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 static software.amazon.encryption.s3.TestUtils.appendTestSuffix; -import java.lang.annotation.ElementType; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; 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.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + 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.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. @@ -159,6 +135,7 @@ void transition_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_gcm( .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String S3ECId = clientOutput.getClientId(); @@ -199,5 +176,94 @@ void improved_configured_with_require_encrypt_require_decrypt_should_fail_to_dec TestUtils.Decrypt_fails(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); } + + // Ranged Get Tests - using existing GCM encrypted objects with ranged-get-supported clients + + @Order(21) + @ParameterizedTest(name = "{0}: Transition configured with the default can ranged get GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetTransitionClientsForTest") + void transition_configured_with_the_default_can_ranged_get_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .enableLegacyUnauthenticatedModes(true) + // .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); + } + + @Order(22) + @ParameterizedTest(name = "{0}: Transition configured with ForbidEncryptAllowDecrypt can ranged get GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetTransitionClientsForTest") + void transition_configured_with_forbid_encrypt_allow_decrypt_can_ranged_get_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); + } + + @Order(23) + @ParameterizedTest(name = "{0}: Improved configured with ForbidEncryptAllowDecrypt can ranged get GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_forbid_encrypt_allow_decrypt_can_ranged_get_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); + } + + @Order(24) + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptAllowDecrypt can ranged get GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_require_encrypt_allow_decrypt_can_ranged_get_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); + } + + @Order(25) + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should fail to ranged get GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_require_encrypt_require_decrypt_should_fail_to_ranged_get_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.Decrypt_fails(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); + } } 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..6c3d5b34 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,24 @@ 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 static software.amazon.encryption.s3.TestUtils.appendTestSuffix; + 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.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + 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.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. @@ -215,5 +191,111 @@ 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); } + + // Ranged Get Tests - using existing KC-GCM encrypted objects with ranged-get-supported clients + + @Order(20) + @ParameterizedTest(name = "{0}: Transition configured with the default can ranged get KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetTransitionClientsForTest") + void transition_configured_with_the_default_can_ranged_get_kc_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .enableLegacyUnauthenticatedModes(true) + // .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } + + @Order(21) + @ParameterizedTest(name = "{0}: Transition configured with ForbidEncryptAllowDecrypt can ranged get KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetTransitionClientsForTest") + void transition_configured_with_forbid_encrypt_allow_decrypt_can_ranged_get_kc_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } + + @Order(22) + @ParameterizedTest(name = "{0}: Improved configured with ForbidEncryptAllowDecrypt can ranged get KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_forbid_encrypt_allow_decrypt_can_ranged_get_kc_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } + + @Order(23) + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptAllowDecrypt can ranged get KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_require_encrypt_allow_decrypt_can_ranged_get_kc_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } + + @Order(24) + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt can ranged get KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_require_encrypt_require_decrypt_can_ranged_get_kc_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .enableLegacyUnauthenticatedModes(true) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } + + @Order(25) + @ParameterizedTest(name = "{0}: Improved configured with the default can ranged get KC-GCM") + @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") + void improved_configured_with_the_default_can_ranged_get_kc_gcm(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = TestUtils.testServerClientFor(language); + CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .enableLegacyUnauthenticatedModes(true) + // .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .build()) + .build()); + String S3ECId = clientOutput.getClientId(); + + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + } } 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 70f44066..f82b492b 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 @@ -18,6 +18,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Random; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -121,6 +122,24 @@ public class TestUtils { public static final Set INSTRUCTION_FILE_ROUNDTRIP_TEMP_UNSUPPORTED = Set.of(PHP_V2_CURRENT, PHP_V2_TRANSITION, PHP_V3); + public static final Set RANGED_GET_CURRENT_VERSIONS = + Set.of( + JAVA_V3_CURRENT, + CPP_V2_CURRENT + ); + + public static final Set RANGED_GET_TRANSITION_VERSIONS = + Set.of( + JAVA_V3_TRANSITION, + CPP_V2_TRANSITION + ); + + public static final Set RANGED_GET_IMPROVED_VERSIONS = + Set.of( + JAVA_V4, + CPP_V3 + ); + public static final Set CURRENT_VERSIONS = Set.of( JAVA_V3_CURRENT, @@ -439,6 +458,34 @@ public static Stream crossLanguageClients() { ))); } + /** + * Get stream of arguments for current version clients which support ranged gets for testing. + */ + public static Stream rangedGetCurrentClientsForTest() { + return serverMap.values().stream() + .filter(target -> RANGED_GET_CURRENT_VERSIONS.contains(target.getLanguageName())) + .map(Arguments::of); + } + + /** + * Get stream of arguments for transition version clients for testing. + */ + public static Stream rangedGetTransitionClientsForTest() { + return serverMap.values().stream() + .filter(target -> RANGED_GET_TRANSITION_VERSIONS.contains(target.getLanguageName())) + .map(Arguments::of); + } + + /** + * Get stream of arguments for improved version clients for testing. + */ + public static Stream rangedGetImprovedClientsForTest() { + return serverMap.values().stream() + .filter(target -> RANGED_GET_IMPROVED_VERSIONS.contains(target.getLanguageName())) + .map(Arguments::of); + } + + /** * For a given string, append a suffix to distinguish it from * simultaneous test runs. @@ -518,6 +565,34 @@ public static void Decrypt( } } + public static void DecryptWithRangedGet( + S3ECTestServerClient client, + String S3ECId, List crossLanguageObjects, + EncryptionAlgorithm expectedEncryptionAlgorithm + ) { + Random rand = new Random(); + for (String objectKey : crossLanguageObjects) { + // Get random range within the object length + int max = objectKey.length() - 1; + int begin = rand.nextInt(max), end = rand.nextInt(max - begin) + begin + 1; + String range = "bytes=" + begin + "-" + end; + GetObjectOutput output = client.getObject(GetObjectInput.builder() + .clientID(S3ECId) + .bucket(TestUtils.BUCKET) + .range(range) + .key(objectKey) + .build()); + + // Then: Pass + assertEquals(objectKey.substring(begin, end + 1), output.getBody().toString()); + assertEquals( + expectedEncryptionAlgorithm, + GetEncryptionAlgorithm(objectKey), + "When decrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm + ); + } + } + public static void Decrypt_fails( S3ECTestServerClient client, String S3ECId, List crossLanguageObjects, diff --git a/test-server/java-v3-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java b/test-server/java-v3-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java index e7c5493f..b7def958 100644 --- a/test-server/java-v3-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java +++ b/test-server/java-v3-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java @@ -37,6 +37,7 @@ public GetObjectOutput getObject(GetObjectInput input, RequestContext context) { ResponseBytes resp = s3Client.getObjectAsBytes(builder -> builder .bucket(input.getBucket()) .key(input.getKey()) + .range(input.getRange()) .overrideConfiguration(withAdditionalConfiguration(ecMap))); List mdAsList = metadataMapToList(resp.response().metadata()); diff --git a/test-server/java-v3-transition-server/s3ec-staging b/test-server/java-v3-transition-server/s3ec-staging index 9042d648..403e9d8b 160000 --- a/test-server/java-v3-transition-server/s3ec-staging +++ b/test-server/java-v3-transition-server/s3ec-staging @@ -1 +1 @@ -Subproject commit 9042d64860d240146a11a379e38b78f812dc7358 +Subproject commit 403e9d8b99571fa932fb2fba06d62374dd452ad4 diff --git a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java index 86749489..155ee15e 100644 --- a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java +++ b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java @@ -39,6 +39,7 @@ public GetObjectOutput getObject(GetObjectInput input, RequestContext context) { ResponseBytes resp = s3Client.getObjectAsBytes(builder -> builder .bucket(input.getBucket()) .key(input.getKey()) + .range(input.getRange()) .overrideConfiguration(withAdditionalConfiguration(ecMap))); List mdAsList = metadataMapToList(resp.response().metadata()); diff --git a/test-server/java-v4-server/s3ec-staging b/test-server/java-v4-server/s3ec-staging index 4a4d639e..a67c4dfd 160000 --- a/test-server/java-v4-server/s3ec-staging +++ b/test-server/java-v4-server/s3ec-staging @@ -1 +1 @@ -Subproject commit 4a4d639ee05d6a57826231b1d78689c81672e2a1 +Subproject commit a67c4dfde56053f802465f3f80b8d53d7b293fe0 diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java index 17e9a8ee..c21c0ead 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/GetObjectOperationImpl.java @@ -37,6 +37,7 @@ public GetObjectOutput getObject(GetObjectInput input, RequestContext context) { ResponseBytes resp = s3Client.getObjectAsBytes(builder -> builder .bucket(input.getBucket()) .key(input.getKey()) + .range(input.getRange()) .overrideConfiguration(withAdditionalConfiguration(ecMap))); List mdAsList = metadataMapToList(resp.response().metadata()); diff --git a/test-server/model/object.smithy b/test-server/model/object.smithy index 6d793353..3ff1cf3c 100644 --- a/test-server/model/object.smithy +++ b/test-server/model/object.smithy @@ -80,6 +80,10 @@ operation GetObject { @required @notProperty clientID: String + + @httpHeader("Range") + @notProperty + range: String } output := for Object { From 402acb3cf0e9296b9846efdc1b39d2ac258c8bb1 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Wed, 12 Nov 2025 09:31:25 -0800 Subject: [PATCH 26/37] chore: add ranged get tests --- .../src/it/java/software/amazon/encryption/s3/TestUtils.java | 2 +- 1 file changed, 1 insertion(+), 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 f82b492b..e1d38346 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 @@ -584,7 +584,7 @@ public static void DecryptWithRangedGet( .build()); // Then: Pass - assertEquals(objectKey.substring(begin, end + 1), output.getBody().toString()); + assertEquals(objectKey.substring(begin, end + 1).getBytes(StandardCharsets.UTF_8), output.getBody().array()); assertEquals( expectedEncryptionAlgorithm, GetEncryptionAlgorithm(objectKey), From 8370d0806e7488ef7fbf399de4b237ad41fd4401 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Wed, 12 Nov 2025 23:15:52 -0800 Subject: [PATCH 27/37] more tests --- .../amazon/encryption/s3/CBCDecryptTests.java | 13 ++--- .../amazon/encryption/s3/GCMTests.java | 2 +- .../amazon/encryption/s3/TestUtils.java | 52 ++++++++++++++++--- 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java index c6ae6e36..f8eb52fa 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/CBCDecryptTests.java @@ -168,14 +168,15 @@ void improved_configured_with_the_default_should_fail_to_decrypt_cbc(TestUtils.L // Ranged Get Tests - using existing CBC encrypted object with ranged-get-supported clients - @ParameterizedTest(name = "{0}: Transition clients can ranged get CBC") + @ParameterizedTest(name = "{0}: Transition configured with ForbidEncryptAllowDecrypt can ranged get CBC") @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetTransitionClientsForTest") void transition_configured_with_forbid_encrypt_allow_decrypt_ranged_get_cbc(TestUtils.LanguageServerTarget language) { S3ECTestServerClient client = TestUtils.testServerClientFor(language); CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() .config(S3ECConfig.builder() .keyMaterial(kmsKeyArn) - .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .enableLegacyUnauthenticatedModes(true) .enableLegacyWrappingAlgorithms(true) .build()) @@ -185,7 +186,7 @@ void transition_configured_with_forbid_encrypt_allow_decrypt_ranged_get_cbc(Test TestUtils.DecryptWithRangedGet(client, S3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); } - @ParameterizedTest(name = "{0}: Improved (Forbid) clients can ranged get CBC") + @ParameterizedTest(name = "{0}: Improved configured with ForbidEncryptAllowDecrypt can ranged get CBC") @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") void improved_configured_with_forbid_encrypt_allow_decrypt_should_ranged_get_cbc(TestUtils.LanguageServerTarget language) { S3ECTestServerClient decClient = TestUtils.testServerClientFor(language); @@ -203,7 +204,7 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_should_ranged_get_cbc TestUtils.DecryptWithRangedGet(decClient, decS3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); } - @ParameterizedTest(name = "{0}: Improved (Require/Allow) clients can ranged get CBC") + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptAllowDecrypt should ranged get CBC") @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") void improved_configured_with_require_encrypt_allow_decrypt_should_ranged_get_cbc(TestUtils.LanguageServerTarget language) { S3ECTestServerClient decClient = TestUtils.testServerClientFor(language); @@ -220,7 +221,7 @@ void improved_configured_with_require_encrypt_allow_decrypt_should_ranged_get_cb TestUtils.DecryptWithRangedGet(decClient, decS3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); } - @ParameterizedTest(name = "{0}: Improved (Require/Require) clients CANNOT ranged get CBC") + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should FAIL to ranged get CBC") @MethodSource("software.amazon.encryption.s3.TestUtils#rangedGetImprovedClientsForTest") void improved_configured_with_require_encrypt_require_decrypt_should_ranged_get_cbc(TestUtils.LanguageServerTarget language) { S3ECTestServerClient decClient = TestUtils.testServerClientFor(language); @@ -233,6 +234,6 @@ void improved_configured_with_require_encrypt_require_decrypt_should_ranged_get_ .build()); String decS3ECId = decClientOutput.getClientId(); - TestUtils.DecryptWithRangedGet(decClient, decS3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); + TestUtils.DecryptWithRangedGet_fails(decClient, decS3ECId, Arrays.asList(sharedObjectKey), EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF); } } diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java index 8f62a0a5..03e16095 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/GCMTests.java @@ -263,7 +263,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_fail_to_ran .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt_fails(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); + TestUtils.DecryptWithRangedGet_fails(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF); } } 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 e1d38346..4d945c66 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 @@ -12,6 +12,7 @@ import java.net.URI; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; @@ -124,20 +125,20 @@ public class TestUtils { public static final Set RANGED_GET_CURRENT_VERSIONS = Set.of( - JAVA_V3_CURRENT, - CPP_V2_CURRENT + JAVA_V3_CURRENT + // CPP_V2_CURRENT ); public static final Set RANGED_GET_TRANSITION_VERSIONS = Set.of( - JAVA_V3_TRANSITION, - CPP_V2_TRANSITION + JAVA_V3_TRANSITION + // CPP_V2_TRANSITION ); public static final Set RANGED_GET_IMPROVED_VERSIONS = Set.of( - JAVA_V4, - CPP_V3 + JAVA_V4 + // CPP_V3 ); public static final Set CURRENT_VERSIONS = @@ -584,7 +585,7 @@ public static void DecryptWithRangedGet( .build()); // Then: Pass - assertEquals(objectKey.substring(begin, end + 1).getBytes(StandardCharsets.UTF_8), output.getBody().array()); + assertTrue(MessageDigest.isEqual(objectKey.substring(begin, end + 1).getBytes(StandardCharsets.UTF_8), output.getBody().array())); assertEquals( expectedEncryptionAlgorithm, GetEncryptionAlgorithm(objectKey), @@ -593,6 +594,43 @@ public static void DecryptWithRangedGet( } } + + public static void DecryptWithRangedGet_fails( + S3ECTestServerClient client, + String S3ECId, List crossLanguageObjects, + EncryptionAlgorithm expectedEncryptionAlgorithm + ) { + List successfulDecrypt = new ArrayList<>(); + Random rand = new Random(); + for (String objectKey : crossLanguageObjects) { + try { + + assertEquals( + expectedEncryptionAlgorithm, + GetEncryptionAlgorithm(objectKey), + "Before decrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm + ); + // Get random range within the object length + int max = objectKey.length() - 1; + int begin = rand.nextInt(max), end = rand.nextInt(max - begin) + begin + 1; + String range = "bytes=" + begin + "-" + end; + GetObjectOutput output = client.getObject(GetObjectInput.builder() + .clientID(S3ECId) + .bucket(TestUtils.BUCKET) + .range(range) + .key(objectKey) + .build()); + // It should fail to decrypt + successfulDecrypt.add(objectKey); + } catch (S3EncryptionClientError e) { + // This is a success + // TODO, add the failure message + } + } + + assertEquals(successfulDecrypt.size(), 0, "Ranged get should have failed:" + String.join(",", successfulDecrypt)); + } + public static void Decrypt_fails( S3ECTestServerClient client, String S3ECId, List crossLanguageObjects, From 1c63c14116e47cead8607056c6f996c4ae5c5ff6 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Wed, 12 Nov 2025 23:17:17 -0800 Subject: [PATCH 28/37] cpp ranged get --- test-server/cpp-v2-transition-server/main.cpp | 7 +++++-- test-server/cpp-v3-server/main.cpp | 7 +++++-- .../software/amazon/encryption/s3/TestUtils.java | 12 ++++++------ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/test-server/cpp-v2-transition-server/main.cpp b/test-server/cpp-v2-transition-server/main.cpp index 1fcedc3c..1e6935af 100644 --- a/test-server/cpp-v2-transition-server/main.cpp +++ b/test-server/cpp-v2-transition-server/main.cpp @@ -168,7 +168,8 @@ void fill_context(Aws::Map &map, MHD_Result handle_get_object(struct MHD_Connection *connection, const std::string &bucket, const std::string &key, const std::string &client_id, - const std::string &metadata) { + const std::string &metadata, + const std::string &range) { auto it = client_cache.find(client_id); if (it == client_cache.end()) { return send_response(connection, 404, "{\"error\":\"Client not found\"}"); @@ -178,6 +179,7 @@ MHD_Result handle_get_object(struct MHD_Connection *connection, Aws::S3::Model::GetObjectRequest request; request.SetBucket(bucket); request.SetKey(key); + request.SetRange(range); // S3EncryptionGetObjectOutcome outcome ; // if (metadata.empty()) { @@ -280,8 +282,9 @@ MHD_Result request_handler(void *cls, struct MHD_Connection *connection, std::string client_id = get_header_value(connection, "clientid"); std::string metadata = get_header_value(connection, "content-metadata"); + std::string range = get_header_value(range, "range") if (method_str == "GET") { - return handle_get_object(connection, bucket, key, client_id, metadata); + return handle_get_object(connection, bucket, key, client_id, metadata, range); } else if (method_str == "PUT") { std::unique_ptr body(static_cast(*con_cls)); *upload_data_size = 0; diff --git a/test-server/cpp-v3-server/main.cpp b/test-server/cpp-v3-server/main.cpp index 1f74974c..e4b3ad0a 100644 --- a/test-server/cpp-v3-server/main.cpp +++ b/test-server/cpp-v3-server/main.cpp @@ -174,7 +174,8 @@ void fill_context(Aws::Map &map, MHD_Result handle_get_object(struct MHD_Connection *connection, const std::string &bucket, const std::string &key, const std::string &client_id, - const std::string &metadata) { + const std::string &metadata, + const std::string &range) { auto it = client_cache.find(client_id); if (it == client_cache.end()) { return send_response(connection, 404, "{\"error\":\"Client not found\"}"); @@ -184,6 +185,7 @@ MHD_Result handle_get_object(struct MHD_Connection *connection, Aws::S3::Model::GetObjectRequest request; request.SetBucket(bucket); request.SetKey(key); + request.SetRange(range); // S3EncryptionGetObjectOutcome outcome ; // if (metadata.empty()) { @@ -290,8 +292,9 @@ MHD_Result request_handler(void *cls, struct MHD_Connection *connection, std::string client_id = get_header_value(connection, "clientid"); std::string metadata = get_header_value(connection, "content-metadata"); + std::string range = get_header_value(range, "range") if (method_str == "GET") { - return handle_get_object(connection, bucket, key, client_id, metadata); + return handle_get_object(connection, bucket, key, client_id, metadata, range); } else if (method_str == "PUT") { std::unique_ptr body(static_cast(*con_cls)); *upload_data_size = 0; 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 4d945c66..20cd8c0c 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 @@ -125,20 +125,20 @@ public class TestUtils { public static final Set RANGED_GET_CURRENT_VERSIONS = Set.of( - JAVA_V3_CURRENT - // CPP_V2_CURRENT + JAVA_V3_CURRENT, + CPP_V2_CURRENT ); public static final Set RANGED_GET_TRANSITION_VERSIONS = Set.of( - JAVA_V3_TRANSITION - // CPP_V2_TRANSITION + JAVA_V3_TRANSITION, + CPP_V2_TRANSITION ); public static final Set RANGED_GET_IMPROVED_VERSIONS = Set.of( - JAVA_V4 - // CPP_V3 + JAVA_V4, + CPP_V3 ); public static final Set CURRENT_VERSIONS = From a58ef9a90799f8986131b487c6b0a3db0af92075 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Wed, 12 Nov 2025 23:17:26 -0800 Subject: [PATCH 29/37] Revert "cpp ranged get" This reverts commit 1c63c14116e47cead8607056c6f996c4ae5c5ff6. --- test-server/cpp-v2-transition-server/main.cpp | 7 ++----- test-server/cpp-v3-server/main.cpp | 7 ++----- .../software/amazon/encryption/s3/TestUtils.java | 12 ++++++------ 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/test-server/cpp-v2-transition-server/main.cpp b/test-server/cpp-v2-transition-server/main.cpp index 1e6935af..1fcedc3c 100644 --- a/test-server/cpp-v2-transition-server/main.cpp +++ b/test-server/cpp-v2-transition-server/main.cpp @@ -168,8 +168,7 @@ void fill_context(Aws::Map &map, MHD_Result handle_get_object(struct MHD_Connection *connection, const std::string &bucket, const std::string &key, const std::string &client_id, - const std::string &metadata, - const std::string &range) { + const std::string &metadata) { auto it = client_cache.find(client_id); if (it == client_cache.end()) { return send_response(connection, 404, "{\"error\":\"Client not found\"}"); @@ -179,7 +178,6 @@ MHD_Result handle_get_object(struct MHD_Connection *connection, Aws::S3::Model::GetObjectRequest request; request.SetBucket(bucket); request.SetKey(key); - request.SetRange(range); // S3EncryptionGetObjectOutcome outcome ; // if (metadata.empty()) { @@ -282,9 +280,8 @@ MHD_Result request_handler(void *cls, struct MHD_Connection *connection, std::string client_id = get_header_value(connection, "clientid"); std::string metadata = get_header_value(connection, "content-metadata"); - std::string range = get_header_value(range, "range") if (method_str == "GET") { - return handle_get_object(connection, bucket, key, client_id, metadata, range); + return handle_get_object(connection, bucket, key, client_id, metadata); } else if (method_str == "PUT") { std::unique_ptr body(static_cast(*con_cls)); *upload_data_size = 0; diff --git a/test-server/cpp-v3-server/main.cpp b/test-server/cpp-v3-server/main.cpp index e4b3ad0a..1f74974c 100644 --- a/test-server/cpp-v3-server/main.cpp +++ b/test-server/cpp-v3-server/main.cpp @@ -174,8 +174,7 @@ void fill_context(Aws::Map &map, MHD_Result handle_get_object(struct MHD_Connection *connection, const std::string &bucket, const std::string &key, const std::string &client_id, - const std::string &metadata, - const std::string &range) { + const std::string &metadata) { auto it = client_cache.find(client_id); if (it == client_cache.end()) { return send_response(connection, 404, "{\"error\":\"Client not found\"}"); @@ -185,7 +184,6 @@ MHD_Result handle_get_object(struct MHD_Connection *connection, Aws::S3::Model::GetObjectRequest request; request.SetBucket(bucket); request.SetKey(key); - request.SetRange(range); // S3EncryptionGetObjectOutcome outcome ; // if (metadata.empty()) { @@ -292,9 +290,8 @@ MHD_Result request_handler(void *cls, struct MHD_Connection *connection, std::string client_id = get_header_value(connection, "clientid"); std::string metadata = get_header_value(connection, "content-metadata"); - std::string range = get_header_value(range, "range") if (method_str == "GET") { - return handle_get_object(connection, bucket, key, client_id, metadata, range); + return handle_get_object(connection, bucket, key, client_id, metadata); } else if (method_str == "PUT") { std::unique_ptr body(static_cast(*con_cls)); *upload_data_size = 0; 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 20cd8c0c..4d945c66 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 @@ -125,20 +125,20 @@ public class TestUtils { public static final Set RANGED_GET_CURRENT_VERSIONS = Set.of( - JAVA_V3_CURRENT, - CPP_V2_CURRENT + JAVA_V3_CURRENT + // CPP_V2_CURRENT ); public static final Set RANGED_GET_TRANSITION_VERSIONS = Set.of( - JAVA_V3_TRANSITION, - CPP_V2_TRANSITION + JAVA_V3_TRANSITION + // CPP_V2_TRANSITION ); public static final Set RANGED_GET_IMPROVED_VERSIONS = Set.of( - JAVA_V4, - CPP_V3 + JAVA_V4 + // CPP_V3 ); public static final Set CURRENT_VERSIONS = From 09d339da618da0d35109f28c543c21cdca316197 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Thu, 13 Nov 2025 08:53:28 -0800 Subject: [PATCH 30/37] Merge Conflicts --- .../java-v3-transition-server/s3ec-staging | 2 +- .../s3/CreateClientOperationImpl.java | 25 ++++++++++++++++--- test-server/java-v4-server/s3ec-staging | 2 +- .../s3/CreateClientOperationImpl.java | 21 +++++++++++++--- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/test-server/java-v3-transition-server/s3ec-staging b/test-server/java-v3-transition-server/s3ec-staging index 9042d648..86ca56f6 160000 --- a/test-server/java-v3-transition-server/s3ec-staging +++ b/test-server/java-v3-transition-server/s3ec-staging @@ -1 +1 @@ -Subproject commit 9042d64860d240146a11a379e38b78f812dc7358 +Subproject commit 86ca56f6668d447a5d1f126ade8123712171dbab diff --git a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index 8b9cb0f4..1cccb2fe 100644 --- a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -1,8 +1,8 @@ package software.amazon.encryption.s3; import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.encryption.s3.algorithms.AlgorithmSuite; import software.amazon.encryption.s3.internal.InstructionFileConfig; +import software.amazon.encryption.s3.algorithms.AlgorithmSuite; import software.amazon.encryption.s3.materials.AesKeyring; import software.amazon.encryption.s3.materials.Keyring; import software.amazon.encryption.s3.materials.KmsKeyring; @@ -21,7 +21,10 @@ import java.io.StringWriter; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.interfaces.RSAPrivateCrtKey; import java.security.spec.InvalidKeySpecException; +import java.security.spec.RSAPublicKeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Map; import java.util.UUID; @@ -31,7 +34,7 @@ import static software.amazon.encryption.s3.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT; public class CreateClientOperationImpl implements CreateClientOperation { - private Map clientCache_; + private final Map clientCache_; public CreateClientOperationImpl(Map clientCache) { clientCache_ = clientCache; @@ -74,13 +77,25 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c key.getRsaKey().get(keyBytes); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec); + RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec( + privateKey.getModulus(), + privateKey.getPublicExponent() + ); + + // Generate public key + PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); + keyring = RsaKeyring.builder() .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) .wrappingKeyPair(PartialRsaKeyPair.builder() - .privateKey(keyFactory.generatePrivate(keySpec)).build()) + .publicKey(publicKey) + .privateKey(privateKey).build()) .build(); } catch (NoSuchAlgorithmException | InvalidKeySpecException nse) { - throw new RuntimeException(nse); + throw GenericServerError.builder() + .message(nse.getMessage()) + .build(); } } else if (key.getKmsKeyId() != null) { keyring = KmsKeyring.builder() @@ -91,6 +106,8 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c throw new RuntimeException("No KeyMaterial found!"); } + + // Client Creation boolean instFilePut = false; if (input.getConfig().getInstructionFileConfig() != null) { instFilePut = input.getConfig().getInstructionFileConfig().isEnableInstructionFilePutObject(); diff --git a/test-server/java-v4-server/s3ec-staging b/test-server/java-v4-server/s3ec-staging index 4a4d639e..d0dad541 160000 --- a/test-server/java-v4-server/s3ec-staging +++ b/test-server/java-v4-server/s3ec-staging @@ -1 +1 @@ -Subproject commit 4a4d639ee05d6a57826231b1d78689c81672e2a1 +Subproject commit d0dad5413b2114998e040325b4b6108e822de012 diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index b6747d8e..c7308328 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -1,8 +1,8 @@ package software.amazon.encryption.s3; import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.encryption.s3.algorithms.AlgorithmSuite; import software.amazon.encryption.s3.internal.InstructionFileConfig; +import software.amazon.encryption.s3.algorithms.AlgorithmSuite; import software.amazon.encryption.s3.materials.AesKeyring; import software.amazon.encryption.s3.materials.Keyring; import software.amazon.encryption.s3.materials.KmsKeyring; @@ -21,7 +21,10 @@ import java.io.StringWriter; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.interfaces.RSAPrivateCrtKey; import java.security.spec.InvalidKeySpecException; +import java.security.spec.RSAPublicKeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Map; import java.util.UUID; @@ -74,13 +77,25 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c key.getRsaKey().get(keyBytes); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec); + RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec( + privateKey.getModulus(), + privateKey.getPublicExponent() + ); + + // Generate public key + PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); + keyring = RsaKeyring.builder() .enableLegacyWrappingAlgorithms(input.getConfig().isEnableLegacyWrappingAlgorithms()) .wrappingKeyPair(PartialRsaKeyPair.builder() - .privateKey(keyFactory.generatePrivate(keySpec)).build()) + .publicKey(publicKey) + .privateKey(privateKey).build()) .build(); } catch (NoSuchAlgorithmException | InvalidKeySpecException nse) { - throw new RuntimeException(nse); + throw GenericServerError.builder() + .message(nse.getMessage()) + .build(); } } else if (key.getKmsKeyId() != null) { keyring = KmsKeyring.builder() From 375ff21eb5a51dad614d9f3b002c2a52daeffb48 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Thu, 13 Nov 2025 09:03:28 -0800 Subject: [PATCH 31/37] m --- .../src/it/java/software/amazon/encryption/s3/TestUtils.java | 1 + 1 file changed, 1 insertion(+) 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 5b1a8b0d..5e9408d5 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 @@ -123,6 +123,7 @@ public class TestUtils { public static final Set INSTRUCTION_FILE_ROUNDTRIP_TEMP_UNSUPPORTED = Set.of(PHP_V2_CURRENT, PHP_V2_TRANSITION, PHP_V3); + // Ranged Get Supported Versions public static final Set RANGED_GET_CURRENT_VERSIONS = Set.of( JAVA_V3_CURRENT From c159f9fc80e13b7128735276d34ed4ab388c48fe Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Fri, 14 Nov 2025 13:26:10 -0800 Subject: [PATCH 32/37] Reapply "cpp ranged get" This reverts commit a58ef9a90799f8986131b487c6b0a3db0af92075. --- test-server/cpp-v2-transition-server/main.cpp | 7 +++++-- test-server/cpp-v3-server/main.cpp | 7 +++++-- .../software/amazon/encryption/s3/TestUtils.java | 12 ++++++------ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/test-server/cpp-v2-transition-server/main.cpp b/test-server/cpp-v2-transition-server/main.cpp index 1fcedc3c..1e6935af 100644 --- a/test-server/cpp-v2-transition-server/main.cpp +++ b/test-server/cpp-v2-transition-server/main.cpp @@ -168,7 +168,8 @@ void fill_context(Aws::Map &map, MHD_Result handle_get_object(struct MHD_Connection *connection, const std::string &bucket, const std::string &key, const std::string &client_id, - const std::string &metadata) { + const std::string &metadata, + const std::string &range) { auto it = client_cache.find(client_id); if (it == client_cache.end()) { return send_response(connection, 404, "{\"error\":\"Client not found\"}"); @@ -178,6 +179,7 @@ MHD_Result handle_get_object(struct MHD_Connection *connection, Aws::S3::Model::GetObjectRequest request; request.SetBucket(bucket); request.SetKey(key); + request.SetRange(range); // S3EncryptionGetObjectOutcome outcome ; // if (metadata.empty()) { @@ -280,8 +282,9 @@ MHD_Result request_handler(void *cls, struct MHD_Connection *connection, std::string client_id = get_header_value(connection, "clientid"); std::string metadata = get_header_value(connection, "content-metadata"); + std::string range = get_header_value(range, "range") if (method_str == "GET") { - return handle_get_object(connection, bucket, key, client_id, metadata); + return handle_get_object(connection, bucket, key, client_id, metadata, range); } else if (method_str == "PUT") { std::unique_ptr body(static_cast(*con_cls)); *upload_data_size = 0; diff --git a/test-server/cpp-v3-server/main.cpp b/test-server/cpp-v3-server/main.cpp index 1f74974c..e4b3ad0a 100644 --- a/test-server/cpp-v3-server/main.cpp +++ b/test-server/cpp-v3-server/main.cpp @@ -174,7 +174,8 @@ void fill_context(Aws::Map &map, MHD_Result handle_get_object(struct MHD_Connection *connection, const std::string &bucket, const std::string &key, const std::string &client_id, - const std::string &metadata) { + const std::string &metadata, + const std::string &range) { auto it = client_cache.find(client_id); if (it == client_cache.end()) { return send_response(connection, 404, "{\"error\":\"Client not found\"}"); @@ -184,6 +185,7 @@ MHD_Result handle_get_object(struct MHD_Connection *connection, Aws::S3::Model::GetObjectRequest request; request.SetBucket(bucket); request.SetKey(key); + request.SetRange(range); // S3EncryptionGetObjectOutcome outcome ; // if (metadata.empty()) { @@ -290,8 +292,9 @@ MHD_Result request_handler(void *cls, struct MHD_Connection *connection, std::string client_id = get_header_value(connection, "clientid"); std::string metadata = get_header_value(connection, "content-metadata"); + std::string range = get_header_value(range, "range") if (method_str == "GET") { - return handle_get_object(connection, bucket, key, client_id, metadata); + return handle_get_object(connection, bucket, key, client_id, metadata, range); } else if (method_str == "PUT") { std::unique_ptr body(static_cast(*con_cls)); *upload_data_size = 0; 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 095aa044..78705cab 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 @@ -126,20 +126,20 @@ public class TestUtils { // Ranged Get Supported Versions public static final Set RANGED_GET_CURRENT_VERSIONS = Set.of( - JAVA_V3_CURRENT - // CPP_V2_CURRENT + JAVA_V3_CURRENT, + CPP_V2_CURRENT ); public static final Set RANGED_GET_TRANSITION_VERSIONS = Set.of( - JAVA_V3_TRANSITION - // CPP_V2_TRANSITION + JAVA_V3_TRANSITION, + CPP_V2_TRANSITION ); public static final Set RANGED_GET_IMPROVED_VERSIONS = Set.of( - JAVA_V4 - // CPP_V3 + JAVA_V4, + CPP_V3 ); public static final Set CURRENT_VERSIONS = From ba2414e526f3fadfbdc57632b994e175a99d45df Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Fri, 14 Nov 2025 13:33:09 -0800 Subject: [PATCH 33/37] update cpp --- test-server/cpp-v2-transition-server/main.cpp | 7 +++++-- test-server/cpp-v3-server/main.cpp | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/test-server/cpp-v2-transition-server/main.cpp b/test-server/cpp-v2-transition-server/main.cpp index 1e6935af..c3dcece9 100644 --- a/test-server/cpp-v2-transition-server/main.cpp +++ b/test-server/cpp-v2-transition-server/main.cpp @@ -93,6 +93,7 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, CryptoConfigurationV2 config(materials); if (legacy1 || legacy2) config.SetSecurityProfile(SecurityProfile::V2_AND_LEGACY); + config.SetUnAuthenticatedRangeGet(RangeGetMode::ALL); if (inst_put) config.SetStorageMethod(StorageMethod::INSTRUCTION_FILE); @@ -179,7 +180,9 @@ MHD_Result handle_get_object(struct MHD_Connection *connection, Aws::S3::Model::GetObjectRequest request; request.SetBucket(bucket); request.SetKey(key); - request.SetRange(range); + if (!range.empty()) { + request.SetRange(range); + } // S3EncryptionGetObjectOutcome outcome ; // if (metadata.empty()) { @@ -282,7 +285,7 @@ MHD_Result request_handler(void *cls, struct MHD_Connection *connection, std::string client_id = get_header_value(connection, "clientid"); std::string metadata = get_header_value(connection, "content-metadata"); - std::string range = get_header_value(range, "range") + std::string range = get_header_value(connection, "range"); if (method_str == "GET") { return handle_get_object(connection, bucket, key, client_id, metadata, range); } else if (method_str == "PUT") { diff --git a/test-server/cpp-v3-server/main.cpp b/test-server/cpp-v3-server/main.cpp index e4b3ad0a..5ca04e85 100644 --- a/test-server/cpp-v3-server/main.cpp +++ b/test-server/cpp-v3-server/main.cpp @@ -83,6 +83,7 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, CryptoConfigurationV3 config(materials); if (legacy1 || legacy2) config.AllowLegacy(); + config.SetUnAuthenticatedRangeGet(RangeGetMode::ALL); if (inst_put) config.SetStorageMethod(StorageMethod::INSTRUCTION_FILE); @@ -185,7 +186,9 @@ MHD_Result handle_get_object(struct MHD_Connection *connection, Aws::S3::Model::GetObjectRequest request; request.SetBucket(bucket); request.SetKey(key); - request.SetRange(range); + if (!range.empty()) { + request.SetRange(range); + } // S3EncryptionGetObjectOutcome outcome ; // if (metadata.empty()) { @@ -292,7 +295,7 @@ MHD_Result request_handler(void *cls, struct MHD_Connection *connection, std::string client_id = get_header_value(connection, "clientid"); std::string metadata = get_header_value(connection, "content-metadata"); - std::string range = get_header_value(range, "range") + std::string range = get_header_value(connection, "range"); if (method_str == "GET") { return handle_get_object(connection, bucket, key, client_id, metadata, range); } else if (method_str == "PUT") { From 630ff58511f2e5658fb5ed2a770196d6272be593 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:53:54 -0800 Subject: [PATCH 34/37] update tests --- .../amazon/encryption/s3/KC_GCMTests.java | 40 +++++++------------ 1 file changed, 14 insertions(+), 26 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 d4f140f1..cc5aed9a 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 @@ -14,34 +14,23 @@ import java.util.ArrayList; import java.util.List; -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,8 +48,7 @@ class KC_GCMTests { private static KeyMaterial kmsKeyArn = KeyMaterial.builder() .kmsKeyId(TestUtils.KMS_KEY_ARN) .build(); - private static final List crossLanguageObjectsMetaDataMode = new ArrayList<>(); - private static final List crossLanguageObjectsInstructionFiles = new ArrayList<>(); + private static final List crossLanguageObjects = new ArrayList<>(); private static KeyPair RSA_KEY_PAIR_1; @BeforeAll @@ -83,7 +71,7 @@ void improved_configured_with_require_encrypt_allow_decrypt_should_encrypt_kc_gc .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(2) @@ -110,7 +98,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_ .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseInsFileMode + language.getLanguageName()), crossLanguageObjectsInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseInsFileMode + language.getLanguageName()), crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(2) @@ -126,7 +114,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_ .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(2) @@ -142,7 +130,7 @@ void improved_configured_with_the_default_should_encrypt_kc_gcm(TestUtils.Langua .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(10) @@ -159,7 +147,7 @@ void transition_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.Lang .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(11) @@ -176,7 +164,7 @@ void transition_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_g .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(12) @@ -194,7 +182,7 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_gcm .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(13) @@ -211,7 +199,7 @@ void improved_configured_with_require_encrypt_allow_decrypt_should_decrypt_kc_gc .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(14) @@ -228,7 +216,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_ .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(15) @@ -245,7 +233,7 @@ void improved_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.Langua .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(16) @@ -272,7 +260,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_ .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } // Ranged Get Tests - using existing KC-GCM encrypted objects with ranged-get-supported clients From 576792894aa0b2f1aa2f73b87be6ebd04179a55d Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Fri, 14 Nov 2025 15:19:54 -0800 Subject: [PATCH 35/37] format --- .../src/it/java/software/amazon/encryption/s3/KC_GCMTests.java | 2 -- .../src/it/java/software/amazon/encryption/s3/TestUtils.java | 1 + 2 files changed, 1 insertion(+), 2 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 cc5aed9a..bc6dc9b5 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 @@ -30,8 +30,6 @@ import software.amazon.encryption.s3.model.KeyMaterial; import software.amazon.encryption.s3.model.S3ECConfig; -import software.amazon.encryption.s3.TestUtils.*; - /** * Exhaustive tests for S3 Encryption Client round-trip operations. * These tests cover various combinations of client versions, commitment policies, and encryption modes. 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 53ae5afa..78705cab 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,6 +6,7 @@ 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 180081b4b49772fa4766d60d48f3a852aab0c391 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Fri, 14 Nov 2025 16:13:19 -0800 Subject: [PATCH 36/37] Revert "cpp range get" Revert "Reapply "cpp ranged get"" This reverts commit c159f9fc80e13b7128735276d34ed4ab388c48fe. Revert "update cpp" This reverts commit ba2414e526f3fadfbdc57632b994e175a99d45df. --- test-server/cpp-v2-transition-server/main.cpp | 10 ++-------- test-server/cpp-v3-server/main.cpp | 10 ++-------- .../software/amazon/encryption/s3/TestUtils.java | 12 ++++++------ 3 files changed, 10 insertions(+), 22 deletions(-) diff --git a/test-server/cpp-v2-transition-server/main.cpp b/test-server/cpp-v2-transition-server/main.cpp index c3dcece9..1fcedc3c 100644 --- a/test-server/cpp-v2-transition-server/main.cpp +++ b/test-server/cpp-v2-transition-server/main.cpp @@ -93,7 +93,6 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, CryptoConfigurationV2 config(materials); if (legacy1 || legacy2) config.SetSecurityProfile(SecurityProfile::V2_AND_LEGACY); - config.SetUnAuthenticatedRangeGet(RangeGetMode::ALL); if (inst_put) config.SetStorageMethod(StorageMethod::INSTRUCTION_FILE); @@ -169,8 +168,7 @@ void fill_context(Aws::Map &map, MHD_Result handle_get_object(struct MHD_Connection *connection, const std::string &bucket, const std::string &key, const std::string &client_id, - const std::string &metadata, - const std::string &range) { + const std::string &metadata) { auto it = client_cache.find(client_id); if (it == client_cache.end()) { return send_response(connection, 404, "{\"error\":\"Client not found\"}"); @@ -180,9 +178,6 @@ MHD_Result handle_get_object(struct MHD_Connection *connection, Aws::S3::Model::GetObjectRequest request; request.SetBucket(bucket); request.SetKey(key); - if (!range.empty()) { - request.SetRange(range); - } // S3EncryptionGetObjectOutcome outcome ; // if (metadata.empty()) { @@ -285,9 +280,8 @@ MHD_Result request_handler(void *cls, struct MHD_Connection *connection, std::string client_id = get_header_value(connection, "clientid"); std::string metadata = get_header_value(connection, "content-metadata"); - std::string range = get_header_value(connection, "range"); if (method_str == "GET") { - return handle_get_object(connection, bucket, key, client_id, metadata, range); + return handle_get_object(connection, bucket, key, client_id, metadata); } else if (method_str == "PUT") { std::unique_ptr body(static_cast(*con_cls)); *upload_data_size = 0; diff --git a/test-server/cpp-v3-server/main.cpp b/test-server/cpp-v3-server/main.cpp index 5ca04e85..1f74974c 100644 --- a/test-server/cpp-v3-server/main.cpp +++ b/test-server/cpp-v3-server/main.cpp @@ -83,7 +83,6 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, CryptoConfigurationV3 config(materials); if (legacy1 || legacy2) config.AllowLegacy(); - config.SetUnAuthenticatedRangeGet(RangeGetMode::ALL); if (inst_put) config.SetStorageMethod(StorageMethod::INSTRUCTION_FILE); @@ -175,8 +174,7 @@ void fill_context(Aws::Map &map, MHD_Result handle_get_object(struct MHD_Connection *connection, const std::string &bucket, const std::string &key, const std::string &client_id, - const std::string &metadata, - const std::string &range) { + const std::string &metadata) { auto it = client_cache.find(client_id); if (it == client_cache.end()) { return send_response(connection, 404, "{\"error\":\"Client not found\"}"); @@ -186,9 +184,6 @@ MHD_Result handle_get_object(struct MHD_Connection *connection, Aws::S3::Model::GetObjectRequest request; request.SetBucket(bucket); request.SetKey(key); - if (!range.empty()) { - request.SetRange(range); - } // S3EncryptionGetObjectOutcome outcome ; // if (metadata.empty()) { @@ -295,9 +290,8 @@ MHD_Result request_handler(void *cls, struct MHD_Connection *connection, std::string client_id = get_header_value(connection, "clientid"); std::string metadata = get_header_value(connection, "content-metadata"); - std::string range = get_header_value(connection, "range"); if (method_str == "GET") { - return handle_get_object(connection, bucket, key, client_id, metadata, range); + return handle_get_object(connection, bucket, key, client_id, metadata); } else if (method_str == "PUT") { std::unique_ptr body(static_cast(*con_cls)); *upload_data_size = 0; 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 78705cab..095aa044 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 @@ -126,20 +126,20 @@ public class TestUtils { // Ranged Get Supported Versions public static final Set RANGED_GET_CURRENT_VERSIONS = Set.of( - JAVA_V3_CURRENT, - CPP_V2_CURRENT + JAVA_V3_CURRENT + // CPP_V2_CURRENT ); public static final Set RANGED_GET_TRANSITION_VERSIONS = Set.of( - JAVA_V3_TRANSITION, - CPP_V2_TRANSITION + JAVA_V3_TRANSITION + // CPP_V2_TRANSITION ); public static final Set RANGED_GET_IMPROVED_VERSIONS = Set.of( - JAVA_V4, - CPP_V3 + JAVA_V4 + // CPP_V3 ); public static final Set CURRENT_VERSIONS = From 434520cf8fe0893ba9ce18b3fa357bf41d5064b0 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Sun, 16 Nov 2025 19:19:46 -0800 Subject: [PATCH 37/37] Rename --- .../amazon/encryption/s3/KC_GCMTests.java | 104 +++++++++--------- 1 file changed, 52 insertions(+), 52 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 bc6dc9b5..acdbf045 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 @@ -1,12 +1,11 @@ /* -* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -* SPDX-License-Identifier: Apache-2.0 -*/ + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ package software.amazon.encryption.s3; import static software.amazon.encryption.s3.TestUtils.*; -import static software.amazon.encryption.s3.TestUtils.appendTestSuffix; import java.nio.ByteBuffer; import java.security.KeyPair; @@ -31,22 +30,23 @@ import software.amazon.encryption.s3.model.S3ECConfig; /** -* Exhaustive tests for S3 Encryption Client round-trip operations. -* These tests cover various combinations of client versions, commitment policies, and encryption modes. -* -* Tests are based on the exhaustive test matrix defined at: -* https://tiny.amazon.com/3xnzwczl/loopcloumicrpeyJ3 -* -*/ + * Exhaustive tests for S3 Encryption Client round-trip operations. + * These tests cover various combinations of client versions, commitment policies, and encryption modes. + * + * Tests are based on the exhaustive test matrix defined at: + * https://tiny.amazon.com/3xnzwczl/loopcloumicrpeyJ3 + * + */ @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class KC_GCMTests { 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 final List crossLanguageObjects = new ArrayList<>(); + .kmsKeyId(TestUtils.KMS_KEY_ARN) + .build(); + private static final List crossLanguageObjectsMetaDataMode = new ArrayList<>(); + private static final List crossLanguageObjectsRawRsaInstructionFiles = new ArrayList<>(); private static KeyPair RSA_KEY_PAIR_1; @BeforeAll @@ -55,7 +55,7 @@ static void setupKeys() throws Exception { keyPairGen.initialize(2048); RSA_KEY_PAIR_1 = keyPairGen.generateKeyPair(); } - + @Order(1) @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptAllowDecrypt should encrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") @@ -68,12 +68,12 @@ void improved_configured_with_require_encrypt_allow_decrypt_should_encrypt_kc_gc .build()) .build()); String S3ECId = clientOutput.getClientId(); - - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + 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") + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt with InstructionFilePutObject 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())) { @@ -96,7 +96,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_ .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseInsFileMode + language.getLanguageName()), crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseInsFileMode + language.getLanguageName()), crossLanguageObjectsRawRsaInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(2) @@ -111,8 +111,8 @@ void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_ .build()) .build()); String S3ECId = clientOutput.getClientId(); - - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + 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) @@ -127,15 +127,15 @@ void improved_configured_with_the_default_should_encrypt_kc_gcm(TestUtils.Langua .build()) .build()); String S3ECId = clientOutput.getClientId(); - - TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + 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) @ParameterizedTest(name = "{0}: Transition configured with the default should decrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#transitionClientsForTest") void transition_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.LanguageServerTarget language) { - + S3ECTestServerClient client = TestUtils.testServerClientFor(language); CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() .config(S3ECConfig.builder() @@ -144,15 +144,15 @@ void transition_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.Lang .build()) .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) @ParameterizedTest(name = "{0}: Transition configured with ForbidEncryptAllowDecrypt should decrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#transitionClientsForTest") void transition_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_gcm(TestUtils.LanguageServerTarget language) { - + S3ECTestServerClient client = TestUtils.testServerClientFor(language); CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() .config(S3ECConfig.builder() @@ -161,15 +161,15 @@ void transition_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_g .build()) .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) @ParameterizedTest(name = "{0}: Improved configured with ForbidEncryptAllowDecrypt should decrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") void improved_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_gcm(TestUtils.LanguageServerTarget language) { - + S3ECTestServerClient client = TestUtils.testServerClientFor(language); CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() .config(S3ECConfig.builder() @@ -179,15 +179,15 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_gcm .build()) .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) @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptAllowDecrypt should decrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") void improved_configured_with_require_encrypt_allow_decrypt_should_decrypt_kc_gcm(TestUtils.LanguageServerTarget language) { - + S3ECTestServerClient client = TestUtils.testServerClientFor(language); CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() .config(S3ECConfig.builder() @@ -196,15 +196,15 @@ void improved_configured_with_require_encrypt_allow_decrypt_should_decrypt_kc_gc .build()) .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) @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should decrypt KC-GCM") @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_gcm(TestUtils.LanguageServerTarget language) { - + S3ECTestServerClient client = TestUtils.testServerClientFor(language); CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder() .config(S3ECConfig.builder() @@ -213,8 +213,8 @@ void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_ .build()) .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) @@ -230,12 +230,12 @@ void improved_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.Langua .build()) .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") + @ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt decrypt InstructionFilePutObject 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())) { @@ -258,7 +258,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, crossLanguageObjectsRawRsaInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } // Ranged Get Tests - using existing KC-GCM encrypted objects with ranged-get-supported clients @@ -277,7 +277,7 @@ void transition_configured_with_the_default_can_ranged_get_kc_gcm(TestUtils.Lang .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(21) @@ -295,7 +295,7 @@ void transition_configured_with_forbid_encrypt_allow_decrypt_can_ranged_get_kc_g .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(22) @@ -313,7 +313,7 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_can_ranged_get_kc_gcm .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(23) @@ -330,7 +330,7 @@ void improved_configured_with_require_encrypt_allow_decrypt_can_ranged_get_kc_gc .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(24) @@ -347,7 +347,7 @@ void improved_configured_with_require_encrypt_require_decrypt_can_ranged_get_kc_ .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } @Order(25) @@ -364,7 +364,7 @@ void improved_configured_with_the_default_can_ranged_get_kc_gcm(TestUtils.Langua .build()); String S3ECId = clientOutput.getClientId(); - TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); + TestUtils.DecryptWithRangedGet(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY); } }