Skip to content

Commit 5258475

Browse files
Create builders for the standard keyrings
1 parent 3af73f0 commit 5258475

File tree

8 files changed

+342
-88
lines changed

8 files changed

+342
-88
lines changed

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

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@
2424
import com.amazonaws.encryptionsdk.EncryptRequest;
2525
import com.amazonaws.encryptionsdk.keyrings.Keyring;
2626
import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings;
27-
import com.amazonaws.encryptionsdk.kms.AwsKmsClientSupplier;
28-
29-
import static java.util.Collections.emptyList;
3027

3128
/**
3229
* <p>
@@ -53,17 +50,12 @@ static void encryptAndDecrypt(final String keyArn) {
5350
// 1. Instantiate the SDK
5451
final AwsCrypto crypto = new AwsCrypto();
5552

56-
// 2. Instantiate an AWS KMS Client Supplier. This example uses the default client supplier but you can
57-
// also configure the credentials provider, client configuration and other settings as necessary
58-
final AwsKmsClientSupplier clientSupplier = AwsKmsClientSupplier.builder().build();
59-
60-
// 3. Instantiate an AWS KMS Keyring, supplying the key ARN as the generator for generating a data key. While
53+
// 2. Instantiate an AWS KMS Keyring, supplying the key ARN as the generator for generating a data key. While
6154
// using a key ARN is a best practice, for encryption operations it is also acceptable to use a CMK alias or
62-
// an alias ARN. For this example, empty lists are provided for grant tokens and additional keys to encrypt
63-
// the data key with, but those can be supplied as necessary.
64-
final Keyring keyring = StandardKeyrings.awsKms(clientSupplier, emptyList(), emptyList(), keyArn);
55+
// an alias ARN.
56+
final Keyring keyring = StandardKeyrings.awsKms(keyArn);
6557

66-
// 4. Create an encryption context
58+
// 3. Create an encryption context
6759
//
6860
// Most encrypted data should have an associated encryption context
6961
// to protect integrity. This sample uses placeholder values.
@@ -72,28 +64,28 @@ static void encryptAndDecrypt(final String keyArn) {
7264
// blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management
7365
final Map<String, String> encryptionContext = Collections.singletonMap("ExampleContextKey", "ExampleContextValue");
7466

75-
// 5. Encrypt the data with the keyring and encryption context
67+
// 4. Encrypt the data with the keyring and encryption context
7668
final AwsCryptoResult<byte[]> encryptResult = crypto.encrypt(
7769
EncryptRequest.builder()
7870
.keyring(keyring)
7971
.encryptionContext(encryptionContext)
8072
.plaintext(EXAMPLE_DATA).build());
8173
final byte[] ciphertext = encryptResult.getResult();
8274

83-
// 6. Decrypt the data. The same keyring may be used to encrypt and decrypt, but for decryption
75+
// 5. Decrypt the data. The same keyring may be used to encrypt and decrypt, but for decryption
8476
// the key IDs must be in the key ARN format.
8577
final AwsCryptoResult<byte[]> decryptResult = crypto.decrypt(
8678
DecryptRequest.builder()
8779
.keyring(keyring)
8880
.ciphertext(ciphertext).build());
8981

90-
// 7. Before verifying the plaintext, inspect the Keyring Trace to verify that the CMK used
82+
// 6. Before verifying the plaintext, inspect the Keyring Trace to verify that the CMK used
9183
// to decrypt the encrypted data key was the CMK in the encryption keyring.
9284
if(!decryptResult.getKeyringTrace().getEntries().get(0).getKeyName().equals(keyArn)) {
9385
throw new IllegalStateException("Wrong key ID!");
9486
}
9587

96-
// 8. Also, verify that the encryption context in the result contains the
88+
// 7. Also, verify that the encryption context in the result contains the
9789
// encryption context supplied to the encryptData method. Because the
9890
// SDK can add values to the encryption context, don't require that
9991
// the entire context matches.
@@ -102,7 +94,7 @@ static void encryptAndDecrypt(final String keyArn) {
10294
throw new IllegalStateException("Wrong Encryption Context!");
10395
}
10496

105-
// 9. Verify that the decrypted plaintext matches the original plaintext
97+
// 8. Verify that the decrypted plaintext matches the original plaintext
10698
assert Arrays.equals(decryptResult.getResult(), EXAMPLE_DATA);
10799
}
108100
}

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

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import com.amazonaws.encryptionsdk.EncryptRequest;
1919
import com.amazonaws.encryptionsdk.keyrings.Keyring;
2020
import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings;
21-
import com.amazonaws.encryptionsdk.kms.AwsKmsClientSupplier;
2221

2322
import java.nio.charset.StandardCharsets;
2423
import java.security.GeneralSecurityException;
@@ -28,8 +27,6 @@
2827
import java.security.PublicKey;
2928
import java.util.Arrays;
3029

31-
import static java.util.Collections.emptyList;
32-
3330
/**
3431
* <p>
3532
* Encrypts data using both KMS and an asymmetric key pair.
@@ -75,7 +72,7 @@ static void escrowEncryptAndDecrypt(String kmsArn) throws GeneralSecurityExcepti
7572
byte[] standardDecryptedData = standardDecrypt(kmsArn, encryptedData);
7673

7774
// Decrypt the data using the escrowed RSA Key
78-
byte[] escrowedDecryptedData = escrowDecrypt(encryptedData, escrowKeyPair.getPublic(), escrowKeyPair.getPrivate());
75+
byte[] escrowedDecryptedData = escrowDecrypt(encryptedData, escrowKeyPair.getPrivate());
7976

8077
// Verify both decrypted data instances are the same as the original plaintext
8178
assert Arrays.equals(standardDecryptedData, EXAMPLE_DATA);
@@ -88,25 +85,23 @@ private static byte[] standardEncrypt(final String kmsArn, final PublicKey publi
8885
// 1. Instantiate the SDK
8986
final AwsCrypto crypto = new AwsCrypto();
9087

91-
// 2. Instantiate an AWS KMS Client Supplier. This example uses the default client supplier but you can
92-
// also configure the credentials provider, client configuration and other settings as necessary
93-
final AwsKmsClientSupplier clientSupplier = AwsKmsClientSupplier.builder().build();
94-
95-
// 3. Instantiate an AWS KMS Keyring, supplying the keyArn as the generator for generating a data key.
96-
// For this example, empty lists are provided for grant tokens and additional keys to encrypt the data
97-
// key with, but those can be supplied as necessary.
98-
final Keyring kmsKeyring = StandardKeyrings.awsKms(clientSupplier, emptyList(), emptyList(), kmsArn);
88+
// 2. Instantiate an AWS KMS Keyring, supplying the keyArn as the generator for generating a data key.
89+
final Keyring kmsKeyring = StandardKeyrings.awsKms(kmsArn);
9990

100-
// 4. Instantiate a RawRsaKeyring
91+
// 3. Instantiate a RawRsaKeyring
10192
// Because the user does not have access to the private escrow key,
10293
// they pass in "null" for the private key parameter.
103-
final Keyring rsaKeyring = StandardKeyrings.rawRsa("Escrow", "Escrow",
104-
publicEscrowKey, null, "RSA/ECB/OAEPWithSHA-512AndMGF1Padding");
105-
106-
// 5. Combine the providers into a single MultiKeyring
94+
final Keyring rsaKeyring = StandardKeyrings.rawRsa()
95+
.keyNamespace("Escrow")
96+
.keyName("Escrow")
97+
.publicKey(publicEscrowKey)
98+
.wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding")
99+
.build();
100+
101+
// 4. Combine the providers into a single MultiKeyring
107102
final Keyring keyring = StandardKeyrings.multi(kmsKeyring, rsaKeyring);
108103

109-
// 6. Encrypt the data with the keyring.
104+
// 5. Encrypt the data with the keyring.
110105
// To simplify the code, we omit the encryption context. Production code should always
111106
// use an encryption context. For an example, see the other SDK samples.
112107
return crypto.encrypt(EncryptRequest.builder()
@@ -121,14 +116,8 @@ private static byte[] standardDecrypt(final String kmsArn, final byte[] cipherTe
121116
// 1. Instantiate the SDK
122117
final AwsCrypto crypto = new AwsCrypto();
123118

124-
// 2. Instantiate an AWS KMS Client Supplier. This example uses the default client supplier but you can
125-
// also configure the credentials provider, client configuration and other settings as necessary
126-
final AwsKmsClientSupplier clientSupplier = AwsKmsClientSupplier.builder().build();
127-
128-
// 3. Instantiate an AWS KMS Keyring, supplying the keyArn as the generator for generating a data key.
129-
// For this example, empty lists are provided for grant tokens and additional keys to encrypt the data
130-
// key with, but those can be supplied as necessary.
131-
final Keyring kmsKeyring = StandardKeyrings.awsKms(clientSupplier, emptyList(), emptyList(), kmsArn);
119+
// 2. Instantiate an AWS KMS Keyring, supplying the keyArn as the generator for generating a data key.
120+
final Keyring kmsKeyring = StandardKeyrings.awsKms(kmsArn);
132121

133122
// 4. Decrypt the data with the keyring.
134123
// To simplify the code, we omit the encryption context. Production code should always
@@ -138,16 +127,20 @@ private static byte[] standardDecrypt(final String kmsArn, final byte[] cipherTe
138127
.ciphertext(cipherText).build()).getResult();
139128
}
140129

141-
private static byte[] escrowDecrypt(final byte[] cipherText, final PublicKey publicEscrowKey, final PrivateKey privateEscrowKey) {
130+
private static byte[] escrowDecrypt(final byte[] cipherText, final PrivateKey privateEscrowKey) {
142131
// You can decrypt the stream using only the private key.
143132
// This method does not call KMS.
144133

145134
// 1. Instantiate the SDK
146135
final AwsCrypto crypto = new AwsCrypto();
147136

148137
// 2. Instantiate a RawRsaKeyring using the escrowed private key
149-
final Keyring rsaKeyring = StandardKeyrings.rawRsa("Escrow", "Escrow",
150-
publicEscrowKey, privateEscrowKey, "RSA/ECB/OAEPWithSHA-512AndMGF1Padding");
138+
final Keyring rsaKeyring = StandardKeyrings.rawRsa()
139+
.keyNamespace("Escrow")
140+
.keyName("Escrow")
141+
.privateKey(privateEscrowKey)
142+
.wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding")
143+
.build();
151144

152145
// 3. Decrypt the data with the keyring
153146
// To simplify the code, we omit the encryption context. Production code should always

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,11 @@ static void encryptAndDecrypt(final File srcFile, final File encryptedFile, fina
6868
final SecretKey cryptoKey = retrieveEncryptionKey();
6969

7070
// 3. Instantiate a RawAesKeyring using the random key
71-
final Keyring keyring = StandardKeyrings.rawAes("Example", "RandomKey", cryptoKey);
71+
final Keyring keyring = StandardKeyrings.rawAes()
72+
.keyNamespace("Example")
73+
.keyName("RandomKey")
74+
.wrappingKey(cryptoKey)
75+
.build();
7276

7377
// 4. Create an encryption context
7478
//
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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.encryptionsdk.keyrings;
15+
16+
import com.amazonaws.encryptionsdk.kms.AwsKmsClientSupplier;
17+
import com.amazonaws.encryptionsdk.kms.DataKeyEncryptionDao;
18+
19+
import java.util.List;
20+
21+
public class AwsKmsKeyringBuilder {
22+
private AwsKmsClientSupplier awsKmsClientSupplier;
23+
private List<String> grantTokens;
24+
private List<String> keyIds;
25+
private String generatorKeyId;
26+
27+
AwsKmsKeyringBuilder() {
28+
// Use StandardKeyrings.awsKms() to instantiate
29+
}
30+
31+
/**
32+
* A function that returns an AWS KMS client that can make GenerateDataKey, Encrypt, and Decrypt calls in
33+
* a particular AWS region. If this is not supplied, the default AwsKmsClientSupplier will
34+
* be used. AwsKmsClientSupplier.builder() can be used to construct this type.
35+
*
36+
* @param awsKmsClientSupplier The AWS KMS client supplier
37+
* @return The AwsKmsKeyringBuilder, for method chaining
38+
*/
39+
public AwsKmsKeyringBuilder awsKmsClientSupplier(AwsKmsClientSupplier awsKmsClientSupplier) {
40+
this.awsKmsClientSupplier = awsKmsClientSupplier;
41+
return this;
42+
}
43+
44+
/**
45+
* A list of string grant tokens to be included in all KMS calls.
46+
*
47+
* @param grantTokens The list of grant tokens
48+
* @return The AwsKmsKeyringBuilder, for method chaining
49+
*/
50+
public AwsKmsKeyringBuilder grantTokens(List<String> grantTokens) {
51+
this.grantTokens = grantTokens;
52+
return this;
53+
}
54+
55+
/**
56+
* A list of strings identifying AWS KMS CMKs used for encrypting and decrypting data keys
57+
* in ARN, CMK Alias, or ARN Alias format.
58+
*
59+
* @param keyIds The list of AWS KMS CMKs
60+
* @return The AwsKmsKeyringBuilder, for method chaining
61+
*/
62+
public AwsKmsKeyringBuilder keyIds(List<String> keyIds) {
63+
this.keyIds = keyIds;
64+
return this;
65+
}
66+
67+
/**
68+
* A string that identifies a AWS KMS CMK responsible for generating a data key,
69+
* as well as encrypting and decrypting data keys in ARN, CMK Alias, or ARN Alias format.
70+
*
71+
* @param generatorKeyId The generator AWS KMS CMK
72+
* @return The AwsKmsKeyringBuilder, for method chaining
73+
*/
74+
public AwsKmsKeyringBuilder generatorKeyId(String generatorKeyId) {
75+
this.generatorKeyId = generatorKeyId;
76+
return this;
77+
}
78+
79+
/**
80+
* Constructs the {@link Keyring} instance.
81+
*
82+
* @return The {@link Keyring} instance
83+
*/
84+
public Keyring build() {
85+
if(awsKmsClientSupplier == null) {
86+
awsKmsClientSupplier = AwsKmsClientSupplier.builder().build();
87+
}
88+
return new AwsKmsKeyring(DataKeyEncryptionDao.awsKms(awsKmsClientSupplier, grantTokens), keyIds, generatorKeyId);
89+
}
90+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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.encryptionsdk.keyrings;
15+
16+
import javax.crypto.SecretKey;
17+
18+
public class RawAesKeyringBuilder {
19+
private String keyNamespace;
20+
private String keyName;
21+
private SecretKey wrappingKey;
22+
23+
RawAesKeyringBuilder() {
24+
// Use StandardKeyrings.rawAes() to instantiate
25+
}
26+
27+
/**
28+
* A value that, together with the key name, identifies the wrapping key (required).
29+
*
30+
* @param keyNamespace The key namespace
31+
* @return The RawAesKeyringBuilder, for method chaining
32+
*/
33+
public RawAesKeyringBuilder keyNamespace(String keyNamespace) {
34+
this.keyNamespace = keyNamespace;
35+
return this;
36+
}
37+
38+
/**
39+
* A value that, together with the key namespace, identifies the wrapping key (required).
40+
*
41+
* @param keyName The key name
42+
* @return The RawAesKeyringBuilder, for method chaining
43+
*/
44+
public RawAesKeyringBuilder keyName(String keyName) {
45+
this.keyName = keyName;
46+
return this;
47+
}
48+
49+
/**
50+
* The AES key input to AES-GCM to encrypt plaintext data keys (required).
51+
*
52+
* @param wrappingKey The wrapping key
53+
* @return The RawAesKeyringBuilder, for method chaining
54+
*/
55+
public RawAesKeyringBuilder wrappingKey(SecretKey wrappingKey) {
56+
this.wrappingKey = wrappingKey;
57+
return this;
58+
}
59+
60+
/**
61+
* Constructs the {@link Keyring} instance.
62+
*
63+
* @return The {@link Keyring} instance
64+
*/
65+
public Keyring build() {
66+
return new RawAesKeyring(keyNamespace, keyName, wrappingKey);
67+
}
68+
}

0 commit comments

Comments
 (0)