Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,3 @@
path = all-examples/net/v4/s3ec-v4-local
url = https://github.com/aws/private-amazon-s3-encryption-client-dotnet-staging.git
branch = s3ec-v4-WIP
[submodule "all-examples/net/v3/s3ec-v3-local"]
path = all-examples/net/v3/s3ec-v3-local
url = https://github.com/aws/private-amazon-s3-encryption-client-dotnet-staging.git
branch = rishav/key-commitment
1 change: 0 additions & 1 deletion all-examples/net/v3/s3ec-v3-local
Submodule s3ec-v3-local deleted from ca1149
1 change: 1 addition & 0 deletions all-examples/net/v3/s3ec-v3-local
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,29 @@

package software.amazon.encryption.s3;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static software.amazon.encryption.s3.TestUtils.*;

import java.lang.annotation.ElementType;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import com.amazonaws.services.s3.model.KMSEncryptionMaterials;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.opentest4j.TestAbortedException;
import software.amazon.encryption.s3.client.S3ECTestServerClient;
import software.amazon.encryption.s3.model.CommitmentPolicy;
import software.amazon.encryption.s3.model.CreateClientInput;
import software.amazon.encryption.s3.model.CreateClientOutput;
import software.amazon.encryption.s3.model.EncryptionAlgorithm;
import software.amazon.encryption.s3.model.GetObjectInput;
import software.amazon.encryption.s3.model.GetObjectOutput;
import software.amazon.encryption.s3.model.InstructionFileConfig;
import software.amazon.encryption.s3.model.KeyMaterial;
import software.amazon.encryption.s3.model.PutObjectInput;
import software.amazon.encryption.s3.model.S3ECConfig;
import software.amazon.encryption.s3.model.S3EncryptionClientError;

import com.amazonaws.services.s3.AmazonS3Encryption;
import com.amazonaws.services.s3.AmazonS3EncryptionClient;
import com.amazonaws.services.s3.model.CryptoConfiguration;
import com.amazonaws.services.s3.model.CryptoMode;
import com.amazonaws.services.s3.model.CryptoStorageMode;
import software.amazon.encryption.s3.TestUtils.*;
import com.amazonaws.services.s3.model.EncryptionMaterialsProvider;
import com.amazonaws.services.s3.model.KMSEncryptionMaterialsProvider;

/**
* Exhaustive tests for S3 Encryption Client round-trip operations.
Expand All @@ -59,11 +40,21 @@

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class KC_GCMTests {
private static String sharedObjectKeyBase = "test-kc-gcm-kms";
private static final String sharedObjectKeyBaseMetaDataMode = "test-kc-gcm-kms";
private static final String sharedObjectKeyBaseInsFileMode = "test-kc-gcm-kms-instruction-file";
private static KeyMaterial kmsKeyArn = KeyMaterial.builder()
.kmsKeyId(TestUtils.KMS_KEY_ARN)
.build();
private static List<String> crossLanguageObjects = new ArrayList<>();
private static final List<String> crossLanguageObjectsMetaDataMode = new ArrayList<>();
private static final List<String> crossLanguageObjectsInstructionFiles = new ArrayList<>();
private static KeyPair RSA_KEY_PAIR_1;

@BeforeAll
static void setupKeys() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048);
RSA_KEY_PAIR_1 = keyPairGen.generateKeyPair();
}

@Order(1)
@ParameterizedTest(name = "{0}: Improved configured with RequireEncryptAllowDecrypt should encrypt KC-GCM")
Expand All @@ -78,7 +69,34 @@ void improved_configured_with_require_encrypt_allow_decrypt_should_encrypt_kc_gc
.build());
String S3ECId = clientOutput.getClientId();

TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBase + language.getLanguageName()), crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
}

@Order(2)
@ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should encrypt KC-GCM")
@MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest")
void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_gcm_ins_file(TestUtils.LanguageServerTarget language) {
if (!RAW_SUPPORTED.contains(language.getLanguageName())) {
throw new TestAbortedException("Not encrypting raw keyring with: " + language.getLanguageName());
}

KeyMaterial rsaKey = KeyMaterial.builder()
.rsaKey(ByteBuffer.wrap(RSA_KEY_PAIR_1.getPrivate().getEncoded()))
.build();

S3ECTestServerClient client = TestUtils.testServerClientFor(language);
CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder()
.config(S3ECConfig.builder()
.instructionFileConfig(InstructionFileConfig.builder()
.enableInstructionFilePutObject(true)
.build())
.encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)
.commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)
.keyMaterial(rsaKey).build())
.build());
String S3ECId = clientOutput.getClientId();

TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseInsFileMode + language.getLanguageName()), crossLanguageObjectsInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
}

@Order(2)
Expand All @@ -94,7 +112,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_encrypt_kc_
.build());
String S3ECId = clientOutput.getClientId();

TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBase + language.getLanguageName()), crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
}

@Order(2)
Expand All @@ -110,7 +128,7 @@ void improved_configured_with_the_default_should_encrypt_kc_gcm(TestUtils.Langua
.build());
String S3ECId = clientOutput.getClientId();

TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBase + language.getLanguageName()), crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
TestUtils.Encrypt(client, S3ECId, appendTestSuffix(sharedObjectKeyBaseMetaDataMode + language.getLanguageName()), crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
}

@Order(10)
Expand All @@ -127,7 +145,7 @@ void transition_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.Lang
.build());
String S3ECId = clientOutput.getClientId();

TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
}

@Order(11)
Expand All @@ -144,7 +162,7 @@ void transition_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_g
.build());
String S3ECId = clientOutput.getClientId();

TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
}

@Order(12)
Expand All @@ -162,7 +180,7 @@ void improved_configured_with_forbid_encrypt_allow_decrypt_should_decrypt_kc_gcm
.build());
String S3ECId = clientOutput.getClientId();

TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
}

@Order(13)
Expand All @@ -179,7 +197,7 @@ void improved_configured_with_require_encrypt_allow_decrypt_should_decrypt_kc_gc
.build());
String S3ECId = clientOutput.getClientId();

TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
}

@Order(14)
Expand All @@ -196,7 +214,7 @@ void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_
.build());
String S3ECId = clientOutput.getClientId();

TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
}

@Order(15)
Expand All @@ -213,7 +231,34 @@ void improved_configured_with_the_default_should_decrypt_kc_gcm(TestUtils.Langua
.build());
String S3ECId = clientOutput.getClientId();

TestUtils.Decrypt(client, S3ECId, crossLanguageObjects, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsMetaDataMode, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
}

@Order(16)
@ParameterizedTest(name = "{0}: Improved configured with RequireEncryptRequireDecrypt should encrypt KC-GCM")
@MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest")
void improved_configured_with_require_encrypt_require_decrypt_should_decrypt_kc_gcm_ins_file(final TestUtils.LanguageServerTarget language) {
if (!RAW_SUPPORTED.contains(language.getLanguageName())) {
throw new TestAbortedException("Not encrypting raw keyring with: " + language.getLanguageName());
}

KeyMaterial rsaKey = KeyMaterial.builder()
.rsaKey(ByteBuffer.wrap(RSA_KEY_PAIR_1.getPrivate().getEncoded()))
.build();

S3ECTestServerClient client = TestUtils.testServerClientFor(language);
CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder()
.config(S3ECConfig.builder()
.instructionFileConfig(InstructionFileConfig.builder()
.enableInstructionFilePutObject(true)
.build())
.encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)
.commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)
.keyMaterial(rsaKey).build())
.build());
String S3ECId = clientOutput.getClientId();

TestUtils.Decrypt(client, S3ECId, crossLanguageObjectsInstructionFiles, EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import software.amazon.awssdk.core.ResponseBytes;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.encryption.s3.TestUtils.LanguageServerTarget;
import software.amazon.encryption.s3.client.S3ECTestServerClient;
import software.amazon.encryption.s3.model.CommitmentPolicy;
import software.amazon.encryption.s3.model.CreateClientInput;
Expand Down Expand Up @@ -595,15 +596,84 @@ public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageSe
if (!encLang.getLanguageName().startsWith("Ruby") && !encLang.getLanguageName().startsWith("PHP")) {
// Ruby and PHP do not include it :(
assertTrue(ptInstFile.response().metadata().containsKey("x-amz-crypto-instr-file"));
assertFalse(ptInstFile.asUtf8String().isEmpty());
// Read should be enabled by default
GetObjectOutput output = decClient.getObject(GetObjectInput.builder()
.clientID(decS3ECId)
.bucket(BUCKET)
.key(objectKey)
.build());
}
assertFalse(ptInstFile.asUtf8String().isEmpty());
// Read should be enabled by default
GetObjectOutput output = decClient.getObject(GetObjectInput.builder()
.clientID(decS3ECId)
.bucket(BUCKET)
.key(objectKey)
.build());

assertEquals(input, new String(output.getBody().array()));
}

@ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {1}")
@MethodSource("software.amazon.encryption.s3.TestUtils#crossLanguageClients")
public void instructionFileWriteAndReadWithRSA(LanguageServerTarget encLang, LanguageServerTarget decLang) throws Exception {
// Early validation
if (!RAW_SUPPORTED.contains(encLang.getLanguageName())) {
throw new TestAbortedException("not encrypting raw keyring with: " + encLang.getLanguageName());
}
if (!RAW_SUPPORTED.contains(decLang.getLanguageName())) {
throw new TestAbortedException("not decrypting raw keyring with: " + decLang.getLanguageName());
}

KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048);
KeyMaterial rsaKeyMaterial = KeyMaterial.builder()
.rsaKey(ByteBuffer.wrap(keyPairGen.generateKeyPair().getPrivate().getEncoded()))
.build();

S3ECConfig config = S3ECConfig.builder()
.instructionFileConfig(InstructionFileConfig.builder()
.enableInstructionFilePutObject(true)
.build())
.encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF)
.commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)
.keyMaterial(rsaKeyMaterial)
.build();

// Create clients
S3ECTestServerClient encClient = testServerClientFor(encLang);
S3ECTestServerClient decClient = testServerClientFor(decLang);

String encS3ECId = encClient.createClient(CreateClientInput.builder().config(config).build()).getClientId();
String decS3ECId = decClient.createClient(CreateClientInput.builder().config(config).build()).getClientId();

final String objectKey = appendTestSuffix(String.format("rsa-insfile-write-%s-read-%s",
encLang.getLanguageName(), decLang.getLanguageName()));
final String input = "simple-test-input-rsa";

assertEquals(input, new String(output.getBody().array()));
// Encrypt
encClient.putObject(PutObjectInput.builder()
.clientID(encS3ECId)
.bucket(BUCKET)
.key(objectKey)
.body(ByteBuffer.wrap(input.getBytes(StandardCharsets.UTF_8)))
.build());

// Assert using Java plaintext client that an instruction file exists
ResponseBytes<GetObjectResponse> ptInstFile;
try (S3Client ptS3Client = S3Client.create()) {
ptInstFile = ptS3Client.getObjectAsBytes(builder -> builder
.bucket(BUCKET)
.key(objectKey + ".instruction")
.build());
}
// Check for inst file key
if (!encLang.getLanguageName().startsWith("Ruby") && !encLang.getLanguageName().startsWith("PHP")) {
// Ruby and PHP do not include it :(
assertTrue(ptInstFile.response().metadata().containsKey("x-amz-crypto-instr-file"));
}
assertFalse(ptInstFile.asUtf8String().isEmpty());
// Read should be enabled by default
GetObjectOutput output = decClient.getObject(GetObjectInput.builder()
.clientID(decS3ECId)
.bucket(BUCKET)
.key(objectKey)
.build());

assertEquals(input, new String(output.getBody().array()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
package software.amazon.encryption.s3;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.net.Socket;
import java.net.URI;
Expand Down
Loading
Loading