From 1e6a8deaeec6a9ff69bbf2e2c1eee376e5fc46a7 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Mon, 9 Sep 2024 12:39:24 -0700 Subject: [PATCH 01/11] chore(examples): Shared cache across Hierarchical Keyrings --- ...acheAcrossHierarchicalKeyringsExample.java | 252 ++++++++++++++++++ ...AcrossHierarchicalKeyringsExampleTest.java | 19 ++ .../encryptionsdk/AllTestsSuite.java | 2 + .../encryptionsdk/kms/KMSTestFixtures.java | 1 + 4 files changed, 274 insertions(+) create mode 100644 src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java create mode 100644 src/test/java/com/amazonaws/crypto/examples/keyrings/SharedCacheAcrossHierarchicalKeyringsExampleTest.java diff --git a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java new file mode 100644 index 00000000..98ea8fe8 --- /dev/null +++ b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java @@ -0,0 +1,252 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.crypto.examples.keyrings.hierarchical; + +import com.amazonaws.encryptionsdk.AwsCrypto; +import com.amazonaws.encryptionsdk.CryptoResult; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.cryptography.keystore.KeyStore; +import software.amazon.cryptography.keystore.model.CreateKeyInput; +import software.amazon.cryptography.keystore.model.KMSConfiguration; +import software.amazon.cryptography.keystore.model.KeyStoreConfig; +import software.amazon.cryptography.materialproviders.CryptographicMaterialsCache; +import software.amazon.cryptography.materialproviders.ICryptographicMaterialsCache; +import software.amazon.cryptography.materialproviders.IKeyring; +import software.amazon.cryptography.materialproviders.MaterialProviders; +import software.amazon.cryptography.materialproviders.model.CacheType; +import software.amazon.cryptography.materialproviders.model.CreateAwsKmsHierarchicalKeyringInput; +import software.amazon.cryptography.materialproviders.model.DefaultCache; +import software.amazon.cryptography.materialproviders.model.MaterialProvidersConfig; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * This example demonstrates how to use a shared cache across multiple Hierarchical Keyrings. + * With this functionality, users only need to maintain one common shared cache across multiple + * Hierarchical Keyrings with different Key Stores instances/KMS Clients/KMS Keys. + * + *

There are two important parameters that users need to carefully set while providing the shared cache: + * + *

Partition ID - Partition ID is an optional parameter provided to the Hierarchical Keyring input, + * which distinguishes Cryptographic Material Providers (i.e: Keyrings) writing to a cache. + * - If the Partition ID is set and is the same for two Hierarchical Keyrings (or another Material Provider), + * they CAN share the same cache entries in the cache. + * - If the Partition ID is set and is different for two Hierarchical Keyrings (or another Material Provider), + * they CANNOT share the same cache entries in the cache. + * - If the Partition ID is not set by the user, it is initialized as a random 16-byte UUID which makes + * it unique for every Hierarchical Keyring, and two Hierarchical Keyrings (or another Material Provider) + * CANNOT share the same cache entries in the cache. + * + *

Logical Key Store Name - This parameter is set by the user when configuring the Key Store for + * the Hierarchical Keyring. This is a logical name for the branch key store. + * Suppose you have a physical Key Store (K). You create two instances of K (K1 and K2). Now, you create + * two Hierarchical Keyrings (HK1 and HK2) with these Key Store instances (K1 and K2 respectively). + * - If you want to share cache entries across these two keyrings, you should set the Logical Key Store Names + * for both the Key Store instances (K1 and K2) to be the same. + * - If you set the Logical Key Store Names for K1 and K2 to be different, HK1 (which uses Key Store instance K1) + * and HK2 (which uses Key Store instance K2) will NOT be able to share cache entries. + * + * This is demonstrated in the example below. + * Notice that both K1 and K2 are instances of the same physical Key Store (K). + * You MUST NEVER have two different physical Key Stores with the same Logical Key Store Name. + * + * Important Note: If you have two or more Hierarchy Keyrings with: + * - Same Partition ID + * - Same Logical Key Store Name of the Key Store for the Hierarchical Keyring + * - Same Branch Key ID + * then they WILL share the cache entries in the Shared Cache. + * Please make sure that you set all of Partition ID, Logical Key Store Name and Branch Key ID + * to be the same for two Hierarchical Keyrings only if you want them to share cache entries. + * + *

This example first creates a shared cache that you can use across multiple Hierarchical Keyrings. + * The example then configures a Hierarchical Keyring (HK1 and HK2) with the shared cache, + * a Branch Key ID and two instances (K1 and K2) of the same physical Key Store (K) respectively, + * i.e. HK1 with K1 and HK2 with K2. The example demonstrates that if you set the same Partition ID + * for HK1 and HK2, the two keyrings can share cache entries. + * If you set different Partition ID of the Hierarchical Keyrings, or different + * Logical Key Store Names of the Key Store instances, then the keyrings will NOT + * be able to share cache entries. + * + *

This example requires access to the DDB Table (K) where you are storing the Branch Keys. This + * table must be configured with the following primary key configuration: - Partition key is named + * "partition_key" with type (S) - Sort key is named "sort_key" with type (S) + * + *

This example also requires using a KMS Key. You need the following access on this key: - + * GenerateDataKeyWithoutPlaintext - Decrypt + */ +public class SharedCacheAcrossHierarchicalKeyringsExample { + private static final byte[] EXAMPLE_DATA = "Hello World".getBytes(StandardCharsets.UTF_8); + + public static void encryptAndDecryptWithKeyring( + String keyStoreTableName, String logicalKeyStoreName, String partitionId, String kmsKeyId) { + // Create the CryptographicMaterialsCache (CMC) to share across multiple Hierarchical Keyrings + // using the Material Providers Library + // This CMC takes in: + // - CacheType + final MaterialProviders matProv = + MaterialProviders.builder() + .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) + .build(); + + final CacheType cache = + CacheType.builder() + .Default(DefaultCache.builder().entryCapacity(100).build()) + .build(); + + final CreateCryptographicMaterialsCacheInput cryptographicMaterialsCacheInput = + CreateCryptographicMaterialsCacheInput.builder() + .cache(cache) + .build(); + + final ICryptographicMaterialsCache sharedCryptographicMaterialsCache = + matProv.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput); + + // Create a CacheType object for the sharedCryptographicMaterialsCache + // Note that the `cache` parameter in the Hierarchical Keyring Input takes a `CacheType` as input + final CacheType sharedCache = + CacheType.builder() + // This is the `Shared` CacheType that passes an already initialized shared cache + .Shared(sharedCryptographicMaterialsCache) + .build(); + + // Instantiate the SDK + // This builds the AwsCrypto client with the RequireEncryptRequireDecrypt commitment policy, + // which enforces that this client only encrypts using committing algorithm suites and enforces + // that this client will only decrypt encrypted messages that were created with a committing + // algorithm suite. + // This is the default commitment policy if you build the client with + // `AwsCrypto.builder().build()` + // or `AwsCrypto.standard()`. + final AwsCrypto crypto = AwsCrypto.builder().build(); + + // Configure your KeyStore resource keystore1. + // This SHOULD be the same configuration that you used + // to initially create and populate your physical KeyStore. + // Note that ddbTableName keyStoreTableName is the physical Key Store, + // and keystore1 is instances of this physical Key Store. + final KeyStore keystore1 = + KeyStore.builder() + .KeyStoreConfig( + KeyStoreConfig.builder() + .ddbClient(DynamoDbClient.create()) + .ddbTableName(keyStoreTableName) + .logicalKeyStoreName(logicalKeyStoreName) + .kmsClient(KmsClient.create()) + .kmsConfiguration(KMSConfiguration.builder().kmsKeyArn(kmsKeyId).build()) + .build()) + .build(); + + // Call CreateKey to create a new active branch key + final String branchKeyId = + keystore1.CreateKey(CreateKeyInput.builder().build()).branchKeyIdentifier(); + + // Create the Hierarchical Keyring HK1 with Key Store instance K1, partitionId, + // the shared Cache and the BranchKeyId. + // Note that we are now providing an already initialized shared cache instead of just mentioning + // the cache type and the Hierarchical Keyring initializing a cache at initialization. + final CreateAwsKmsHierarchicalKeyringInput keyringInput1 = + CreateAwsKmsHierarchicalKeyringInput.builder() + .keyStore(keystore1) + .branchKeyId(branchKeyId) + .ttlSeconds(600) + .cache(sharedCache) + .partitionId(partitionId) + .build(); + final IKeyring hierarchicalKeyring1 = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput1); + + // Create example encryption context + Map encryptionContext = new HashMap<>(); + encryptionContext.put("encryption", "context"); + encryptionContext.put("is not", "secret"); + encryptionContext.put("but adds", "useful metadata"); + encryptionContext.put("that can help you", "be confident that"); + encryptionContext.put("the data you are handling", "is what you think it is"); + + // Encrypt the data for encryptionContext using hierarchicalKeyring1 + final CryptoResult encryptResult1 = + crypto.encryptData(hierarchicalKeyring1, EXAMPLE_DATA, encryptionContext); + + // Decrypt your encrypted data using the same keyring HK1 you used on encrypt. + final CryptoResult decryptResult1 = + crypto.decryptData(hierarchicalKeyring1, encryptResult1.getResult()); + assert Arrays.equals(decryptResult1.getResult(), EXAMPLE_DATA); + + // Through the above encrypt and decrypt roundtrip, the cache will be populated and + // the cache entries can be used by another Hierarchical Keyring with the + // - Same Partition ID + // - Same Logical Key Store Name of the Key Store for the Hierarchical Keyring + // - Same Branch Key ID + + // Configure your KeyStore resource keystore2. + // This SHOULD be the same configuration that you used + // to initially create and populate your physical KeyStore. + // Note that ddbTableName keyStoreTableName is the physical Key Store, + // and keystore2 is instances of this physical Key Store. + + // Note that for this example, keystore2 is identical to keystore1. + // You can optionally change configurations like KMS Client or KMS Key ID based + // on your use-case. + // Make sure you have the required permissions to use different configurations. + + // - If you want to share cache entries across two keyrings HK1 and HK2, + // you should set the Logical Key Store Names for both + // Key Store instances (K1 and K2) to be the same. + // - If you set the Logical Key Store Names for K1 and K2 to be different, + // HK1 (which uses Key Store instance K1) and HK2 (which uses Key Store + // instance K2) will NOT be able to share cache entries. + final KeyStore keystore2 = + KeyStore.builder() + .KeyStoreConfig( + KeyStoreConfig.builder() + .ddbClient(DynamoDbClient.create()) + .ddbTableName(keyStoreTableName) + .logicalKeyStoreName(logicalKeyStoreName) + .kmsClient(KmsClient.create()) + .kmsConfiguration(KMSConfiguration.builder().kmsKeyArn(kmsKeyId).build()) + .build()) + .build(); + + // Create the Hierarchical Keyring HK2 with Key Store instance K2, the shared Cache + // and the same partitionId and BranchKeyId used in HK1 because we want to share cache entries + // (and experience cache HITS). + final CreateAwsKmsHierarchicalKeyringInput keyringInput2 = + CreateAwsKmsHierarchicalKeyringInput.builder() + .keyStore(keystore2) + .branchKeyId(branchKeyId) + .ttlSeconds(600) + .cache(sharedCache) + .partitionId(partitionId) + .build(); + final IKeyring hierarchicalKeyring2 = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput2); + + // Encrypt the data for encryptionContext using hierarchicalKeyring2 + final CryptoResult encryptResult2 = + crypto.encryptData(hierarchicalKeyring2, EXAMPLE_DATA, encryptionContext); + + // Decrypt your encrypted data using the same keyring HK2 you used on encrypt. + final CryptoResult decryptResult2 = + crypto.decryptData(hierarchicalKeyring2, encryptResult2.getResult()); + assert Arrays.equals(decryptResult2.getResult(), EXAMPLE_DATA); + } + + public static void main(final String[] args) { + if (args.length <= 0) { + throw new IllegalArgumentException( + "To run this example, include the keyStoreTableName, logicalKeyStoreName, partitionId, and kmsKeyId in args"); + } + final String keyStoreTableName = args[0]; + final String logicalKeyStoreName = args[1]; + final String partitionId = args[2]; + final String kmsKeyId = args[3]; + encryptAndDecryptWithKeyring(keyStoreTableName, logicalKeyStoreName, partitionId, kmsKeyId); + } +} diff --git a/src/test/java/com/amazonaws/crypto/examples/keyrings/SharedCacheAcrossHierarchicalKeyringsExampleTest.java b/src/test/java/com/amazonaws/crypto/examples/keyrings/SharedCacheAcrossHierarchicalKeyringsExampleTest.java new file mode 100644 index 00000000..9cf21e67 --- /dev/null +++ b/src/test/java/com/amazonaws/crypto/examples/keyrings/SharedCacheAcrossHierarchicalKeyringsExampleTest.java @@ -0,0 +1,19 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazonaws.crypto.examples.keyrings; + +import com.amazonaws.crypto.examples.keyrings.hierarchical.SharedCacheAcrossHierarchicalKeyringsExample; +import com.amazonaws.encryptionsdk.kms.KMSTestFixtures; +import org.junit.Test; + +public class SharedCacheAcrossHierarchicalKeyringsExampleTest { + @Test + public void testEncryptAndDecrypt() { + SharedCacheAcrossHierarchicalKeyringsExample.encryptAndDecryptWithKeyring( + KMSTestFixtures.TEST_KEYSTORE_NAME, + KMSTestFixtures.TEST_LOGICAL_KEYSTORE_NAME, + KMSTestFixtures.HIERARCHY_KEYRING_PARTITION_ID, + KMSTestFixtures.TEST_KEYSTORE_KMS_KEY_ID); + } +} diff --git a/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java b/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java index 6f337f6c..47c46c24 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java +++ b/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java @@ -4,6 +4,7 @@ package com.amazonaws.encryptionsdk; import com.amazonaws.crypto.examples.keyrings.AwsKmsHierarchicalKeyringExampleTest; +import com.amazonaws.crypto.examples.keyrings.SharedCacheAcrossHierarchicalKeyringsExampleTest; import com.amazonaws.crypto.examples.keyrings.AwsKmsRsaKeyringExampleTest; import com.amazonaws.crypto.examples.keyrings.BasicEncryptionKeyringExampleTest; import com.amazonaws.crypto.examples.keyrings.DiscoveryDecryptionKeyringExampleTest; @@ -120,6 +121,7 @@ AwsKmsRsaKeyringExampleTest.class, DiscoveryDecryptionKeyringExampleTest.class, AwsKmsHierarchicalKeyringExampleTest.class, + SharedCacheAcrossHierarchicalKeyringsExampleTest.class, SetCommitmentPolicyExampleTest.class, SetEncryptionAlgorithmKeyringExampleTest.class, ParsedCiphertextTest.class, diff --git a/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java b/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java index 3ff1d5cf..e99232ec 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java +++ b/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java @@ -37,4 +37,5 @@ private KMSTestFixtures() { public static final String TEST_LOGICAL_KEYSTORE_NAME = "KeyStoreDdbTable"; public static final String TEST_KEYSTORE_KMS_KEY_ID = "arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126"; + public static final String HIERARCHY_KEYRING_PARTITION_ID = "partition_id"; } From a288023a33cf7f2a15b52b03993534f6b1235119 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Mon, 9 Sep 2024 12:58:14 -0700 Subject: [PATCH 02/11] fix --- ...acheAcrossHierarchicalKeyringsExample.java | 121 +++++++++--------- 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java index 98ea8fe8..25141038 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java @@ -110,13 +110,13 @@ public static void encryptAndDecryptWithKeyring( final ICryptographicMaterialsCache sharedCryptographicMaterialsCache = matProv.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput); - // Create a CacheType object for the sharedCryptographicMaterialsCache + // Create a CacheType object for the sharedCryptographicMaterialsCache // Note that the `cache` parameter in the Hierarchical Keyring Input takes a `CacheType` as input final CacheType sharedCache = - CacheType.builder() - // This is the `Shared` CacheType that passes an already initialized shared cache - .Shared(sharedCryptographicMaterialsCache) - .build(); + CacheType.builder() + // This is the `Shared` CacheType that passes an already initialized shared cache + .Shared(sharedCryptographicMaterialsCache) + .build(); // Instantiate the SDK // This builds the AwsCrypto client with the RequireEncryptRequireDecrypt commitment policy, @@ -133,7 +133,7 @@ public static void encryptAndDecryptWithKeyring( // to initially create and populate your physical KeyStore. // Note that ddbTableName keyStoreTableName is the physical Key Store, // and keystore1 is instances of this physical Key Store. - final KeyStore keystore1 = + final KeyStore keystore1 = KeyStore.builder() .KeyStoreConfig( KeyStoreConfig.builder() @@ -150,17 +150,17 @@ public static void encryptAndDecryptWithKeyring( keystore1.CreateKey(CreateKeyInput.builder().build()).branchKeyIdentifier(); // Create the Hierarchical Keyring HK1 with Key Store instance K1, partitionId, - // the shared Cache and the BranchKeyId. - // Note that we are now providing an already initialized shared cache instead of just mentioning - // the cache type and the Hierarchical Keyring initializing a cache at initialization. + // the shared Cache and the BranchKeyId. + // Note that we are now providing an already initialized shared cache instead of just mentioning + // the cache type and the Hierarchical Keyring initializing a cache at initialization. final CreateAwsKmsHierarchicalKeyringInput keyringInput1 = CreateAwsKmsHierarchicalKeyringInput.builder() - .keyStore(keystore1) - .branchKeyId(branchKeyId) - .ttlSeconds(600) - .cache(sharedCache) - .partitionId(partitionId) - .build(); + .keyStore(keystore1) + .branchKeyId(branchKeyId) + .ttlSeconds(600) + .cache(sharedCache) + .partitionId(partitionId) + .build(); final IKeyring hierarchicalKeyring1 = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput1); // Create example encryption context @@ -180,54 +180,55 @@ public static void encryptAndDecryptWithKeyring( crypto.decryptData(hierarchicalKeyring1, encryptResult1.getResult()); assert Arrays.equals(decryptResult1.getResult(), EXAMPLE_DATA); - // Through the above encrypt and decrypt roundtrip, the cache will be populated and - // the cache entries can be used by another Hierarchical Keyring with the - // - Same Partition ID - // - Same Logical Key Store Name of the Key Store for the Hierarchical Keyring - // - Same Branch Key ID - - // Configure your KeyStore resource keystore2. - // This SHOULD be the same configuration that you used - // to initially create and populate your physical KeyStore. - // Note that ddbTableName keyStoreTableName is the physical Key Store, - // and keystore2 is instances of this physical Key Store. - - // Note that for this example, keystore2 is identical to keystore1. - // You can optionally change configurations like KMS Client or KMS Key ID based - // on your use-case. - // Make sure you have the required permissions to use different configurations. - - // - If you want to share cache entries across two keyrings HK1 and HK2, - // you should set the Logical Key Store Names for both - // Key Store instances (K1 and K2) to be the same. - // - If you set the Logical Key Store Names for K1 and K2 to be different, - // HK1 (which uses Key Store instance K1) and HK2 (which uses Key Store - // instance K2) will NOT be able to share cache entries. - final KeyStore keystore2 = - KeyStore.builder() - .KeyStoreConfig( - KeyStoreConfig.builder() - .ddbClient(DynamoDbClient.create()) - .ddbTableName(keyStoreTableName) - .logicalKeyStoreName(logicalKeyStoreName) - .kmsClient(KmsClient.create()) - .kmsConfiguration(KMSConfiguration.builder().kmsKeyArn(kmsKeyId).build()) - .build()) - .build(); + // Through the above encrypt and decrypt roundtrip, the cache will be populated and + // the cache entries can be used by another Hierarchical Keyring with the + // - Same Partition ID + // - Same Logical Key Store Name of the Key Store for the Hierarchical Keyring + // - Same Branch Key ID + + // Configure your KeyStore resource keystore2. + // This SHOULD be the same configuration that you used + // to initially create and populate your physical KeyStore. + // Note that ddbTableName keyStoreTableName is the physical Key Store, + // and keystore2 is instances of this physical Key Store. + + // Note that for this example, keystore2 is identical to keystore1. + // You can optionally change configurations like KMS Client or KMS Key ID based + // on your use-case. + // Make sure you have the required permissions to use different configurations. + + // - If you want to share cache entries across two keyrings HK1 and HK2, + // you should set the Logical Key Store Names for both + // Key Store instances (K1 and K2) to be the same. + // - If you set the Logical Key Store Names for K1 and K2 to be different, + // HK1 (which uses Key Store instance K1) and HK2 (which uses Key Store + // instance K2) will NOT be able to share cache entries. + final KeyStore keystore2 = + KeyStore.builder() + .KeyStoreConfig( + KeyStoreConfig.builder() + .ddbClient(DynamoDbClient.create()) + .ddbTableName(keyStoreTableName) + .logicalKeyStoreName(logicalKeyStoreName) + .kmsClient(KmsClient.create()) + .kmsConfiguration(KMSConfiguration.builder().kmsKeyArn(kmsKeyId).build()) + .build()) + .build(); // Create the Hierarchical Keyring HK2 with Key Store instance K2, the shared Cache - // and the same partitionId and BranchKeyId used in HK1 because we want to share cache entries - // (and experience cache HITS). + // and the same partitionId and BranchKeyId used in HK1 because we want to share cache entries + // (and experience cache HITS). final CreateAwsKmsHierarchicalKeyringInput keyringInput2 = - CreateAwsKmsHierarchicalKeyringInput.builder() - .keyStore(keystore2) - .branchKeyId(branchKeyId) - .ttlSeconds(600) - .cache(sharedCache) - .partitionId(partitionId) - .build(); - final IKeyring hierarchicalKeyring2 = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput2); - + CreateAwsKmsHierarchicalKeyringInput.builder() + .keyStore(keystore2) + .branchKeyId(branchKeyId) + .ttlSeconds(600) + .cache(sharedCache) + .partitionId(partitionId) + .build(); + final IKeyring hierarchicalKeyring2 = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput2); + + // This encrypt-decrypt roundtrip with HK2 will experience Cache HITS from previous HK1 roundtrip // Encrypt the data for encryptionContext using hierarchicalKeyring2 final CryptoResult encryptResult2 = crypto.encryptData(hierarchicalKeyring2, EXAMPLE_DATA, encryptionContext); From 33775ffb5f4dac47b1a987d8c45d416747e219a0 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Mon, 30 Sep 2024 14:55:54 -0700 Subject: [PATCH 03/11] update --- ...acheAcrossHierarchicalKeyringsExample.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java index 25141038..59f4482d 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java @@ -65,7 +65,7 @@ * - Same Branch Key ID * then they WILL share the cache entries in the Shared Cache. * Please make sure that you set all of Partition ID, Logical Key Store Name and Branch Key ID - * to be the same for two Hierarchical Keyrings only if you want them to share cache entries. + * to be the same for two Hierarchical Keyrings if and only if you want them to share cache entries. * *

This example first creates a shared cache that you can use across multiple Hierarchical Keyrings. * The example then configures a Hierarchical Keyring (HK1 and HK2) with the shared cache, @@ -80,8 +80,9 @@ * table must be configured with the following primary key configuration: - Partition key is named * "partition_key" with type (S) - Sort key is named "sort_key" with type (S) * - *

This example also requires using a KMS Key. You need the following access on this key: - - * GenerateDataKeyWithoutPlaintext - Decrypt + *

This example also requires using a KMS Key. You need the following access on this key: + * - GenerateDataKeyWithoutPlaintext + * - Decrypt */ public class SharedCacheAcrossHierarchicalKeyringsExample { private static final byte[] EXAMPLE_DATA = "Hello World".getBytes(StandardCharsets.UTF_8); @@ -204,16 +205,16 @@ public static void encryptAndDecryptWithKeyring( // HK1 (which uses Key Store instance K1) and HK2 (which uses Key Store // instance K2) will NOT be able to share cache entries. final KeyStore keystore2 = - KeyStore.builder() - .KeyStoreConfig( - KeyStoreConfig.builder() - .ddbClient(DynamoDbClient.create()) - .ddbTableName(keyStoreTableName) - .logicalKeyStoreName(logicalKeyStoreName) - .kmsClient(KmsClient.create()) - .kmsConfiguration(KMSConfiguration.builder().kmsKeyArn(kmsKeyId).build()) - .build()) - .build(); + KeyStore.builder() + .KeyStoreConfig( + KeyStoreConfig.builder() + .ddbClient(DynamoDbClient.create()) + .ddbTableName(keyStoreTableName) + .logicalKeyStoreName(logicalKeyStoreName) + .kmsClient(KmsClient.create()) + .kmsConfiguration(KMSConfiguration.builder().kmsKeyArn(kmsKeyId).build()) + .build()) + .build(); // Create the Hierarchical Keyring HK2 with Key Store instance K2, the shared Cache // and the same partitionId and BranchKeyId used in HK1 because we want to share cache entries From 938996d6ff2bc5e8d923ff2f31259776400bfcfe Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Mon, 30 Sep 2024 15:06:37 -0700 Subject: [PATCH 04/11] m --- src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java b/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java index 47c46c24..881d3d32 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java +++ b/src/test/java/com/amazonaws/encryptionsdk/AllTestsSuite.java @@ -4,7 +4,6 @@ package com.amazonaws.encryptionsdk; import com.amazonaws.crypto.examples.keyrings.AwsKmsHierarchicalKeyringExampleTest; -import com.amazonaws.crypto.examples.keyrings.SharedCacheAcrossHierarchicalKeyringsExampleTest; import com.amazonaws.crypto.examples.keyrings.AwsKmsRsaKeyringExampleTest; import com.amazonaws.crypto.examples.keyrings.BasicEncryptionKeyringExampleTest; import com.amazonaws.crypto.examples.keyrings.DiscoveryDecryptionKeyringExampleTest; @@ -12,6 +11,7 @@ import com.amazonaws.crypto.examples.keyrings.RawAesKeyringExampleTest; import com.amazonaws.crypto.examples.keyrings.RawRsaKeyringExampleTest; import com.amazonaws.crypto.examples.keyrings.SetEncryptionAlgorithmKeyringExampleTest; +import com.amazonaws.crypto.examples.keyrings.SharedCacheAcrossHierarchicalKeyringsExampleTest; import com.amazonaws.crypto.examples.v2.BasicEncryptionExampleTest; import com.amazonaws.crypto.examples.v2.BasicMultiRegionKeyEncryptionExampleTest; import com.amazonaws.crypto.examples.v2.CustomCMMExampleTest; From 5e3e733f2cc6bc0f96d3a1ab6308a53f4d4d0544 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Mon, 30 Sep 2024 15:23:20 -0700 Subject: [PATCH 05/11] indent --- ...acheAcrossHierarchicalKeyringsExample.java | 332 +++++++++--------- 1 file changed, 166 insertions(+), 166 deletions(-) diff --git a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java index 59f4482d..863aba1c 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java @@ -85,170 +85,170 @@ * - Decrypt */ public class SharedCacheAcrossHierarchicalKeyringsExample { - private static final byte[] EXAMPLE_DATA = "Hello World".getBytes(StandardCharsets.UTF_8); - - public static void encryptAndDecryptWithKeyring( - String keyStoreTableName, String logicalKeyStoreName, String partitionId, String kmsKeyId) { - // Create the CryptographicMaterialsCache (CMC) to share across multiple Hierarchical Keyrings - // using the Material Providers Library - // This CMC takes in: - // - CacheType - final MaterialProviders matProv = - MaterialProviders.builder() - .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) - .build(); - - final CacheType cache = - CacheType.builder() - .Default(DefaultCache.builder().entryCapacity(100).build()) - .build(); - - final CreateCryptographicMaterialsCacheInput cryptographicMaterialsCacheInput = - CreateCryptographicMaterialsCacheInput.builder() - .cache(cache) - .build(); - - final ICryptographicMaterialsCache sharedCryptographicMaterialsCache = - matProv.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput); - - // Create a CacheType object for the sharedCryptographicMaterialsCache - // Note that the `cache` parameter in the Hierarchical Keyring Input takes a `CacheType` as input - final CacheType sharedCache = - CacheType.builder() - // This is the `Shared` CacheType that passes an already initialized shared cache - .Shared(sharedCryptographicMaterialsCache) - .build(); - - // Instantiate the SDK - // This builds the AwsCrypto client with the RequireEncryptRequireDecrypt commitment policy, - // which enforces that this client only encrypts using committing algorithm suites and enforces - // that this client will only decrypt encrypted messages that were created with a committing - // algorithm suite. - // This is the default commitment policy if you build the client with - // `AwsCrypto.builder().build()` - // or `AwsCrypto.standard()`. - final AwsCrypto crypto = AwsCrypto.builder().build(); - - // Configure your KeyStore resource keystore1. - // This SHOULD be the same configuration that you used - // to initially create and populate your physical KeyStore. - // Note that ddbTableName keyStoreTableName is the physical Key Store, - // and keystore1 is instances of this physical Key Store. - final KeyStore keystore1 = - KeyStore.builder() - .KeyStoreConfig( - KeyStoreConfig.builder() - .ddbClient(DynamoDbClient.create()) - .ddbTableName(keyStoreTableName) - .logicalKeyStoreName(logicalKeyStoreName) - .kmsClient(KmsClient.create()) - .kmsConfiguration(KMSConfiguration.builder().kmsKeyArn(kmsKeyId).build()) - .build()) - .build(); - - // Call CreateKey to create a new active branch key - final String branchKeyId = - keystore1.CreateKey(CreateKeyInput.builder().build()).branchKeyIdentifier(); - - // Create the Hierarchical Keyring HK1 with Key Store instance K1, partitionId, - // the shared Cache and the BranchKeyId. - // Note that we are now providing an already initialized shared cache instead of just mentioning - // the cache type and the Hierarchical Keyring initializing a cache at initialization. - final CreateAwsKmsHierarchicalKeyringInput keyringInput1 = - CreateAwsKmsHierarchicalKeyringInput.builder() - .keyStore(keystore1) - .branchKeyId(branchKeyId) - .ttlSeconds(600) - .cache(sharedCache) - .partitionId(partitionId) - .build(); - final IKeyring hierarchicalKeyring1 = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput1); - - // Create example encryption context - Map encryptionContext = new HashMap<>(); - encryptionContext.put("encryption", "context"); - encryptionContext.put("is not", "secret"); - encryptionContext.put("but adds", "useful metadata"); - encryptionContext.put("that can help you", "be confident that"); - encryptionContext.put("the data you are handling", "is what you think it is"); - - // Encrypt the data for encryptionContext using hierarchicalKeyring1 - final CryptoResult encryptResult1 = - crypto.encryptData(hierarchicalKeyring1, EXAMPLE_DATA, encryptionContext); - - // Decrypt your encrypted data using the same keyring HK1 you used on encrypt. - final CryptoResult decryptResult1 = - crypto.decryptData(hierarchicalKeyring1, encryptResult1.getResult()); - assert Arrays.equals(decryptResult1.getResult(), EXAMPLE_DATA); - - // Through the above encrypt and decrypt roundtrip, the cache will be populated and - // the cache entries can be used by another Hierarchical Keyring with the - // - Same Partition ID - // - Same Logical Key Store Name of the Key Store for the Hierarchical Keyring - // - Same Branch Key ID - - // Configure your KeyStore resource keystore2. - // This SHOULD be the same configuration that you used - // to initially create and populate your physical KeyStore. - // Note that ddbTableName keyStoreTableName is the physical Key Store, - // and keystore2 is instances of this physical Key Store. - - // Note that for this example, keystore2 is identical to keystore1. - // You can optionally change configurations like KMS Client or KMS Key ID based - // on your use-case. - // Make sure you have the required permissions to use different configurations. - - // - If you want to share cache entries across two keyrings HK1 and HK2, - // you should set the Logical Key Store Names for both - // Key Store instances (K1 and K2) to be the same. - // - If you set the Logical Key Store Names for K1 and K2 to be different, - // HK1 (which uses Key Store instance K1) and HK2 (which uses Key Store - // instance K2) will NOT be able to share cache entries. - final KeyStore keystore2 = - KeyStore.builder() - .KeyStoreConfig( - KeyStoreConfig.builder() - .ddbClient(DynamoDbClient.create()) - .ddbTableName(keyStoreTableName) - .logicalKeyStoreName(logicalKeyStoreName) - .kmsClient(KmsClient.create()) - .kmsConfiguration(KMSConfiguration.builder().kmsKeyArn(kmsKeyId).build()) - .build()) - .build(); - - // Create the Hierarchical Keyring HK2 with Key Store instance K2, the shared Cache - // and the same partitionId and BranchKeyId used in HK1 because we want to share cache entries - // (and experience cache HITS). - final CreateAwsKmsHierarchicalKeyringInput keyringInput2 = - CreateAwsKmsHierarchicalKeyringInput.builder() - .keyStore(keystore2) - .branchKeyId(branchKeyId) - .ttlSeconds(600) - .cache(sharedCache) - .partitionId(partitionId) - .build(); - final IKeyring hierarchicalKeyring2 = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput2); - - // This encrypt-decrypt roundtrip with HK2 will experience Cache HITS from previous HK1 roundtrip - // Encrypt the data for encryptionContext using hierarchicalKeyring2 - final CryptoResult encryptResult2 = - crypto.encryptData(hierarchicalKeyring2, EXAMPLE_DATA, encryptionContext); - - // Decrypt your encrypted data using the same keyring HK2 you used on encrypt. - final CryptoResult decryptResult2 = - crypto.decryptData(hierarchicalKeyring2, encryptResult2.getResult()); - assert Arrays.equals(decryptResult2.getResult(), EXAMPLE_DATA); - } - - public static void main(final String[] args) { - if (args.length <= 0) { - throw new IllegalArgumentException( - "To run this example, include the keyStoreTableName, logicalKeyStoreName, partitionId, and kmsKeyId in args"); - } - final String keyStoreTableName = args[0]; - final String logicalKeyStoreName = args[1]; - final String partitionId = args[2]; - final String kmsKeyId = args[3]; - encryptAndDecryptWithKeyring(keyStoreTableName, logicalKeyStoreName, partitionId, kmsKeyId); - } + private static final byte[] EXAMPLE_DATA = "Hello World".getBytes(StandardCharsets.UTF_8); + + public static void encryptAndDecryptWithKeyring( + String keyStoreTableName, String logicalKeyStoreName, String partitionId, String kmsKeyId) { + // Create the CryptographicMaterialsCache (CMC) to share across multiple Hierarchical Keyrings + // using the Material Providers Library + // This CMC takes in: + // - CacheType + final MaterialProviders matProv = + MaterialProviders.builder() + .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) + .build(); + + final CacheType cache = + CacheType.builder() + .Default(DefaultCache.builder().entryCapacity(100).build()) + .build(); + + final CreateCryptographicMaterialsCacheInput cryptographicMaterialsCacheInput = + CreateCryptographicMaterialsCacheInput.builder() + .cache(cache) + .build(); + + final ICryptographicMaterialsCache sharedCryptographicMaterialsCache = + matProv.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput); + + // Create a CacheType object for the sharedCryptographicMaterialsCache + // Note that the `cache` parameter in the Hierarchical Keyring Input takes a `CacheType` as input + final CacheType sharedCache = + CacheType.builder() + // This is the `Shared` CacheType that passes an already initialized shared cache + .Shared(sharedCryptographicMaterialsCache) + .build(); + + // Instantiate the SDK + // This builds the AwsCrypto client with the RequireEncryptRequireDecrypt commitment policy, + // which enforces that this client only encrypts using committing algorithm suites and enforces + // that this client will only decrypt encrypted messages that were created with a committing + // algorithm suite. + // This is the default commitment policy if you build the client with + // `AwsCrypto.builder().build()` + // or `AwsCrypto.standard()`. + final AwsCrypto crypto = AwsCrypto.builder().build(); + + // Configure your KeyStore resource keystore1. + // This SHOULD be the same configuration that you used + // to initially create and populate your physical KeyStore. + // Note that ddbTableName keyStoreTableName is the physical Key Store, + // and keystore1 is instances of this physical Key Store. + final KeyStore keystore1 = + KeyStore.builder() + .KeyStoreConfig( + KeyStoreConfig.builder() + .ddbClient(DynamoDbClient.create()) + .ddbTableName(keyStoreTableName) + .logicalKeyStoreName(logicalKeyStoreName) + .kmsClient(KmsClient.create()) + .kmsConfiguration(KMSConfiguration.builder().kmsKeyArn(kmsKeyId).build()) + .build()) + .build(); + + // Call CreateKey to create a new active branch key + final String branchKeyId = + keystore1.CreateKey(CreateKeyInput.builder().build()).branchKeyIdentifier(); + + // Create the Hierarchical Keyring HK1 with Key Store instance K1, partitionId, + // the shared Cache and the BranchKeyId. + // Note that we are now providing an already initialized shared cache instead of just mentioning + // the cache type and the Hierarchical Keyring initializing a cache at initialization. + final CreateAwsKmsHierarchicalKeyringInput keyringInput1 = + CreateAwsKmsHierarchicalKeyringInput.builder() + .keyStore(keystore1) + .branchKeyId(branchKeyId) + .ttlSeconds(600) + .cache(sharedCache) + .partitionId(partitionId) + .build(); + final IKeyring hierarchicalKeyring1 = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput1); + + // Create example encryption context + Map encryptionContext = new HashMap<>(); + encryptionContext.put("encryption", "context"); + encryptionContext.put("is not", "secret"); + encryptionContext.put("but adds", "useful metadata"); + encryptionContext.put("that can help you", "be confident that"); + encryptionContext.put("the data you are handling", "is what you think it is"); + + // Encrypt the data for encryptionContext using hierarchicalKeyring1 + final CryptoResult encryptResult1 = + crypto.encryptData(hierarchicalKeyring1, EXAMPLE_DATA, encryptionContext); + + // Decrypt your encrypted data using the same keyring HK1 you used on encrypt. + final CryptoResult decryptResult1 = + crypto.decryptData(hierarchicalKeyring1, encryptResult1.getResult()); + assert Arrays.equals(decryptResult1.getResult(), EXAMPLE_DATA); + + // Through the above encrypt and decrypt roundtrip, the cache will be populated and + // the cache entries can be used by another Hierarchical Keyring with the + // - Same Partition ID + // - Same Logical Key Store Name of the Key Store for the Hierarchical Keyring + // - Same Branch Key ID + + // Configure your KeyStore resource keystore2. + // This SHOULD be the same configuration that you used + // to initially create and populate your physical KeyStore. + // Note that ddbTableName keyStoreTableName is the physical Key Store, + // and keystore2 is instances of this physical Key Store. + + // Note that for this example, keystore2 is identical to keystore1. + // You can optionally change configurations like KMS Client or KMS Key ID based + // on your use-case. + // Make sure you have the required permissions to use different configurations. + + // - If you want to share cache entries across two keyrings HK1 and HK2, + // you should set the Logical Key Store Names for both + // Key Store instances (K1 and K2) to be the same. + // - If you set the Logical Key Store Names for K1 and K2 to be different, + // HK1 (which uses Key Store instance K1) and HK2 (which uses Key Store + // instance K2) will NOT be able to share cache entries. + final KeyStore keystore2 = + KeyStore.builder() + .KeyStoreConfig( + KeyStoreConfig.builder() + .ddbClient(DynamoDbClient.create()) + .ddbTableName(keyStoreTableName) + .logicalKeyStoreName(logicalKeyStoreName) + .kmsClient(KmsClient.create()) + .kmsConfiguration(KMSConfiguration.builder().kmsKeyArn(kmsKeyId).build()) + .build()) + .build(); + + // Create the Hierarchical Keyring HK2 with Key Store instance K2, the shared Cache + // and the same partitionId and BranchKeyId used in HK1 because we want to share cache entries + // (and experience cache HITS). + final CreateAwsKmsHierarchicalKeyringInput keyringInput2 = + CreateAwsKmsHierarchicalKeyringInput.builder() + .keyStore(keystore2) + .branchKeyId(branchKeyId) + .ttlSeconds(600) + .cache(sharedCache) + .partitionId(partitionId) + .build(); + final IKeyring hierarchicalKeyring2 = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput2); + + // This encrypt-decrypt roundtrip with HK2 will experience Cache HITS from previous HK1 roundtrip + // Encrypt the data for encryptionContext using hierarchicalKeyring2 + final CryptoResult encryptResult2 = + crypto.encryptData(hierarchicalKeyring2, EXAMPLE_DATA, encryptionContext); + + // Decrypt your encrypted data using the same keyring HK2 you used on encrypt. + final CryptoResult decryptResult2 = + crypto.decryptData(hierarchicalKeyring2, encryptResult2.getResult()); + assert Arrays.equals(decryptResult2.getResult(), EXAMPLE_DATA); +} + + public static void main(final String[] args) { + if (args.length <= 0) { + throw new IllegalArgumentException( + "To run this example, include the keyStoreTableName, logicalKeyStoreName, partitionId, and kmsKeyId in args"); + } + final String keyStoreTableName = args[0]; + final String logicalKeyStoreName = args[1]; + final String partitionId = args[2]; + final String kmsKeyId = args[3]; + encryptAndDecryptWithKeyring(keyStoreTableName, logicalKeyStoreName, partitionId, kmsKeyId); + } } From 63b323672dd62f9ee9b700d1afcb0b84701732a9 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Mon, 30 Sep 2024 15:43:14 -0700 Subject: [PATCH 06/11] fix --- ...SharedCacheAcrossHierarchicalKeyringsExample.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java index 863aba1c..874a585b 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java @@ -11,12 +11,12 @@ import software.amazon.cryptography.keystore.model.CreateKeyInput; import software.amazon.cryptography.keystore.model.KMSConfiguration; import software.amazon.cryptography.keystore.model.KeyStoreConfig; -import software.amazon.cryptography.materialproviders.CryptographicMaterialsCache; import software.amazon.cryptography.materialproviders.ICryptographicMaterialsCache; import software.amazon.cryptography.materialproviders.IKeyring; import software.amazon.cryptography.materialproviders.MaterialProviders; import software.amazon.cryptography.materialproviders.model.CacheType; import software.amazon.cryptography.materialproviders.model.CreateAwsKmsHierarchicalKeyringInput; +import software.amazon.cryptography.materialproviders.mdoel.CreateCryptographicMaterialsCacheInput; import software.amazon.cryptography.materialproviders.model.DefaultCache; import software.amazon.cryptography.materialproviders.model.MaterialProvidersConfig; @@ -114,7 +114,7 @@ public static void encryptAndDecryptWithKeyring( // Create a CacheType object for the sharedCryptographicMaterialsCache // Note that the `cache` parameter in the Hierarchical Keyring Input takes a `CacheType` as input final CacheType sharedCache = - CacheType.builder() + CacheType.builder() // This is the `Shared` CacheType that passes an already initialized shared cache .Shared(sharedCryptographicMaterialsCache) .build(); @@ -188,10 +188,10 @@ public static void encryptAndDecryptWithKeyring( // - Same Branch Key ID // Configure your KeyStore resource keystore2. - // This SHOULD be the same configuration that you used - // to initially create and populate your physical KeyStore. - // Note that ddbTableName keyStoreTableName is the physical Key Store, - // and keystore2 is instances of this physical Key Store. + // This SHOULD be the same configuration that you used + // to initially create and populate your physical KeyStore. + // Note that ddbTableName keyStoreTableName is the physical Key Store, + // and keystore2 is instances of this physical Key Store. // Note that for this example, keystore2 is identical to keystore1. // You can optionally change configurations like KMS Client or KMS Key ID based From 6c9a27b644ead2361b7d33b782c32faaf800501f Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Mon, 30 Sep 2024 16:05:48 -0700 Subject: [PATCH 07/11] fi --- .../SharedCacheAcrossHierarchicalKeyringsExample.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java index 874a585b..50826cac 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java @@ -16,7 +16,7 @@ import software.amazon.cryptography.materialproviders.MaterialProviders; import software.amazon.cryptography.materialproviders.model.CacheType; import software.amazon.cryptography.materialproviders.model.CreateAwsKmsHierarchicalKeyringInput; -import software.amazon.cryptography.materialproviders.mdoel.CreateCryptographicMaterialsCacheInput; +import software.amazon.cryptography.materialproviders.model.CreateCryptographicMaterialsCacheInput; import software.amazon.cryptography.materialproviders.model.DefaultCache; import software.amazon.cryptography.materialproviders.model.MaterialProvidersConfig; From 53b59bbe8380956bb8071e0794cd7be7b5df2ce0 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Tue, 1 Oct 2024 15:47:55 -0700 Subject: [PATCH 08/11] comments update --- .../SharedCacheAcrossHierarchicalKeyringsExample.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java index 50826cac..cefe1fe9 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java @@ -179,6 +179,8 @@ public static void encryptAndDecryptWithKeyring( // Decrypt your encrypted data using the same keyring HK1 you used on encrypt. final CryptoResult decryptResult1 = crypto.decryptData(hierarchicalKeyring1, encryptResult1.getResult()); + + // Demonstrate that the decrypted plaintext is identical to the original plaintext. assert Arrays.equals(decryptResult1.getResult(), EXAMPLE_DATA); // Through the above encrypt and decrypt roundtrip, the cache will be populated and @@ -237,6 +239,8 @@ public static void encryptAndDecryptWithKeyring( // Decrypt your encrypted data using the same keyring HK2 you used on encrypt. final CryptoResult decryptResult2 = crypto.decryptData(hierarchicalKeyring2, encryptResult2.getResult()); + + // Demonstrate that the decrypted plaintext is identical to the original plaintext. assert Arrays.equals(decryptResult2.getResult(), EXAMPLE_DATA); } From 3b84e4f7db4de4fb0e1a9f1721a2f21867771b43 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Tue, 1 Oct 2024 16:12:38 -0700 Subject: [PATCH 09/11] fix partition id to random uuid --- ...SharedCacheAcrossHierarchicalKeyringsExample.java | 12 +++++++++++- .../amazonaws/encryptionsdk/kms/KMSTestFixtures.java | 4 +++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java index cefe1fe9..a28ec06f 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java @@ -34,7 +34,7 @@ * With this functionality, users only need to maintain one common shared cache across multiple * Hierarchical Keyrings with different Key Stores instances/KMS Clients/KMS Keys. * - *

There are two important parameters that users need to carefully set while providing the shared cache: + *

There are three important parameters that users need to carefully set while providing the shared cache: * *

Partition ID - Partition ID is an optional parameter provided to the Hierarchical Keyring input, * which distinguishes Cryptographic Material Providers (i.e: Keyrings) writing to a cache. @@ -55,6 +55,8 @@ * - If you set the Logical Key Store Names for K1 and K2 to be different, HK1 (which uses Key Store instance K1) * and HK2 (which uses Key Store instance K2) will NOT be able to share cache entries. * + *

Branch Key ID - Choose an effective Branch Key ID Schema + * * This is demonstrated in the example below. * Notice that both K1 and K2 are instances of the same physical Key Store (K). * You MUST NEVER have two different physical Key Stores with the same Logical Key Store Name. @@ -154,6 +156,10 @@ public static void encryptAndDecryptWithKeyring( // the shared Cache and the BranchKeyId. // Note that we are now providing an already initialized shared cache instead of just mentioning // the cache type and the Hierarchical Keyring initializing a cache at initialization. + + // Please make sure that you read the guidance on how to set Partition ID, Logical Key Store Name and + // Branch Key ID at the top of this example before creating Hierarchical Keyrings with a Shared Cache + final CreateAwsKmsHierarchicalKeyringInput keyringInput1 = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(keystore1) @@ -221,6 +227,10 @@ public static void encryptAndDecryptWithKeyring( // Create the Hierarchical Keyring HK2 with Key Store instance K2, the shared Cache // and the same partitionId and BranchKeyId used in HK1 because we want to share cache entries // (and experience cache HITS). + + // Please make sure that you read the guidance on how to set Partition ID, Logical Key Store Name and + // Branch Key ID at the top of this example before creating Hierarchical Keyrings with a Shared Cache + final CreateAwsKmsHierarchicalKeyringInput keyringInput2 = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(keystore2) diff --git a/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java b/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java index e99232ec..621496a2 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java +++ b/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java @@ -37,5 +37,7 @@ private KMSTestFixtures() { public static final String TEST_LOGICAL_KEYSTORE_NAME = "KeyStoreDdbTable"; public static final String TEST_KEYSTORE_KMS_KEY_ID = "arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126"; - public static final String HIERARCHY_KEYRING_PARTITION_ID = "partition_id"; + + // HIERARCHY_KEYRING_PARTITION_ID here is a random UUID + public static final String HIERARCHY_KEYRING_PARTITION_ID = "91c1b6a2-6fc3-4539-ad5e-938d597ed730"; } From e88d93f626e13302d23aade6dda3f451c5c0f0f3 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Tue, 1 Oct 2024 16:24:40 -0700 Subject: [PATCH 10/11] m --- .../SharedCacheAcrossHierarchicalKeyringsExample.java | 4 +++- .../java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java index a28ec06f..3fe9b1c3 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/keyrings/hierarchical/SharedCacheAcrossHierarchicalKeyringsExample.java @@ -159,7 +159,8 @@ public static void encryptAndDecryptWithKeyring( // Please make sure that you read the guidance on how to set Partition ID, Logical Key Store Name and // Branch Key ID at the top of this example before creating Hierarchical Keyrings with a Shared Cache - + // partitionId for this example is a random UUID + final CreateAwsKmsHierarchicalKeyringInput keyringInput1 = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(keystore1) @@ -230,6 +231,7 @@ public static void encryptAndDecryptWithKeyring( // Please make sure that you read the guidance on how to set Partition ID, Logical Key Store Name and // Branch Key ID at the top of this example before creating Hierarchical Keyrings with a Shared Cache + // partitionId for this example is a random UUID final CreateAwsKmsHierarchicalKeyringInput keyringInput2 = CreateAwsKmsHierarchicalKeyringInput.builder() diff --git a/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java b/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java index 621496a2..167f14cb 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java +++ b/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java @@ -38,6 +38,5 @@ private KMSTestFixtures() { public static final String TEST_KEYSTORE_KMS_KEY_ID = "arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126"; - // HIERARCHY_KEYRING_PARTITION_ID here is a random UUID public static final String HIERARCHY_KEYRING_PARTITION_ID = "91c1b6a2-6fc3-4539-ad5e-938d597ed730"; } From 5e39067bba9bcbe5b47c2f3b021436d7866b1604 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Tue, 1 Oct 2024 16:37:29 -0700 Subject: [PATCH 11/11] fix --- .../java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java b/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java index 167f14cb..e673cf21 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java +++ b/src/test/java/com/amazonaws/encryptionsdk/kms/KMSTestFixtures.java @@ -38,5 +38,6 @@ private KMSTestFixtures() { public static final String TEST_KEYSTORE_KMS_KEY_ID = "arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126"; - public static final String HIERARCHY_KEYRING_PARTITION_ID = "91c1b6a2-6fc3-4539-ad5e-938d597ed730"; + public static final String HIERARCHY_KEYRING_PARTITION_ID = + "91c1b6a2-6fc3-4539-ad5e-938d597ed730"; }