Skip to content

chore(java): demo hv-2 does not send prefixed EC in examples #1529

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: hv-2/hv-2
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public class Fixtures {
// HierarchicalGitHubKMSKeyID
public static final String KEYSTORE_KMS_ARN =
"arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126";
public static final String KMS_KEY_FOR_HV2_ONLY =
"arn:aws:kms:us-west-2:370957321024:key/ab11cc09-38d8-416a-a80f-a51454bd950b";
public static final String MRK_ARN_EAST =
"arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7";
public static final String MRK_ARN_WEST =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
package software.amazon.cryptography.example.hierarchy;

import java.util.Collections;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
Expand Down Expand Up @@ -103,7 +105,18 @@ public static void createHappyCaseId(
@Nonnull HierarchyVersion hierarchyVersion,
@Nonnull Integer versionCount
) {
CreateKeyExample.CreateKey(kmsKeyArn, branchKeyId, admin, hierarchyVersion);
final Map<String, String> encryptionContext = Collections.singletonMap(
"Robbie",
"Is a Dog."
);

CreateKeyExample.CreateKey(
kmsKeyArn,
branchKeyId,
admin,
hierarchyVersion,
encryptionContext
);
for (int i = 0; i < versionCount; i++) {
VersionKeyExample.VersionKey(kmsKeyArn, branchKeyId, admin);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import software.amazon.awssdk.services.kms.model.KmsException;
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.cryptography.example.Fixtures;
import software.amazon.cryptography.keystore.model.AwsKms;
import software.amazon.cryptography.keystore.model.HierarchyVersion;
import software.amazon.cryptography.keystoreadmin.KeyStoreAdmin;
Expand All @@ -32,7 +34,8 @@ public static String CreateKey(
@Nonnull String kmsKeyArn,
@Nullable String branchKeyId,
@Nullable KeyStoreAdmin admin,
@Nullable HierarchyVersion hierarchyVersion
@Nullable HierarchyVersion hierarchyVersion,
@Nullable Map<String, String> encryptionContext
) {
// 1. Configure your Key Store Admin resource.
final KeyStoreAdmin _admin = admin == null ? AdminProvider.admin() : admin;
Expand All @@ -57,19 +60,7 @@ public static String CreateKey(
? "mpl-java-example-" + java.util.UUID.randomUUID().toString()
: branchKeyId;

// 4. Create a custom encryption context for the Branch Key.
// Most encrypted data should have an associated encryption context
// to protect integrity. This sample uses placeholder values.
// Note that the custom encryption context for a Branch Key is
// prefixed by the library with `aws-crypto-ec:`.
// For more information see:
// blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management
final Map<String, String> encryptionContext = Collections.singletonMap(
"ExampleContextKey",
"ExampleContextValue"
);

// 5. Create a new branch key and beacon key in our KeyStore.
// 4. Create a new branch key and beacon key in our KeyStore.
// Both the branch key and the beacon key will share an Id.
// This creation is eventually consistent.
final String actualBranchKeyId = _admin
Expand All @@ -84,6 +75,12 @@ public static String CreateKey(
.Identifier(branchKeyId)
// If a branch key Identifier is provided,
// custom encryption context MUST be provided as well.
// Most encrypted data should have an associated encryption context
// to protect integrity. This sample uses placeholder values.
// Note that the custom encryption context for a Branch Key is
// prefixed by the library with `aws-crypto-ec:` when using hierarchical keyring v1 only.
// For more information see:
// blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management
.EncryptionContext(encryptionContext)
// The Branch Key Store Admin can create HV-1 or HV-2 Branch Keys
.HierarchyVersion(_hierarchyVersion)
Expand All @@ -92,8 +89,8 @@ public static String CreateKey(
.build()
)
.Identifier();

assert actualBranchKeyId.equals(branchKeyId);

return branchKeyId;
}

Expand All @@ -111,6 +108,10 @@ public static void main(final String[] args) {
logicalKeyStoreName,
null
);
CreateKey(kmsKeyArn, null, admin, HierarchyVersion.v1);
final Map<String, String> encryptionContext = Collections.singletonMap(
"Robbie",
"Is a Dog."
);
CreateKey(kmsKeyArn, null, admin, HierarchyVersion.v1, encryptionContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import static software.amazon.cryptography.example.hierarchy.mutations.MutationsProvider.executeInitialize;

import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Nullable;
import software.amazon.cryptography.example.hierarchy.AdminProvider;
Expand Down Expand Up @@ -129,12 +131,17 @@ public static void CompleteExample(
? AdminProvider.reEncryptStrategy(null)
: strategy;
final KeyStoreAdmin _admin = admin == null ? AdminProvider.admin() : admin;
final Map<String, String> encryptionContext = Collections.singletonMap(
"Robbie",
"Is a Dog."
);

CreateKeyExample.CreateKey(
kmsKeyArnOriginal,
branchKeyId,
_admin,
HierarchyVersion.v1
HierarchyVersion.v1,
encryptionContext
);

MutationToken fromInit = InitMutation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public static Mutations defaultMutation(
@Nullable final HierarchyVersion terminalHierarchyVersion
) {
HashMap<String, String> terminalEC = new HashMap<>(2, 1);
terminalEC.put("Robbie", "is a dog.");
terminalEC.put("Robbie", "Is a Dog.");
return Mutations
.builder()
.TerminalEncryptionContext(terminalEC)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
// SPDX-License-Identifier: Apache-2.0
package software.amazon.cryptography.example.hierarchy;

import java.util.Collections;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.testng.Assert;
import org.testng.annotations.Test;
import software.amazon.awssdk.services.dynamodb.model.GetItemResponse;
import software.amazon.awssdk.services.kms.model.KmsException;
import software.amazon.cryptography.example.Constants;
import software.amazon.cryptography.example.DdbHelper;
import software.amazon.cryptography.example.Fixtures;
Expand Down Expand Up @@ -34,15 +37,46 @@ public class ExampleTests {
public void createKeyHv2Test() {
String branchKeyId =
hv2CreateTestPrefix + java.util.UUID.randomUUID().toString();
final Map<String, String> encryptionContext = Collections.singletonMap(
"Robbie",
"Is a Dog."
);
// Create Branch Key with `hierarchy-version-2` (HV-2)
final String actualBranchKeyId = CreateKeyExample.CreateKey(
Fixtures.KEYSTORE_KMS_ARN,
Fixtures.KMS_KEY_FOR_HV2_ONLY,
branchKeyId,
AdminProvider.admin(),
HierarchyVersion.v2
);
HierarchyVersion.v2,
encryptionContext
);
// HV2 sends the encryption context without any transformation.
// We have a kms key `Fixtures.KMS_KEY_FOR_HV2_ONLY`, that requires EC to be exactly {"Robbie": "Is a Dog."} in its key policy.
// We will create a key with a different EC then the one that is expected and see it fail.
final Map<String, String> encryptionContextFailingCase =
Collections.singletonMap("I", "am not a Dog.");
boolean exceptionThrown = false;
try {
CreateKeyExample.CreateKey(
Fixtures.KMS_KEY_FOR_HV2_ONLY,
branchKeyId,
AdminProvider.admin(),
HierarchyVersion.v2,
encryptionContextFailingCase
);
} catch (KmsException e) {
// String matchings are not great but I need "not authorized to perform" KmsException and not any other.
if (
e
.getMessage()
.contains("is not authorized to perform: kms:GenerateDataKey on")
) {
exceptionThrown = true;
}
}
assert exceptionThrown;
// This is the KeyStore from which Get operations will be performed for assertion
final KeyStore keyStore = KeyStoreProvider.keyStore(
Fixtures.KEYSTORE_KMS_ARN
Fixtures.KMS_KEY_FOR_HV2_ONLY
);
// Get Branch Key Items
GetActiveBranchKeyOutput activeOutput = keyStore.GetActiveBranchKey(
Expand Down Expand Up @@ -82,9 +116,19 @@ public void createKeyHv2Test() {
@Test
public void end2EndKmsSimpleTest() {
// Run the test with v1 -> v2 mutation
end2EndKmsSimpleTestHelper(HierarchyVersion.v1, HierarchyVersion.v2, true);
end2EndKmsSimpleTestHelper(
HierarchyVersion.v1,
Fixtures.KMS_KEY_FOR_HV2_ONLY,
HierarchyVersion.v2,
true
);
// Run the test for v2 mutation
end2EndKmsSimpleTestHelper(HierarchyVersion.v2, null, true);
end2EndKmsSimpleTestHelper(
HierarchyVersion.v2,
Fixtures.KMS_KEY_FOR_HV2_ONLY,
null,
true
);
}

@Test
Expand All @@ -96,15 +140,26 @@ public void end2EndKmsReEncryptTest() {
@Test
public void end2EndDecryptEncryptTest() {
// Run the test for v1 item mutation
end2EndDecryptEncryptTestHelper(HierarchyVersion.v1, null, false);
end2EndDecryptEncryptTestHelper(
HierarchyVersion.v1,
Fixtures.KMS_KEY_FOR_HV2_ONLY,
null,
false
);
// Run the test with v1 -> v2 mutation
end2EndDecryptEncryptTestHelper(
HierarchyVersion.v1,
Fixtures.KMS_KEY_FOR_HV2_ONLY,
HierarchyVersion.v2,
true
);
// Run the test for v2 mutation
end2EndDecryptEncryptTestHelper(HierarchyVersion.v2, null, true);
end2EndDecryptEncryptTestHelper(
HierarchyVersion.v2,
Fixtures.KMS_KEY_FOR_HV2_ONLY,
null,
true
);
}

/**
Expand All @@ -116,20 +171,26 @@ public void end2EndDecryptEncryptTest() {
*/
private void end2EndKmsSimpleTestHelper(
final HierarchyVersion initialHVersion,
final String terminalKmsKeyArn,
@Nullable final HierarchyVersion terminalHVersion,
@Nullable final Boolean doNotVersion
) {
final Map<String, String> encryptionContext = Collections.singletonMap(
"Robbie",
"Is a Dog."
);
String branchKeyId = CreateKeyExample.CreateKey(
Fixtures.KEYSTORE_KMS_ARN,
null,
AdminProvider.admin(),
initialHVersion
initialHVersion,
encryptionContext
);
System.out.println("\nCreated Branch Key: " + branchKeyId);
branchKeyId =
MutationKmsSimpleExample.End2End(
branchKeyId,
Fixtures.POSTAL_HORN_KEY_ARN,
terminalKmsKeyArn,
terminalHVersion,
MutationsProvider.KmsSystemKey(),
AdminProvider.admin()
Expand All @@ -138,7 +199,7 @@ private void end2EndKmsSimpleTestHelper(
"\nMutated Branch Key: " +
branchKeyId +
" to KMS ARN: " +
Fixtures.POSTAL_HORN_KEY_ARN +
terminalKmsKeyArn +
"\n"
);
GetItemResponse mCommitmentRes = DdbHelper.getKeyStoreDdbItem(
Expand All @@ -161,9 +222,7 @@ private void end2EndKmsSimpleTestHelper(
mIndexRes.hasItem(),
Constants.TYPE_MUTATION_INDEX + " was not deleted!"
);
KeyStore postalHornKS = KeyStoreProvider.keyStore(
Fixtures.POSTAL_HORN_KEY_ARN
);
KeyStore postalHornKS = KeyStoreProvider.keyStore(terminalKmsKeyArn);
ValidateKeyStoreItem.ValidateBranchKey(branchKeyId, postalHornKS);
KeyManagementStrategy kmsSimpleStrategy = AdminProvider.kmsSimpleStrategy(
Fixtures.kmsClientWest2
Expand Down Expand Up @@ -223,11 +282,16 @@ private void end2EndKmsSimpleTestHelper(
private void end2EndKmsReEncryptTestHelper(
@Nullable final HierarchyVersion initialHVersion
) {
final Map<String, String> encryptionContext = Collections.singletonMap(
"Robbie",
"Is a Dog."
);
String branchKeyId = CreateKeyExample.CreateKey(
Fixtures.KEYSTORE_KMS_ARN,
null,
AdminProvider.admin(),
initialHVersion
initialHVersion,
encryptionContext
);
System.out.println("\nCreated Branch Key: " + branchKeyId);
branchKeyId =
Expand Down Expand Up @@ -334,14 +398,20 @@ private void end2EndKmsReEncryptTestHelper(
*/
private void end2EndDecryptEncryptTestHelper(
@Nonnull final HierarchyVersion initialHVersion,
@Nonnull String terminalKmsArn,
@Nullable final HierarchyVersion terminalHVersion,
@Nullable final boolean doNotVersion
) {
final Map<String, String> encryptionContext = Collections.singletonMap(
"Robbie",
"Is a Dog."
);
String branchKeyId = CreateKeyExample.CreateKey(
Fixtures.KEYSTORE_KMS_ARN,
null,
AdminProvider.admin(),
initialHVersion
initialHVersion,
encryptionContext
);
System.out.println("\nCreated Branch Key: " + branchKeyId);
branchKeyId =
Expand Down
Loading
Loading