Skip to content

Commit 39b3dd1

Browse files
authored
chore(java): create key example for HV-2 branch key (#1425)
1 parent e751717 commit 39b3dd1

File tree

3 files changed

+187
-1
lines changed

3 files changed

+187
-1
lines changed

AwsCryptographicMaterialProviders/runtimes/java/src/examples/java/software/amazon/cryptography/example/hierarchy/CreateKeyExample.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public static String CreateKey(
5555
"ExampleContextValue"
5656
);
5757

58-
// 2. Create a new branch key and beacon key in our KeyStore.
58+
// 4. Create a new branch key and beacon key in our KeyStore.
5959
// Both the branch key and the beacon key will share an Id.
6060
// This creation is eventually consistent.
6161
final String actualBranchKeyId = _admin
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package software.amazon.cryptography.example.hierarchy;
4+
5+
import java.util.Collections;
6+
import java.util.Map;
7+
import javax.annotation.Nonnull;
8+
import javax.annotation.Nullable;
9+
import org.testng.annotations.Test;
10+
import software.amazon.awssdk.utils.StringUtils;
11+
import software.amazon.cryptography.keystore.model.AwsKms;
12+
import software.amazon.cryptography.keystore.model.HierarchyVersion;
13+
import software.amazon.cryptography.keystoreadmin.KeyStoreAdmin;
14+
import software.amazon.cryptography.keystoreadmin.model.CreateKeyInput;
15+
import software.amazon.cryptography.keystoreadmin.model.KeyManagementStrategy;
16+
import software.amazon.cryptography.keystoreadmin.model.KmsSymmetricKeyArn;
17+
18+
/*
19+
The Hierarchical Keyring Example relies on the existence of a
20+
key store with pre-existing branch key material or beacon key material.
21+
22+
This example demonstrates configuring a Key Store Admin and then
23+
to create Hierarchy Version 2 (HV2) branch key and beacon key materials
24+
that share the same Id, then return that Id.
25+
26+
For HV2 branch keys:
27+
- The branch key materials are created with 'hierarchy-version-2'
28+
- Kms Simple Strategy is required to create branch keys with 'hierarchy-version-2'
29+
30+
We will always create a new beacon key alongside a new branch key,
31+
even if you are not using searchable encryption.
32+
33+
This key creation should occur within your control plane.
34+
*/
35+
36+
public class CreateKeyHv2Example {
37+
38+
@Test
39+
public static String CreateKey(
40+
@Nonnull String kmsKeyArn,
41+
@Nonnull HierarchyVersion hierarchyVersion,
42+
@Nullable String branchKeyId,
43+
@Nullable KeyStoreAdmin admin
44+
) {
45+
// 1. Configure your Key Store Admin resource.
46+
final KeyStoreAdmin _admin = admin == null ? AdminProvider.admin() : admin;
47+
48+
// 2. Configure Key Management Strategy.
49+
// Only KMS Simple is supported at this time for HV-2 to Create Keys
50+
final KeyManagementStrategy strategy = KeyManagementStrategy
51+
.builder()
52+
.AwsKmsSimple(AwsKms.builder().build())
53+
.build();
54+
55+
// 3. If you need to specify the Identifier for a Branch Key, you may.
56+
// This is an optional argument.
57+
// If an Identifier is not provided, a v4 UUID will be generated and used.
58+
// This example provides a combination of a fixed string and a v4 UUID;
59+
// this makes it easy for Crypto Tools to clean up these Example Branch Keys.
60+
branchKeyId =
61+
StringUtils.isBlank(branchKeyId)
62+
? "mpl-java-example-hv2-" + java.util.UUID.randomUUID().toString()
63+
: branchKeyId;
64+
65+
// 4. Create a custom encryption context for the Branch Key.
66+
// Most encrypted data should have an associated encryption context
67+
// to protect integrity. This sample uses placeholder values.
68+
// Note that the custom encryption context for a Branch Key is
69+
// prefixed by the library with `aws-crypto-ec:`.
70+
// For more information see:
71+
// blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management
72+
final Map<String, String> encryptionContext = Collections.singletonMap(
73+
"ExampleContextKey",
74+
"ExampleContextValue"
75+
);
76+
77+
// 5. Create a new branch key and beacon key in our KeyStore.
78+
// Both the branch key and the beacon key will share an Id.
79+
// This creation is eventually consistent.
80+
final String actualBranchKeyId = _admin
81+
.CreateKey(
82+
CreateKeyInput
83+
.builder()
84+
// This is the KMS ARN that will be used to protect the Branch Key.
85+
// It is a required argument.
86+
.KmsArn(KmsSymmetricKeyArn.builder().KmsKeyArn(kmsKeyArn).build())
87+
// If you need to specify the Identifier for a Branch Key, you may.
88+
// This is an optional argument.
89+
.Identifier(branchKeyId)
90+
// If a branch key Identifier is provided,
91+
// custom encryption context MUST be provided as well.
92+
.EncryptionContext(encryptionContext)
93+
// Only KMS Simple is supported at this time for HV-2 to Create Keys
94+
// This is an optional argument which defaults to
95+
// AwsKmsDecryptEncrypt Strategy if no input is provided
96+
.Strategy(strategy)
97+
// If a Hierarchy Version is set to `v2`
98+
// Branch Key is created with `hierarchy-version-2`.
99+
// This is an optional argument, if no Hierarchy Version is provided,
100+
// Hierarchy Version defaults to v1.
101+
.HierarchyVersion(hierarchyVersion)
102+
.build()
103+
)
104+
.Identifier();
105+
106+
assert actualBranchKeyId.equals(branchKeyId);
107+
return branchKeyId;
108+
}
109+
110+
public static void main(final String[] args) {
111+
if (args.length <= 3) {
112+
throw new IllegalArgumentException(
113+
"To run this example, include the keyStoreTableName, logicalKeyStoreName, and kmsKeyArn in args"
114+
);
115+
}
116+
final String keyStoreTableName = args[0];
117+
final String logicalKeyStoreName = args[1];
118+
final String kmsKeyArn = args[2];
119+
final KeyStoreAdmin admin = AdminProvider.admin(
120+
keyStoreTableName,
121+
logicalKeyStoreName,
122+
null
123+
);
124+
CreateKey(kmsKeyArn, HierarchyVersion.v2, null, admin);
125+
}
126+
}

AwsCryptographicMaterialProviders/runtimes/java/src/testExamples/java/software/amazon/cryptography/example/hierarchy/ExampleTests.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,69 @@
1414
import software.amazon.cryptography.example.hierarchy.mutations.MutationsProvider;
1515
import software.amazon.cryptography.keystore.KeyStore;
1616
import software.amazon.cryptography.keystore.model.AwsKms;
17+
import software.amazon.cryptography.keystore.model.GetActiveBranchKeyInput;
18+
import software.amazon.cryptography.keystore.model.GetActiveBranchKeyOutput;
19+
import software.amazon.cryptography.keystore.model.GetBeaconKeyInput;
20+
import software.amazon.cryptography.keystore.model.GetBeaconKeyOutput;
21+
import software.amazon.cryptography.keystore.model.GetBranchKeyVersionInput;
22+
import software.amazon.cryptography.keystore.model.GetBranchKeyVersionOutput;
23+
import software.amazon.cryptography.keystore.model.HierarchyVersion;
1724

1825
public class ExampleTests {
1926

27+
@Test
28+
public void CreateKeyHv2Test() {
29+
// Create Branch Key with `hierarchy-version-2` (HV-2)
30+
final String branchKeyId = CreateKeyHv2Example.CreateKey(
31+
Fixtures.KEYSTORE_KMS_ARN,
32+
HierarchyVersion.v2,
33+
null,
34+
AdminProvider.admin()
35+
);
36+
37+
System.out.println("Create Branch Key for HV-2: " + branchKeyId);
38+
39+
final KeyStore keyStore = KeyStoreProvider.keyStore(
40+
Fixtures.KEYSTORE_KMS_ARN
41+
);
42+
43+
// Get Branch Key Items
44+
GetActiveBranchKeyOutput activeOutput = keyStore.GetActiveBranchKey(
45+
GetActiveBranchKeyInput.builder().branchKeyIdentifier(branchKeyId).build()
46+
);
47+
GetBranchKeyVersionOutput decryptOnlyOutput = keyStore.GetBranchKeyVersion(
48+
GetBranchKeyVersionInput
49+
.builder()
50+
.branchKeyIdentifier(branchKeyId)
51+
.branchKeyVersion(activeOutput.branchKeyMaterials().branchKeyVersion())
52+
.build()
53+
);
54+
GetBeaconKeyOutput beaconOutput = keyStore.GetBeaconKey(
55+
GetBeaconKeyInput.builder().branchKeyIdentifier(branchKeyId).build()
56+
);
57+
58+
assert branchKeyId.equals(
59+
activeOutput.branchKeyMaterials().branchKeyIdentifier()
60+
);
61+
assert branchKeyId.equals(
62+
decryptOnlyOutput.branchKeyMaterials().branchKeyIdentifier()
63+
);
64+
assert activeOutput
65+
.branchKeyMaterials()
66+
.branchKeyVersion()
67+
.equals(decryptOnlyOutput.branchKeyMaterials().branchKeyVersion());
68+
assert branchKeyId.equals(
69+
beaconOutput.beaconKeyMaterials().beaconKeyIdentifier()
70+
);
71+
72+
DdbHelper.DeleteBranchKey(
73+
branchKeyId,
74+
Fixtures.TEST_KEYSTORE_NAME,
75+
HierarchyVersion.v2.toString(),
76+
null
77+
);
78+
}
79+
2080
@Test
2181
public void End2EndReEncryptTest() {
2282
String branchKeyId = CreateKeyExample.CreateKey(

0 commit comments

Comments
 (0)