Skip to content

Commit 282cd6f

Browse files
Merge head of master into keyring (#141)
*Description of changes:* Merge head of master into keyring By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. # Check any applicable: - [ ] Were any files moved? Moving files changes their URL, which breaks all hyperlinks to the files.
1 parent 9307933 commit 282cd6f

File tree

12 files changed

+588
-297
lines changed

12 files changed

+588
-297
lines changed

CHANGELOG.md

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

3-
## 1.6.1 -- Unreleased
3+
## 1.6.1 -- 2019-10-29
4+
5+
### Deprecation Warnings
6+
* Deprecated `AwsCrypto.encryptString()` and `AwsCrypto.decryptString()`.
7+
Replace your calls to these methods with calls to AwsCrypto.encryptData() and AwsCrypto.decryptData().
8+
Unlike the deprecated methods, these methods don't perform any Base64 encoding or decoding, so they are fully compatible with other language implementations of the AWS Encryption SDK.
9+
10+
If you need Base64 encoding or decoding for your application, you can add it outside of the AWS Encryption SDK.
11+
[PR #120](https://github.com/aws/aws-encryption-sdk-java/pull/120)
12+
13+
### Patches
14+
* Correctly validate version [PR #116](https://github.com/aws/aws-encryption-sdk-java/pull/116)
15+
* `ParsedCiphertext` now handles truncated input properly [PR #119](https://github.com/aws/aws-encryption-sdk-java/pull/119)
16+
417
### Maintenance
5-
* Add support for standard test vectors via `testVectorZip` system property.
6-
* No longer require use of BouncyCastle with RSA `JceMasterKey`s
7-
* No longer use BouncyCastle for Elliptic Curve key generation and point compression/decompression
18+
* Add support for standard test vectors via `testVectorZip` system property. [PR #127](https://github.com/aws/aws-encryption-sdk-java/pull/127)
19+
* Remove all explicit cryptographic dependencies on BouncyCastle. The AWS Encryption SDK for Java still uses Bouncy Castle for other tasks. PRs
20+
[#128](https://github.com/aws/aws-encryption-sdk-java/pull/128),
21+
[#129](https://github.com/aws/aws-encryption-sdk-java/pull/129),
22+
[#130](https://github.com/aws/aws-encryption-sdk-java/pull/130),
23+
[#131](https://github.com/aws/aws-encryption-sdk-java/pull/131),
24+
and [#132](https://github.com/aws/aws-encryption-sdk-java/pull/132).
825

926
## 1.6.0 -- 2019-05-31
1027

@@ -17,7 +34,7 @@
1734
## 1.5.0 -- 2019-05-30
1835

1936
### Minor Changes
20-
* Add dependency on Apache Commons Codec 1.12.
37+
* Added dependency on Apache Commons Codec 1.12.
2138
* Use org.apache.commons.codec.binary.Base64 instead of java.util.Base64 so
2239
that the SDK can be used on systems that do not have java.util.Base64 but
2340
support Java 8 language features.

README.md

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,31 @@ For more details about the design and architecture of the SDK, see the [official
99
### Required Prerequisites
1010
To use this SDK you must have:
1111

12-
* **A Java 8 development environment**
12+
* **A Java 8 or newer development environment**
1313

14-
If you do not have one, go to [Java SE Downloads](https://www.oracle.com/technetwork/java/javase/downloads/index.html) on the Oracle website, then download and install the Java SE Development Kit (JDK). Java 8 or higher is required.
14+
If you do not have one, we recommend [Amazon Corretto](https://aws.amazon.com/corretto/).
1515

1616
**Note:** If you use the Oracle JDK, you must also download and install the [Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html).
1717

18-
* **Bouncy Castle**
18+
* **Bouncy Castle** or **Bouncy Castle FIPS**
1919

20-
Bouncy Castle provides a cryptography API for Java. If you do not have Bouncy Castle, go to https://bouncycastle.org/latest_releases.html, then download the provider file that corresponds to your JDK. Or, you can pick it up from Maven:
20+
The AWS Encryption SDK for Java uses Bouncy Castle to serialize and deserialize cryptographic objects.
21+
It does not explicitly use Bouncy Castle (or any other [JCA Provider](https://docs.oracle.com/javase/8/docs/api/java/security/Provider.html)) for the underlying cryptography.
22+
Instead, it uses the platform default, which you can configure or override as documented in the
23+
[Java Cryptography Architecture (JCA) Reference Guide](https://docs.oracle.com/javase/9/security/java-cryptography-architecture-jca-reference-guide.htm#JSSEC-GUID-2BCFDD85-D533-4E6C-8CE9-29990DEB0190).
2124

22-
```xml
23-
<dependency>
24-
<groupId>org.bouncycastle</groupId>
25-
<artifactId>bcprov-ext-jdk15on</artifactId>
26-
<version>1.61</version>
27-
</dependency>
28-
```
25+
If you do not have Bouncy Castle, go to https://bouncycastle.org/latest_releases.html, then download the provider file that corresponds to your JDK.
26+
Or, you can pick it up from Maven (groupId: `org.bouncycastle`, artifactId: `bcprov-ext-jdk15on`).
27+
28+
Beginning in version 1.6.1,
29+
the AWS Encryption SDK also works with Bouncy Castle FIPS (groupId: `org.bouncycastle`, artifactId: `bc-fips`)
30+
as an alternative to non-FIPS Bouncy Castle.
31+
For help installing and configuring Bouncy Castle FIPS properly, see [BC FIPS documentation](https://www.bouncycastle.org/documentation.html),
32+
in particular, **User Guides** and **Security Policy**.
2933

3034
### Optional Prerequisites
3135

36+
#### AWS Integration
3237
You don't need an Amazon Web Services (AWS) account to use this SDK, but some of the [example code][examples] requires an AWS account, a customer master key (CMK) in AWS KMS, and the AWS SDK for Java.
3338

3439
* **To create an AWS account**, go to [Sign In or Create an AWS Account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) and then choose **I am a new user.** Follow the instructions to create an AWS account.
@@ -37,6 +42,10 @@ You don't need an Amazon Web Services (AWS) account to use this SDK, but some of
3742

3843
* **To download and install the AWS SDK for Java**, go to [Installing the AWS SDK for Java](https://docs.aws.amazon.com/AWSSdkDocsJava/latest/DeveloperGuide/java-dg-install-sdk.html) in the AWS SDK for Java documentation and then follow the instructions on that page.
3944

45+
#### Amazon Corretto Crypto Provider
46+
Many users find that the Amazon Corretto Crypto Provider (ACCP) significantly improves the performance of the AWS Encryption SDK.
47+
For help installing and using ACCP, see the [ACCP GitHub Respository](https://github.com/corretto/amazon-corretto-crypto-provider) .
48+
4049
### Download
4150

4251
You can get the latest release from Maven:
@@ -45,29 +54,10 @@ You can get the latest release from Maven:
4554
<dependency>
4655
<groupId>com.amazonaws</groupId>
4756
<artifactId>aws-encryption-sdk-java</artifactId>
48-
<version>1.6.0</version>
57+
<version>1.6.1</version>
4958
</dependency>
5059
```
5160

52-
Don't forget to enable the download of snapshot jars from Maven:
53-
54-
```xml
55-
<profiles>
56-
<profile>
57-
<id>allow-snapshots</id>
58-
<activation><activeByDefault>true</activeByDefault></activation>
59-
<repositories>
60-
<repository>
61-
<id>snapshots-repo</id>
62-
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
63-
<releases><enabled>false</enabled></releases>
64-
<snapshots><enabled>true</enabled></snapshots>
65-
</repository>
66-
</repositories>
67-
</profile>
68-
</profiles>
69-
```
70-
7161
### Get Started
7262

7363
The following code sample demonstrates how to get started:

pom.xml

Lines changed: 27 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.0</version>
7+
<version>1.6.1</version>
88
<packaging>jar</packaging>
99

1010
<name>aws-encryption-sdk-java</name>
@@ -118,6 +118,26 @@
118118
<source>8</source>
119119
</configuration>
120120
</plugin>
121+
122+
<plugin>
123+
<groupId>org.codehaus.mojo</groupId>
124+
<artifactId>build-helper-maven-plugin</artifactId>
125+
<version>3.0.0</version>
126+
<executions>
127+
<execution>
128+
<id>add-test-source</id>
129+
<phase>generate-test-sources</phase>
130+
<goals>
131+
<goal>add-test-source</goal>
132+
</goals>
133+
<configuration>
134+
<sources>
135+
<source>src/examples/java</source>
136+
</sources>
137+
</configuration>
138+
</execution>
139+
</executions>
140+
</plugin>
121141
</plugins>
122142
</build>
123143

@@ -145,6 +165,12 @@
145165
<goals>
146166
<goal>sign</goal>
147167
</goals>
168+
<configuration>
169+
<gpgArguments>
170+
<arg>--pinentry-mode</arg>
171+
<arg>loopback</arg>
172+
</gpgArguments>
173+
</configuration>
148174
</execution>
149175
</executions>
150176
</plugin>
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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+
*/
13+
14+
package com.amazonaws.crypto.examples;
15+
16+
import java.nio.charset.StandardCharsets;
17+
import java.util.Arrays;
18+
import java.util.Collections;
19+
import java.util.Map;
20+
21+
import com.amazonaws.encryptionsdk.AwsCrypto;
22+
import com.amazonaws.encryptionsdk.CryptoResult;
23+
import com.amazonaws.encryptionsdk.kms.KmsMasterKey;
24+
import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider;
25+
26+
/**
27+
* <p>
28+
* Encrypts and then decrypts data using an AWS KMS customer master key.
29+
*
30+
* <p>
31+
* Arguments:
32+
* <ol>
33+
* <li>Key ARN: For help finding the Amazon Resource Name (ARN) of your KMS customer master
34+
* key (CMK), see 'Viewing Keys' at http://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html
35+
* </ol>
36+
*/
37+
public class BasicEncryptionExample {
38+
39+
private static final byte[] EXAMPLE_DATA = "Hello World".getBytes(StandardCharsets.UTF_8);
40+
41+
public static void main(final String[] args) {
42+
final String keyArn = args[0];
43+
44+
encryptAndDecrypt(keyArn);
45+
}
46+
47+
static void encryptAndDecrypt(final String keyArn) {
48+
// 1. Instantiate the SDK
49+
final AwsCrypto crypto = new AwsCrypto();
50+
51+
// 2. Instantiate a KMS master key provider
52+
final KmsMasterKeyProvider masterKeyProvider = KmsMasterKeyProvider.builder().withKeysForEncryption(keyArn).build();
53+
54+
// 3. Create an encryption context
55+
//
56+
// Most encrypted data should have an associated encryption context
57+
// to protect integrity. This sample uses placeholder values.
58+
//
59+
// For more information see:
60+
// blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management
61+
final Map<String, String> encryptionContext = Collections.singletonMap("ExampleContextKey", "ExampleContextValue");
62+
63+
// 4. Encrypt the data
64+
final CryptoResult<byte[], KmsMasterKey> encryptResult = crypto.encryptData(masterKeyProvider, EXAMPLE_DATA, encryptionContext);
65+
final byte[] ciphertext = encryptResult.getResult();
66+
67+
// 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+
}
75+
76+
// 7. Also, verify that the encryption context in the result contains the
77+
// encryption context supplied to the encryptData method. Because the
78+
// SDK can add values to the encryption context, don't require that
79+
// the entire context matches.
80+
if (!encryptionContext.entrySet().stream()
81+
.allMatch(e -> e.getValue().equals(decryptResult.getEncryptionContext().get(e.getKey())))) {
82+
throw new IllegalStateException("Wrong Encryption Context!");
83+
}
84+
85+
// 8. Verify that the decrypted plaintext matches the original plaintext
86+
assert Arrays.equals(decryptResult.getResult(), EXAMPLE_DATA);
87+
}
88+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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+
*/
13+
14+
package com.amazonaws.encryptionsdk.internal;
15+
16+
import javax.crypto.Cipher;
17+
import javax.crypto.SecretKey;
18+
import javax.crypto.spec.GCMParameterSpec;
19+
import java.nio.ByteBuffer;
20+
import java.security.GeneralSecurityException;
21+
import java.security.InvalidKeyException;
22+
import java.security.Key;
23+
import java.util.Map;
24+
25+
/**
26+
* A JceKeyCipher based on the Advanced Encryption Standard in Galois/Counter Mode.
27+
*/
28+
class AesGcmJceKeyCipher extends JceKeyCipher {
29+
private static final int NONCE_LENGTH = 12;
30+
private static final int TAG_LENGTH = 128;
31+
private static final String TRANSFORMATION = "AES/GCM/NoPadding";
32+
private static final int SPEC_LENGTH = Integer.BYTES + Integer.BYTES + NONCE_LENGTH;
33+
34+
AesGcmJceKeyCipher(SecretKey key) {
35+
super(key, key);
36+
}
37+
38+
private static byte[] specToBytes(final GCMParameterSpec spec) {
39+
final byte[] nonce = spec.getIV();
40+
final byte[] result = new byte[SPEC_LENGTH];
41+
final ByteBuffer buffer = ByteBuffer.wrap(result);
42+
buffer.putInt(spec.getTLen());
43+
buffer.putInt(nonce.length);
44+
buffer.put(nonce);
45+
return result;
46+
}
47+
48+
private static GCMParameterSpec bytesToSpec(final byte[] data, final int offset) throws InvalidKeyException {
49+
if (data.length - offset != SPEC_LENGTH) {
50+
throw new InvalidKeyException("Algorithm specification was an invalid data size");
51+
}
52+
53+
final ByteBuffer buffer = ByteBuffer.wrap(data, offset, SPEC_LENGTH);
54+
final int tagLen = buffer.getInt();
55+
final int nonceLen = buffer.getInt();
56+
57+
if (tagLen != TAG_LENGTH) {
58+
throw new InvalidKeyException(String.format("Authentication tag length must be %s", TAG_LENGTH));
59+
}
60+
61+
if (nonceLen != NONCE_LENGTH) {
62+
throw new InvalidKeyException(String.format("Initialization vector (IV) length must be %s", NONCE_LENGTH));
63+
}
64+
65+
final byte[] nonce = new byte[nonceLen];
66+
buffer.get(nonce);
67+
68+
return new GCMParameterSpec(tagLen, nonce);
69+
}
70+
71+
@Override
72+
WrappingData buildWrappingCipher(final Key key, final Map<String, String> encryptionContext)
73+
throws GeneralSecurityException {
74+
final byte[] nonce = new byte[NONCE_LENGTH];
75+
Utils.getSecureRandom().nextBytes(nonce);
76+
final GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH, nonce);
77+
final Cipher cipher = Cipher.getInstance(TRANSFORMATION);
78+
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
79+
final byte[] aad = EncryptionContextSerializer.serialize(encryptionContext);
80+
cipher.updateAAD(aad);
81+
return new WrappingData(cipher, specToBytes(spec));
82+
}
83+
84+
@Override
85+
Cipher buildUnwrappingCipher(final Key key, final byte[] extraInfo, final int offset,
86+
final Map<String, String> encryptionContext) throws GeneralSecurityException {
87+
final GCMParameterSpec spec = bytesToSpec(extraInfo, offset);
88+
final Cipher cipher = Cipher.getInstance(TRANSFORMATION);
89+
cipher.init(Cipher.DECRYPT_MODE, key, spec);
90+
final byte[] aad = EncryptionContextSerializer.serialize(encryptionContext);
91+
cipher.updateAAD(aad);
92+
return cipher;
93+
}
94+
}

0 commit comments

Comments
 (0)