Skip to content

Commit a6be12a

Browse files
committed
feat: Updates to the AWS Encryption SDK.
This change includes fixes for issues that were reported by Thai Duong from Google's Security team, and for issues that were identified by AWS Cryptography. See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/migration.html
1 parent 8f5f69e commit a6be12a

File tree

71 files changed

+5228
-960
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+5228
-960
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 1.7.0 -- 2020-09-24
4+
5+
* feat: Updates to the AWS Encryption SDK.
6+
37
## 1.6.2 -- 2020-05-26
48

59
### Patches

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ You can get the latest release from Maven:
5656
<dependency>
5757
<groupId>com.amazonaws</groupId>
5858
<artifactId>aws-encryption-sdk-java</artifactId>
59-
<version>1.6.2</version>
59+
<version>1.7.0</version>
6060
</dependency>
6161
```
6262

@@ -77,6 +77,7 @@ import java.util.Collections;
7777
import java.util.Map;
7878

7979
import com.amazonaws.encryptionsdk.AwsCrypto;
80+
import com.amazonaws.encryptionsdk.CommitmentPolicy;
8081
import com.amazonaws.encryptionsdk.CryptoResult;
8182
import com.amazonaws.encryptionsdk.kms.KmsMasterKey;
8283
import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider;
@@ -90,10 +91,12 @@ public class StringExample {
9091
data = args[1];
9192

9293
// Instantiate the SDK
93-
final AwsCrypto crypto = new AwsCrypto();
94+
final AwsCrypto crypto = AwsCrypto.builder()
95+
.withCommitmentPolicy(CommitmentPolicy.ForbidEncryptAllowDecrypt)
96+
.build();
9497

9598
// Set up the master key provider
96-
final KmsMasterKeyProvider prov = new KmsMasterKeyProvider(keyArn);
99+
final KmsMasterKeyProvider prov = KmsMasterKeyProvider.builder().buildStrict(keyArn);
97100

98101
// Encrypt the data
99102
//

pom.xml

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>com.amazonaws</groupId>
66
<artifactId>aws-encryption-sdk-java</artifactId>
7-
<version>1.6.2</version>
7+
<version>1.7.0</version>
88
<packaging>jar</packaging>
99

1010
<name>aws-encryption-sdk-java</name>
@@ -142,6 +142,54 @@
142142
</build>
143143

144144
<profiles>
145+
<profile>
146+
<id>publishingCodeArtifact</id>
147+
148+
<distributionManagement>
149+
<!--
150+
Registers an alternate repository for testing the publishing process using CodeArtifact
151+
before moving to the production sonatype repository.
152+
153+
This can be used with a mvn invocation like:
154+
155+
mvn deploy -PpublishingCodeArtifact \
156+
-DaltDeploymentRepository=codeartifact::default::$CODEARTIFACT_REPO_URL \
157+
...
158+
-->
159+
<repository>
160+
<id>codeartifact</id>
161+
<name>codeartifact</name>
162+
<!-- url specified using -DaltDeploymentRepository to avoid hardcoding it here -->
163+
</repository>
164+
</distributionManagement>
165+
166+
<!-- TODO: figure out how to share this config between the two publishing profiles -->
167+
<build>
168+
<plugins>
169+
<plugin>
170+
<groupId>org.apache.maven.plugins</groupId>
171+
<artifactId>maven-gpg-plugin</artifactId>
172+
<version>1.6</version>
173+
<executions>
174+
<execution>
175+
<id>sign-artifacts</id>
176+
<phase>verify</phase>
177+
<goals>
178+
<goal>sign</goal>
179+
</goals>
180+
<configuration>
181+
<gpgArguments>
182+
<arg>--pinentry-mode</arg>
183+
<arg>loopback</arg>
184+
</gpgArguments>
185+
</configuration>
186+
</execution>
187+
</executions>
188+
</plugin>
189+
</plugins>
190+
</build>
191+
</profile>
192+
145193
<profile>
146194
<id>publishing</id>
147195

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
1-
/*
2-
* Copyright 2019 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-
*/
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
133

144
package com.amazonaws.crypto.examples;
155

@@ -22,6 +12,7 @@
2212
import com.amazonaws.encryptionsdk.CryptoResult;
2313
import com.amazonaws.encryptionsdk.kms.KmsMasterKey;
2414
import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider;
15+
import com.amazonaws.encryptionsdk.CommitmentPolicy;
2516

2617
/**
2718
* <p>
@@ -45,35 +36,32 @@ public static void main(final String[] args) {
4536
}
4637

4738
static void encryptAndDecrypt(final String keyArn) {
48-
// 1. Instantiate the SDK
49-
final AwsCrypto crypto = new AwsCrypto();
39+
// 1. Instantiate the SDK with a specific commitment policy.
40+
// ForbidEncryptAllowDecrypt is the only available policy in 1.7.0.
41+
final AwsCrypto crypto = AwsCrypto.builder().withCommitmentPolicy(CommitmentPolicy.ForbidEncryptAllowDecrypt).build();
5042

51-
// 2. Instantiate a KMS master key provider
52-
final KmsMasterKeyProvider masterKeyProvider = KmsMasterKeyProvider.builder().withKeysForEncryption(keyArn).build();
43+
// 2. Instantiate an AWS KMS master key provider in strict mode using buildStrict()
44+
// In strict mode, the AWS KMS master key provider encrypts and decrypts only by using the key
45+
// indicated by keyArn.
46+
// To encrypt and decrypt with this master key provider, use an AWS KMS key ARN to identify the CMKs.
47+
// The decrypt operation doesn't work with any other key identifier in strict mode.
48+
final KmsMasterKeyProvider keyProvider = KmsMasterKeyProvider.builder().buildStrict(keyArn);
5349

5450
// 3. Create an encryption context
55-
//
5651
// Most encrypted data should have an associated encryption context
5752
// to protect integrity. This sample uses placeholder values.
58-
//
5953
// For more information see:
6054
// blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management
6155
final Map<String, String> encryptionContext = Collections.singletonMap("ExampleContextKey", "ExampleContextValue");
6256

6357
// 4. Encrypt the data
64-
final CryptoResult<byte[], KmsMasterKey> encryptResult = crypto.encryptData(masterKeyProvider, EXAMPLE_DATA, encryptionContext);
58+
final CryptoResult<byte[], KmsMasterKey> encryptResult = crypto.encryptData(keyProvider, EXAMPLE_DATA, encryptionContext);
6559
final byte[] ciphertext = encryptResult.getResult();
6660

6761
// 5. Decrypt the data
68-
final CryptoResult<byte[], KmsMasterKey> decryptResult = crypto.decryptData(masterKeyProvider, ciphertext);
69-
70-
// 6. Before verifying the plaintext, verify that the customer master key that
71-
// was used in the encryption operation was the one supplied to the master key provider.
72-
if (!decryptResult.getMasterKeyIds().get(0).equals(keyArn)) {
73-
throw new IllegalStateException("Wrong key ID!");
74-
}
62+
final CryptoResult<byte[], KmsMasterKey> decryptResult = crypto.decryptData(keyProvider, ciphertext);
7563

76-
// 7. Also, verify that the encryption context in the result contains the
64+
// 6. Verify that the encryption context in the result contains the
7765
// encryption context supplied to the encryptData method. Because the
7866
// SDK can add values to the encryption context, don't require that
7967
// the entire context matches.
@@ -82,7 +70,7 @@ static void encryptAndDecrypt(final String keyArn) {
8270
throw new IllegalStateException("Wrong Encryption Context!");
8371
}
8472

85-
// 8. Verify that the decrypted plaintext matches the original plaintext
73+
// 7. Verify that the decrypted plaintext matches the original plaintext
8674
assert Arrays.equals(decryptResult.getResult(), EXAMPLE_DATA);
8775
}
8876
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package com.amazonaws.crypto.examples;
5+
6+
import java.nio.charset.StandardCharsets;
7+
import java.util.Arrays;
8+
import java.util.Collections;
9+
import java.util.Map;
10+
11+
import com.amazonaws.encryptionsdk.AwsCrypto;
12+
import com.amazonaws.encryptionsdk.CryptoResult;
13+
import com.amazonaws.encryptionsdk.kms.KmsMasterKey;
14+
import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider;
15+
import com.amazonaws.encryptionsdk.CommitmentPolicy;
16+
import com.amazonaws.encryptionsdk.kms.DiscoveryFilter;
17+
18+
/**
19+
* <p>
20+
* Encrypts and then decrypts data using an AWS KMS customer master key in discovery mode.
21+
* Discovery mode is useful when you use an alias to identify a CMK when encrypting and the
22+
* underlying key ARN might vary in each AWS Region.
23+
* <p>
24+
* Arguments:
25+
* <ol>
26+
* <li>Key Name: An identifier for the AWS KMS customer master key (CMK) to use. For example,
27+
* a key ARN or a key alias.
28+
* For help finding the Amazon Resource Name (ARN) of your AWS KMS customer master
29+
* key (CMK), see 'Viewing Keys' at http://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html
30+
* <li>Partition: The partition of the AWS KMS customer master key, which is usually "aws."
31+
* A partition is a group of regions. The partition is the second element in the key ARN, e.g. "arn" in "aws:aws: ..."
32+
* <li>Account ID: The identifier for the account of the AWS KMS customer master key.
33+
* </ol>
34+
*/
35+
public class DiscoveryDecryptionExample {
36+
37+
private static final byte[] EXAMPLE_DATA = "Hello World".getBytes(StandardCharsets.UTF_8);
38+
39+
public static void main(final String[] args) {
40+
final String keyName = args[0];
41+
final String partition = args[1];
42+
final String accountId = args[2];
43+
44+
encryptAndDecrypt(keyName, partition, accountId);
45+
}
46+
47+
static void encryptAndDecrypt(final String keyName, final String partition, final String accountId) {
48+
// 1. Instantiate the SDK with a specific commitment policy.
49+
// ForbidEncryptAllowDecrypt is the only available policy in 1.7.0.
50+
final AwsCrypto crypto = AwsCrypto.builder().withCommitmentPolicy(CommitmentPolicy.ForbidEncryptAllowDecrypt).build();
51+
52+
// 2. Instantiate an AWS KMS master key provider for encryption.
53+
//
54+
// In strict mode (`buildStrict`), the AWS KMS master key provider encrypts and decrypts only by using the key
55+
// indicated by keyName.
56+
final KmsMasterKeyProvider encryptingKeyProvider = KmsMasterKeyProvider.builder().buildStrict(keyName);
57+
58+
// 3. 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+
// 4. Encrypt the data
68+
final CryptoResult<byte[], KmsMasterKey> encryptResult = crypto.encryptData(encryptingKeyProvider, EXAMPLE_DATA, encryptionContext);
69+
final byte[] ciphertext = encryptResult.getResult();
70+
71+
// 5. Instantiate a discovery filter for decrypting. This filter restricts what AWS KMS CMKs the
72+
// AWS KMS master key provider can use to those in a particular AWS partition and account.
73+
// You can create a similar filter with one partition and multiple AWS accounts.
74+
// This example only configures the filter with one account, but more may be specified
75+
// as long as they exist within the same partition.
76+
// This filter is not required for Discovery mode, but is a best practice.
77+
final DiscoveryFilter discoveryFilter = new DiscoveryFilter(partition, accountId);
78+
79+
// 6. Instantiate an AWS KMS master key provider for decryption in discovery mode (`buildDiscovery`) with a
80+
// Discovery Filter.
81+
//
82+
// In discovery mode, the AWS KMS master key provider attempts to decrypt only by using AWS KMS ARNs
83+
// indicated in the encrypted message.
84+
// By configuring the master key provider with a Discovery Filter, this master key provider
85+
// attempts to decrypt AWS KMS CMKs only in the configured partition and accounts.
86+
final KmsMasterKeyProvider decryptingKeyProvider = KmsMasterKeyProvider.builder().buildDiscovery(discoveryFilter);
87+
88+
// 7. Decrypt the data
89+
final CryptoResult<byte[], KmsMasterKey> decryptResult = crypto.decryptData(decryptingKeyProvider, ciphertext);
90+
91+
// 8. Verify that the encryption context in the result contains the
92+
// encryption context supplied to the encryptData method. Because the
93+
// SDK can add values to the encryption context, don't require that
94+
// the entire context matches.
95+
if (!encryptionContext.entrySet().stream()
96+
.allMatch(e -> e.getValue().equals(decryptResult.getEncryptionContext().get(e.getKey())))) {
97+
throw new IllegalStateException("Wrong Encryption Context!");
98+
}
99+
100+
// 9. Verify that the decrypted plaintext matches the original plaintext
101+
assert Arrays.equals(decryptResult.getResult(), EXAMPLE_DATA);
102+
}
103+
}

0 commit comments

Comments
 (0)