Skip to content

Commit 12f0c42

Browse files
Additional example code for Keyrings (#155)
* Additional example code for Keyrings * Updating wording * Remove AWS from AWS KMS keyring and make keyring lowercase
1 parent ff9dab6 commit 12f0c42

12 files changed

+594
-27
lines changed

pom.xml

+13
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@
8080
<scope>test</scope>
8181
</dependency>
8282

83+
<dependency>
84+
<groupId>com.amazonaws</groupId>
85+
<artifactId>aws-lambda-java-core</artifactId>
86+
<version>1.2.0</version>
87+
<scope>test</scope>
88+
</dependency>
89+
90+
<dependency>
91+
<groupId>com.amazonaws</groupId>
92+
<artifactId>aws-lambda-java-events</artifactId>
93+
<version>2.2.7</version>
94+
<scope>test</scope>
95+
</dependency>
8396

8497
<dependency>
8598
<groupId>com.google.code.findbugs</groupId>

src/examples/java/com/amazonaws/crypto/examples/BasicEncryptionExample.java

+13-15
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
/**
3030
* <p>
31-
* Encrypts and then decrypts data using an AWS KMS customer master key.
31+
* Encrypts and then decrypts data using an AWS Key Management Service (AWS KMS) customer master key.
3232
*
3333
* <p>
3434
* Arguments:
@@ -49,9 +49,9 @@ static void encryptAndDecrypt(final AwsKmsCmkId keyArn) {
4949
// 1. Instantiate the SDK
5050
final AwsCrypto crypto = new AwsCrypto();
5151

52-
// 2. Instantiate an AWS KMS Keyring, supplying the key ARN as the generator for generating a data key. While
53-
// using a key ARN is a best practice, for encryption operations it is also acceptable to use a CMK alias or
54-
// an alias ARN.
52+
// 2. Instantiate a KMS keyring. Supply the key ARN for the generator key
53+
// that generates a data key. While using a key ARN is a best practice,
54+
// for encryption operations you can also use an alias name or alias ARN.
5555
final Keyring keyring = StandardKeyrings.awsKms(keyArn);
5656

5757
// 3. Create an encryption context
@@ -71,27 +71,25 @@ static void encryptAndDecrypt(final AwsKmsCmkId keyArn) {
7171
.plaintext(EXAMPLE_DATA).build());
7272
final byte[] ciphertext = encryptResult.getResult();
7373

74-
// 5. Decrypt the data. The same keyring may be used to encrypt and decrypt, but for decryption
74+
// 5. Decrypt the data. You can use the same keyring to encrypt and decrypt, but for decryption
7575
// the key IDs must be in the key ARN format.
7676
final AwsCryptoResult<byte[]> decryptResult = crypto.decrypt(
7777
DecryptRequest.builder()
7878
.keyring(keyring)
7979
.ciphertext(ciphertext).build());
8080

81-
// 6. Before verifying the plaintext, inspect the Keyring Trace to verify that the CMK used
82-
// to decrypt the encrypted data key was the CMK in the encryption keyring.
81+
// 6. To verify the CMK that was actually used in the decrypt operation, inspect the keyring trace.
8382
if(!decryptResult.getKeyringTrace().getEntries().get(0).getKeyName().equals(keyArn.toString())) {
8483
throw new IllegalStateException("Wrong key ID!");
8584
}
8685

87-
// 7. Also, verify that the encryption context in the result contains the
88-
// encryption context supplied to the encryptData method. Because the
89-
// SDK can add values to the encryption context, don't require that
90-
// the entire context matches.
91-
if (!encryptionContext.entrySet().stream()
92-
.allMatch(e -> e.getValue().equals(decryptResult.getEncryptionContext().get(e.getKey())))) {
93-
throw new IllegalStateException("Wrong Encryption Context!");
94-
}
86+
// 7. To verify that the encryption context used to decrypt the data was the encryption context you expected,
87+
// examine the encryption context in the result. This helps to ensure that you decrypted the ciphertext that
88+
// you intended.
89+
//
90+
// When verifying, test that your expected encryption context is a subset of the actual encryption context,
91+
// not an exact match. The Encryption SDK adds the signing key to the encryption context when appropriate.
92+
assert decryptResult.getEncryptionContext().get("ExampleContextKey").equals("ExampleContextValue");
9593

9694
// 8. Verify that the decrypted plaintext matches the original plaintext
9795
assert Arrays.equals(decryptResult.getResult(), EXAMPLE_DATA);

src/examples/java/com/amazonaws/crypto/examples/EscrowedEncryptExample.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ private static byte[] standardEncrypt(final AwsKmsCmkId kmsArn, final PublicKey
8484
// 1. Instantiate the SDK
8585
final AwsCrypto crypto = new AwsCrypto();
8686

87-
// 2. Instantiate an AWS KMS Keyring, supplying the keyArn as the generator for generating a data key.
87+
// 2. Instantiate a KMS keyring, supplying the keyArn as the generator for generating a data key.
8888
final Keyring kmsKeyring = StandardKeyrings.awsKms(kmsArn);
8989

9090
// 3. Instantiate a RawRsaKeyring
@@ -115,7 +115,7 @@ private static byte[] standardDecrypt(final AwsKmsCmkId kmsArn, final byte[] cip
115115
// 1. Instantiate the SDK
116116
final AwsCrypto crypto = new AwsCrypto();
117117

118-
// 2. Instantiate an AWS KMS Keyring, supplying the keyArn as the generator for generating a data key.
118+
// 2. Instantiate a KMS keyring, supplying the keyArn as the generator for generating a data key.
119119
final Keyring kmsKeyring = StandardKeyrings.awsKms(kmsArn);
120120

121121
// 4. Decrypt the data with the keyring.

src/examples/java/com/amazonaws/crypto/examples/FileStreamingExample.java

+11-10
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ static void encryptAndDecrypt(final File srcFile, final File encryptedFile, fina
6363
// 1. Instantiate the SDK
6464
final AwsCrypto crypto = new AwsCrypto();
6565

66-
// 2. Retrieve an encryption key. In this example, we generate a random key.
67-
// In practice, you would get a key from an existing store
68-
final SecretKey cryptoKey = retrieveEncryptionKey();
66+
// 2. Get an encryption key. In this example, we generate a random key.
67+
// In practice, you would get a key from an existing key store.
68+
final SecretKey cryptoKey = generateEncryptKey();
6969

7070
// 3. Instantiate a RawAesKeyring using the random key
7171
final Keyring keyring = StandardKeyrings.rawAesBuilder()
@@ -104,11 +104,12 @@ static void encryptAndDecrypt(final File srcFile, final File encryptedFile, fina
104104
.keyring(keyring)
105105
.inputStream(new FileInputStream(encryptedFile)).build())) {
106106

107-
// 8. Verify that the encryption context in the result contains the
108-
// encryption context supplied to the createEncryptingStream method.
109-
if (!"FileStreaming".equals(decryptingStream.getAwsCryptoResult().getEncryptionContext().get("Example"))) {
110-
throw new IllegalStateException("Bad encryption context");
111-
}
107+
// 8. Verify that the encryption context that was used to decrypt the data is the one that you expect.
108+
// This helps to ensure that the ciphertext that you decrypted was the one that you intended.
109+
//
110+
// When verifying, test that your expected encryption context is a subset of the actual encryption context,
111+
// not an exact match. When appropriate, the Encryption SDK adds the signing key to the encryption context.
112+
assert "FileStreaming".equals(decryptingStream.getAwsCryptoResult().getEncryptionContext().get("Example"));
112113

113114
// 9. Copy the plaintext data to a file
114115
try (FileOutputStream out = new FileOutputStream(decryptedFile)) {
@@ -122,9 +123,9 @@ static void encryptAndDecrypt(final File srcFile, final File encryptedFile, fina
122123

123124
/**
124125
* In practice, this key would be saved in a secure location.
125-
* For this demo, we generate a new random key for each operation.
126+
* In this example, we generate a new random key for each operation.
126127
*/
127-
private static SecretKey retrieveEncryptionKey() {
128+
private static SecretKey generateEncryptKey() {
128129
SecureRandom rnd = new SecureRandom();
129130
byte[] rawKey = new byte[16]; // 128 bits
130131
rnd.nextBytes(rawKey);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
5+
* in compliance with the License. A copy of the License is located at
6+
*
7+
* http://aws.amazon.com/apache2.0
8+
*
9+
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package com.amazonaws.crypto.examples;
15+
16+
import com.amazonaws.encryptionsdk.AwsCrypto;
17+
import com.amazonaws.encryptionsdk.AwsCryptoResult;
18+
import com.amazonaws.encryptionsdk.DecryptRequest;
19+
import com.amazonaws.encryptionsdk.EncryptRequest;
20+
import com.amazonaws.encryptionsdk.keyrings.Keyring;
21+
import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings;
22+
23+
import javax.crypto.KeyGenerator;
24+
import javax.crypto.SecretKey;
25+
import javax.crypto.spec.SecretKeySpec;
26+
import java.nio.charset.StandardCharsets;
27+
import java.security.SecureRandom;
28+
import java.util.Arrays;
29+
import java.util.Collections;
30+
import java.util.Map;
31+
32+
/**
33+
* <p>
34+
* Encrypts and then decrypts data using the Raw AES keyring.
35+
*/
36+
public class RawAesKeyringExample {
37+
38+
private static final byte[] EXAMPLE_DATA = "Hello World".getBytes(StandardCharsets.UTF_8);
39+
40+
public static void main(final String[] args) {
41+
encryptAndDecrypt();
42+
}
43+
44+
static void encryptAndDecrypt() {
45+
// 1. Instantiate the SDK
46+
final AwsCrypto crypto = new AwsCrypto();
47+
48+
// 2. Get an encryption key. In this example, we generate a random key.
49+
// In practice, you would get a key from an existing key store
50+
final SecretKey cryptoKey = generateEncryptKey();
51+
52+
// 3. Instantiate a Raw AES keyring with the encryption key
53+
final Keyring keyring = StandardKeyrings.rawAesBuilder()
54+
.keyNamespace("ExampleKeyNamespace")
55+
.keyName("ExampleKeyName")
56+
.wrappingKey(cryptoKey).build();
57+
58+
// 4. Create an encryption context
59+
//
60+
// Most encrypted data should have an associated encryption context
61+
// to protect integrity. This sample uses placeholder values.
62+
//
63+
// For more information see:
64+
// blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management
65+
final Map<String, String> encryptionContext = Collections.singletonMap("ExampleContextKey", "ExampleContextValue");
66+
67+
// 5. Encrypt the data with the keyring and encryption context
68+
final AwsCryptoResult<byte[]> encryptResult = crypto.encrypt(EncryptRequest.builder()
69+
.keyring(keyring)
70+
.encryptionContext(encryptionContext)
71+
.plaintext(EXAMPLE_DATA).build());
72+
final byte[] ciphertext = encryptResult.getResult();
73+
74+
// 6. Decrypt the data
75+
final AwsCryptoResult<byte[]> decryptResult = crypto.decrypt(DecryptRequest.builder()
76+
.keyring(keyring)
77+
.ciphertext(ciphertext).build());
78+
79+
// 7. Verify that the encryption context that was used to decrypt the data is the one that you expect.
80+
// This helps to ensure that the ciphertext that you decrypted was the one that you intended.
81+
//
82+
// When verifying, test that your expected encryption context is a subset of the actual encryption context,
83+
// not an exact match. When appropriate, the Encryption SDK adds the signing key to the encryption context.
84+
assert decryptResult.getEncryptionContext().get("ExampleContextKey").equals("ExampleContextValue");
85+
86+
// 8. Verify that the decrypted plaintext matches the original plaintext
87+
assert Arrays.equals(decryptResult.getResult(), EXAMPLE_DATA);
88+
}
89+
90+
/**
91+
* In practice, this key would be saved in a secure location.
92+
* For this demo, we generate a new random key for each operation.
93+
*/
94+
private static SecretKey generateEncryptKey() {
95+
SecureRandom rnd = new SecureRandom();
96+
byte[] rawKey = new byte[16]; // 128 bits
97+
rnd.nextBytes(rawKey);
98+
return new SecretKeySpec(rawKey, "AES");
99+
}
100+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
5+
* in compliance with the License. A copy of the License is located at
6+
*
7+
* http://aws.amazon.com/apache2.0
8+
*
9+
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package com.amazonaws.crypto.examples;
15+
16+
import com.amazonaws.encryptionsdk.AwsCrypto;
17+
import com.amazonaws.encryptionsdk.AwsCryptoResult;
18+
import com.amazonaws.encryptionsdk.DecryptRequest;
19+
import com.amazonaws.encryptionsdk.keyrings.Keyring;
20+
import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings;
21+
22+
import java.security.KeyPair;
23+
24+
/**
25+
* <p>
26+
* Decrypts data using the Raw RSA keyring.
27+
*/
28+
public class RawRsaKeyringDecryptExample {
29+
30+
public static byte[] decrypt(byte[] ciphertext, KeyPair keyPair) {
31+
// 1. Instantiate the SDK
32+
final AwsCrypto crypto = new AwsCrypto();
33+
34+
// 2. Instantiate a Raw RSA keyring with the private key
35+
final Keyring keyring = StandardKeyrings.rawRsaBuilder()
36+
.keyNamespace("ExampleKeyNamespace")
37+
.keyName("ExampleKeyName")
38+
.wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding")
39+
.privateKey(keyPair.getPrivate()).build();
40+
41+
// 3. Decrypt the ciphertext with the keyring
42+
final AwsCryptoResult<byte[]> decryptResult = crypto.decrypt(DecryptRequest.builder()
43+
.keyring(keyring)
44+
.ciphertext(ciphertext).build());
45+
46+
// 4. Verify that the encryption context that was used to decrypt the data is the one that you expect.
47+
// This helps to ensure that the ciphertext that you decrypted was the one that you intended.
48+
//
49+
// When verifying, test that your expected encryption context is a subset of the actual encryption context,
50+
// not an exact match. When appropriate, the Encryption SDK adds the signing key to the encryption context.
51+
assert decryptResult.getEncryptionContext().get("ExampleContextKey").equals("ExampleContextValue");
52+
53+
// 5. Return the decrypted byte array result
54+
return decryptResult.getResult();
55+
}
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
5+
* in compliance with the License. A copy of the License is located at
6+
*
7+
* http://aws.amazon.com/apache2.0
8+
*
9+
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package com.amazonaws.crypto.examples;
15+
16+
import com.amazonaws.encryptionsdk.AwsCrypto;
17+
import com.amazonaws.encryptionsdk.AwsCryptoResult;
18+
import com.amazonaws.encryptionsdk.EncryptRequest;
19+
import com.amazonaws.encryptionsdk.keyrings.Keyring;
20+
import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings;
21+
22+
import java.nio.charset.StandardCharsets;
23+
import java.security.PublicKey;
24+
import java.util.Collections;
25+
import java.util.Map;
26+
27+
/**
28+
* Encrypts data using the Raw RSA keyring.
29+
*/
30+
public class RawRsaKeyringEncryptExample {
31+
32+
static final byte[] EXAMPLE_DATA = "Hello World".getBytes(StandardCharsets.UTF_8);
33+
34+
public static byte[] encrypt(PublicKey publicKey) {
35+
// 1. Instantiate the SDK
36+
final AwsCrypto crypto = new AwsCrypto();
37+
38+
// 2. Instantiate a Raw RSA keyring with the public key
39+
final Keyring keyring = StandardKeyrings.rawRsaBuilder()
40+
.keyNamespace("ExampleKeyNamespace")
41+
.keyName("ExampleKeyName")
42+
.wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding")
43+
.publicKey(publicKey).build();
44+
45+
// 3. Create an encryption context
46+
//
47+
// Most encrypted data should have an associated encryption context
48+
// to protect integrity. This sample uses placeholder values.
49+
//
50+
// For more information see:
51+
// blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management
52+
final Map<String, String> encryptionContext = Collections.singletonMap("ExampleContextKey", "ExampleContextValue");
53+
54+
// 4. Encrypt the data with the keyring and encryption context
55+
final AwsCryptoResult<byte[]> encryptResult = crypto.encrypt(EncryptRequest.builder()
56+
.keyring(keyring)
57+
.encryptionContext(encryptionContext)
58+
.plaintext(EXAMPLE_DATA).build());
59+
60+
// 5. Return the encrypted byte array result
61+
return encryptResult.getResult();
62+
}
63+
}

0 commit comments

Comments
 (0)