From 68ad171fd91d60f83b9416f40ebe9050e93a5de4 Mon Sep 17 00:00:00 2001 From: Wesley Rosenblum Date: Fri, 7 Feb 2020 15:58:05 -0800 Subject: [PATCH 1/5] Update Readme for Keyrings --- README.md | 93 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 0387070cc..4eefaeba2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # AWS Encryption SDK for Java -The AWS Encryption SDK enables secure client-side encryption. It uses cryptography best practices to protect your data and the encryption keys used to protect that data. Each data object is protected with a unique data encryption key (DEK), and the DEK is protected with a key encryption key (KEK) called a *master key*. The encrypted DEK is combined with the encrypted data into a single [encrypted message](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html), so you don't need to keep track of the DEKs for your data. The SDK supports master keys in [AWS Key Management Service](https://aws.amazon.com/kms/) (KMS), and it also provides APIs to define and use other master key providers. The SDK provides methods for encrypting and decrypting strings, byte arrays, and byte streams. For details, see the [example code][examples] and the [Javadoc](https://aws.github.io/aws-encryption-sdk-java/javadoc/). +The AWS Encryption SDK is a client-side encryption library designed to make it easy for everyone to encrypt and decrypt data using industry standards and best practices. It enables you to focus on the core functionality of your application, rather than on how to best encrypt and decrypt your data. For more details about the design and architecture of the SDK, see the [official documentation](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/). @@ -63,65 +63,78 @@ You can get the latest release from Maven: The following code sample demonstrates how to get started: 1. Instantiate the SDK. -2. Define the master key provider. +2. Setup an AWS KMS Keyring. 3. Encrypt and decrypt data. ```java -// This sample code encrypts and then decrypts a string using a KMS CMK. -// You provide the KMS key ARN and plaintext string as arguments. +// This sample code encrypts and then decrypts data using an AWS KMS customer master key (CMK). package com.amazonaws.crypto.examples; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.Collections; import java.util.Map; import com.amazonaws.encryptionsdk.AwsCrypto; -import com.amazonaws.encryptionsdk.CryptoResult; -import com.amazonaws.encryptionsdk.kms.KmsMasterKey; -import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; +import com.amazonaws.encryptionsdk.AwsCryptoResult; +import com.amazonaws.encryptionsdk.DecryptRequest; +import com.amazonaws.encryptionsdk.EncryptRequest; +import com.amazonaws.encryptionsdk.keyrings.Keyring; +import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings; +import com.amazonaws.encryptionsdk.kms.AwsKmsCmkId; -public class StringExample { - private static String keyArn; - private static String data; +public class BasicEncryptionExample { + + private static final byte[] EXAMPLE_DATA = "Hello World".getBytes(StandardCharsets.UTF_8); public static void main(final String[] args) { - keyArn = args[0]; - data = args[1]; + encryptAndDecrypt(AwsKmsCmkId.fromString(args[0])); + } - // Instantiate the SDK + static void encryptAndDecrypt(final AwsKmsCmkId keyArn) { + // 1. Instantiate the SDK final AwsCrypto crypto = new AwsCrypto(); - // Set up the master key provider - final KmsMasterKeyProvider prov = new KmsMasterKeyProvider(keyArn); + // 2. Instantiate an AWS KMS Keyring, supplying the key ARN as the generator for generating a + // data key. While using a key ARN is a best practice, for encryption operations it is also + // acceptable to use a CMK alias or an alias ARN. + final Keyring keyring = StandardKeyrings.awsKms(keyArn); - // Encrypt the data + // 3. Create an encryption context // - // NOTE: Encrypted data should have associated encryption context - // to protect integrity. For this example, just use a placeholder - // value. For more information about encryption context, see - // https://amzn.to/1nSbe9X (blogs.aws.amazon.com) - final Map context = Collections.singletonMap("Example", "String"); - - final String ciphertext = crypto.encryptString(prov, data, context).getResult(); - System.out.println("Ciphertext: " + ciphertext); - - // Decrypt the data - final CryptoResult decryptResult = crypto.decryptString(prov, ciphertext); - // Check the encryption context (and ideally the master key) to - // ensure this is the expected ciphertext - if (!decryptResult.getMasterKeyIds().get(0).equals(keyArn)) { - throw new IllegalStateException("Wrong key id!"); + // Most encrypted data should have an associated encryption context + // to protect integrity. This sample uses placeholder values. + // + // For more information see: https://amzn.to/1nSbe9X (blogs.aws.amazon.com) + final Map encryptionContext = Collections.singletonMap("Example", "String"); + + // 4. Encrypt the data with the keyring and encryption context + final AwsCryptoResult encryptResult = crypto.encrypt( + EncryptRequest.builder() + .keyring(keyring) + .encryptionContext(encryptionContext) + .plaintext(EXAMPLE_DATA).build()); + final byte[] ciphertext = encryptResult.getResult(); + + // 5. Decrypt the data. The same keyring may be used to encrypt and decrypt, but for decryption + // the key IDs must be in the key ARN format. + final AwsCryptoResult decryptResult = crypto.decrypt( + DecryptRequest.builder() + .keyring(keyring) + .ciphertext(ciphertext).build()); + + // 6. The Keyring Trace may be inspected to verify which CMK was used for decryption. + if(!decryptResult.getKeyringTrace().getEntries().get(0).getKeyName().equals(keyArn.toString())) { + throw new IllegalStateException("Wrong key ID!"); } - // The SDK may add information to the encryption context, so check to - // ensure all of the values are present - for (final Map.Entry e : context.entrySet()) { - if (!e.getValue().equals(decryptResult.getEncryptionContext().get(e.getKey()))) { - throw new IllegalStateException("Wrong Encryption Context!"); - } - } + // 7. Verify that the encryption context in the result contains the + // data that we expect. The SDK can add values to the encryption context, + // so there may be additional keys in the result context. + assert decryptResult.getEncryptionContext().get("Example").equals("String"); - // The data is correct, so output it. - System.out.println("Decrypted: " + decryptResult.getResult()); + // 8. Verify that the decrypted plaintext matches the original plaintext + assert Arrays.equals(decryptResult.getResult(), EXAMPLE_DATA); } } ``` From aef8c234a048a76009bae781afee53d67cdf49e1 Mon Sep 17 00:00:00 2001 From: Wesley Rosenblum Date: Fri, 7 Feb 2020 16:02:34 -0800 Subject: [PATCH 2/5] Update Readme again --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4eefaeba2..1a6a6384f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ The AWS Encryption SDK is a client-side encryption library designed to make it easy for everyone to encrypt and decrypt data using industry standards and best practices. It enables you to focus on the core functionality of your application, rather than on how to best encrypt and decrypt your data. -For more details about the design and architecture of the SDK, see the [official documentation](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/). +For details about the design, architecture and usage of the SDK, see the [official documentation](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/), [example code][examples] and the [Javadoc](https://aws.github.io/aws-encryption-sdk-java/javadoc/). ## Getting Started @@ -54,7 +54,7 @@ You can get the latest release from Maven: com.amazonaws aws-encryption-sdk-java - 1.6.1 + 1.7.0 ``` From 862f97e33fff7c84c254254a067d2253aec4645a Mon Sep 17 00:00:00 2001 From: Wesley Rosenblum Date: Tue, 11 Feb 2020 14:46:17 -0800 Subject: [PATCH 3/5] Updating wording to match example code --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1a6a6384f..8bf69c17d 100644 --- a/README.md +++ b/README.md @@ -123,14 +123,17 @@ public class BasicEncryptionExample { .keyring(keyring) .ciphertext(ciphertext).build()); - // 6. The Keyring Trace may be inspected to verify which CMK was used for decryption. + // 6. To verify the CMK that was actually used in the decrypt operation, inspect the keyring trace. if(!decryptResult.getKeyringTrace().getEntries().get(0).getKeyName().equals(keyArn.toString())) { throw new IllegalStateException("Wrong key ID!"); } - // 7. Verify that the encryption context in the result contains the - // data that we expect. The SDK can add values to the encryption context, - // so there may be additional keys in the result context. + // 7. To verify that the encryption context used to decrypt the data was the encryption context you expected, + // examine the encryption context in the result. This helps to ensure that you decrypted the ciphertext that + // you intended. + // + // When verifying, test that your expected encryption context is a subset of the actual encryption context, + // not an exact match. The Encryption SDK adds the signing key to the encryption context when appropriate. assert decryptResult.getEncryptionContext().get("Example").equals("String"); // 8. Verify that the decrypted plaintext matches the original plaintext From 8a686a5935e316ab65710b7a51dc6d842fcbbd1e Mon Sep 17 00:00:00 2001 From: Wesley Rosenblum Date: Tue, 11 Feb 2020 16:28:17 -0800 Subject: [PATCH 4/5] Remove AWS from AWS KMS keyring and make keyring lowercase --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8bf69c17d..68fc5b8e0 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ You can get the latest release from Maven: The following code sample demonstrates how to get started: 1. Instantiate the SDK. -2. Setup an AWS KMS Keyring. +2. Setup a KMS keyring. 3. Encrypt and decrypt data. ```java @@ -95,7 +95,7 @@ public class BasicEncryptionExample { // 1. Instantiate the SDK final AwsCrypto crypto = new AwsCrypto(); - // 2. Instantiate an AWS KMS Keyring, supplying the key ARN as the generator for generating a + // 2. Instantiate a KMS keyring, supplying the key ARN as the generator for generating a // data key. While using a key ARN is a best practice, for encryption operations it is also // acceptable to use a CMK alias or an alias ARN. final Keyring keyring = StandardKeyrings.awsKms(keyArn); From 63f4452097611ba752f334813e910200fda1f4d8 Mon Sep 17 00:00:00 2001 From: Wesley Rosenblum Date: Tue, 11 Feb 2020 16:40:10 -0800 Subject: [PATCH 5/5] Updating wording --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 68fc5b8e0..1a4831a09 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ The following code sample demonstrates how to get started: 3. Encrypt and decrypt data. ```java -// This sample code encrypts and then decrypts data using an AWS KMS customer master key (CMK). +// This sample code encrypts and then decrypts data using an AWS Key Management Service (AWS KMS) customer master key (CMK). package com.amazonaws.crypto.examples; import java.nio.charset.StandardCharsets; @@ -95,9 +95,9 @@ public class BasicEncryptionExample { // 1. Instantiate the SDK final AwsCrypto crypto = new AwsCrypto(); - // 2. Instantiate a KMS keyring, supplying the key ARN as the generator for generating a - // data key. While using a key ARN is a best practice, for encryption operations it is also - // acceptable to use a CMK alias or an alias ARN. + // 2. Instantiate a KMS keyring. Supply the key ARN for the generator key that generates a + // data key. While using a key ARN is a best practice, for encryption operations you can also + // use an alias name or alias ARN. final Keyring keyring = StandardKeyrings.awsKms(keyArn); // 3. Create an encryption context @@ -116,7 +116,7 @@ public class BasicEncryptionExample { .plaintext(EXAMPLE_DATA).build()); final byte[] ciphertext = encryptResult.getResult(); - // 5. Decrypt the data. The same keyring may be used to encrypt and decrypt, but for decryption + // 5. Decrypt the data. You can use the same keyring to encrypt and decrypt, but for decryption // the key IDs must be in the key ARN format. final AwsCryptoResult decryptResult = crypto.decrypt( DecryptRequest.builder()