Skip to content

Commit 0e1e0cf

Browse files
SalusaSecondusmattsb42-aws
authored andcommitted
Add examples for direct use of DynamoDBEncryptor (#35)
1 parent e9b8945 commit 0e1e0cf

File tree

4 files changed

+406
-0
lines changed

4 files changed

+406
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package com.amazonaws.examples;
2+
3+
import java.nio.ByteBuffer;
4+
import java.security.GeneralSecurityException;
5+
import java.security.KeyPair;
6+
import java.security.KeyPairGenerator;
7+
import java.util.EnumSet;
8+
import java.util.HashMap;
9+
import java.util.Map;
10+
import java.util.Set;
11+
12+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.DynamoDBEncryptor;
13+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext;
14+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags;
15+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.WrappedMaterialsProvider;
16+
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
17+
18+
/**
19+
* Example showing use of RSA keys for encryption and signing.
20+
* For ease of the example, we create new random ones every time.
21+
*/
22+
public class AsymmetricEncryptedItem {
23+
24+
public static void main(String[] args) throws GeneralSecurityException {
25+
final String tableName = args[0];
26+
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
27+
keyGen.initialize(2048);
28+
// You should never use the same key for encryption and signing
29+
final KeyPair wrappingKeys = keyGen.generateKeyPair();
30+
final KeyPair signingKeys = keyGen.generateKeyPair();
31+
32+
encryptRecord(tableName, wrappingKeys, signingKeys);
33+
}
34+
35+
private static void encryptRecord(String tableName, KeyPair wrappingKeys, KeyPair signingKeys) throws GeneralSecurityException {
36+
// Sample record to be encrypted
37+
final String partitionKeyName = "partition_attribute";
38+
final String sortKeyName = "sort_attribute";
39+
final Map<String, AttributeValue> record = new HashMap<>();
40+
record.put(partitionKeyName, new AttributeValue().withS("is this"));
41+
record.put(sortKeyName, new AttributeValue().withN("55"));
42+
record.put("example", new AttributeValue().withS("data"));
43+
record.put("some numbers", new AttributeValue().withN("99"));
44+
record.put("and some binary", new AttributeValue().withB(ByteBuffer.wrap(new byte[]{0x00, 0x01, 0x02})));
45+
record.put("leave me", new AttributeValue().withS("alone")); // We want to ignore this attribute
46+
47+
// Set up our configuration and clients. All of this is thread-safe and can be reused across calls.
48+
// Provider Configuration
49+
final WrappedMaterialsProvider cmp = new WrappedMaterialsProvider(wrappingKeys.getPublic(), wrappingKeys.getPrivate(), signingKeys);
50+
// Encryptor creation
51+
final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmp);
52+
53+
// Information about the context of our data (normally just Table information)
54+
final EncryptionContext encryptionContext = new EncryptionContext.Builder()
55+
.withTableName(tableName)
56+
.withHashKeyName(partitionKeyName)
57+
.withRangeKeyName(sortKeyName)
58+
.build();
59+
60+
// Describe what actions need to be taken for each attribute
61+
final EnumSet<EncryptionFlags> signOnly = EnumSet.of(EncryptionFlags.SIGN);
62+
final EnumSet<EncryptionFlags> encryptAndSign = EnumSet.of(EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN);
63+
final Map<String, Set<EncryptionFlags>> actions = new HashMap<>();
64+
for (final String attributeName : record.keySet()) {
65+
switch (attributeName) {
66+
case partitionKeyName: // fall through
67+
case sortKeyName:
68+
// Partition and sort keys must not be encrypted but should be signed
69+
actions.put(attributeName, signOnly);
70+
break;
71+
case "leave me":
72+
// For this example, we are neither signing nor encrypting this field
73+
break;
74+
default:
75+
// We want to encrypt and sign everything else
76+
actions.put(attributeName, encryptAndSign);
77+
break;
78+
}
79+
}
80+
// End set-up
81+
82+
// Encrypt the plaintext record directly
83+
final Map<String, AttributeValue> encrypted_record = encryptor.encryptRecord(record, actions, encryptionContext);
84+
85+
// We could now put the encrypted item to DynamoDB just as we would any other item.
86+
// We're skipping it to to keep the example simpler.
87+
88+
System.out.println("Plaintext Record: " + record);
89+
System.out.println("Encrypted Record: " + encrypted_record);
90+
91+
// Decryption is identical. We'll pretend that we retrieved the record from DynamoDB.
92+
final Map<String, AttributeValue> decrypted_record = encryptor.decryptRecord(encrypted_record, actions, encryptionContext);
93+
System.out.println("Decrypted Record: " + decrypted_record);
94+
}
95+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.amazonaws.examples;
2+
3+
import java.nio.ByteBuffer;
4+
import java.security.GeneralSecurityException;
5+
import java.util.EnumSet;
6+
import java.util.HashMap;
7+
import java.util.Map;
8+
import java.util.Set;
9+
10+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.DynamoDBEncryptor;
11+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext;
12+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags;
13+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.DirectKmsMaterialProvider;
14+
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
15+
import com.amazonaws.services.kms.AWSKMS;
16+
import com.amazonaws.services.kms.AWSKMSClientBuilder;
17+
18+
/**
19+
* Example showing use of AWS KMS CMP with record encryption functions directly.
20+
*/
21+
public class AwsKmsEncryptedItem {
22+
23+
public static void main(String[] args) throws GeneralSecurityException {
24+
final String tableName = args[0];
25+
final String cmkArn = args[1];
26+
final String region = args[2];
27+
28+
encryptRecord(tableName, cmkArn, region);
29+
}
30+
31+
private static void encryptRecord(String tableName, String cmkArn, String region) throws GeneralSecurityException {
32+
// Sample record to be encrypted
33+
final String partitionKeyName = "partition_attribute";
34+
final String sortKeyName = "sort_attribute";
35+
final Map<String, AttributeValue> record = new HashMap<>();
36+
record.put(partitionKeyName, new AttributeValue().withS("is this"));
37+
record.put(sortKeyName, new AttributeValue().withN("55"));
38+
record.put("example", new AttributeValue().withS("data"));
39+
record.put("some numbers", new AttributeValue().withN("99"));
40+
record.put("and some binary", new AttributeValue().withB(ByteBuffer.wrap(new byte[]{0x00, 0x01, 0x02})));
41+
record.put("leave me", new AttributeValue().withS("alone")); // We want to ignore this attribute
42+
43+
// Set up our configuration and clients. All of this is thread-safe and can be reused across calls.
44+
// Provider Configuration
45+
final AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region).build();
46+
final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, cmkArn);
47+
// Encryptor creation
48+
final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmp);
49+
50+
// Information about the context of our data (normally just Table information)
51+
final EncryptionContext encryptionContext = new EncryptionContext.Builder()
52+
.withTableName(tableName)
53+
.withHashKeyName(partitionKeyName)
54+
.withRangeKeyName(sortKeyName)
55+
.build();
56+
57+
// Describe what actions need to be taken for each attribute
58+
final EnumSet<EncryptionFlags> signOnly = EnumSet.of(EncryptionFlags.SIGN);
59+
final EnumSet<EncryptionFlags> encryptAndSign = EnumSet.of(EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN);
60+
final Map<String, Set<EncryptionFlags>> actions = new HashMap<>();
61+
for (final String attributeName : record.keySet()) {
62+
switch (attributeName) {
63+
case partitionKeyName: // fall through
64+
case sortKeyName:
65+
// Partition and sort keys must not be encrypted but should be signed
66+
actions.put(attributeName, signOnly);
67+
break;
68+
case "leave me":
69+
// For this example, we are neither signing nor encrypting this field
70+
break;
71+
default:
72+
// We want to encrypt and sign everything else
73+
actions.put(attributeName, encryptAndSign);
74+
break;
75+
}
76+
}
77+
// End set-up
78+
79+
// Encrypt the plaintext record directly
80+
final Map<String, AttributeValue> encrypted_record = encryptor.encryptRecord(record, actions, encryptionContext);
81+
82+
// We could now put the encrypted item to DynamoDB just as we would any other item.
83+
// We're skipping it to to keep the example simpler.
84+
85+
System.out.println("Plaintext Record: " + record);
86+
System.out.println("Encrypted Record: " + encrypted_record);
87+
88+
// Decryption is identical. We'll pretend that we retrieved the record from DynamoDB.
89+
final Map<String, AttributeValue> decrypted_record = encryptor.decryptRecord(encrypted_record, actions, encryptionContext);
90+
System.out.println("Decrypted Record: " + decrypted_record);
91+
}
92+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package com.amazonaws.examples;
2+
3+
import java.nio.ByteBuffer;
4+
import java.security.GeneralSecurityException;
5+
import java.util.EnumSet;
6+
import java.util.HashMap;
7+
import java.util.Map;
8+
import java.util.Set;
9+
10+
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
11+
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
12+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.DynamoDBEncryptor;
13+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext;
14+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionFlags;
15+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.DirectKmsMaterialProvider;
16+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.MostRecentProvider;
17+
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.store.MetaStore;
18+
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
19+
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
20+
import com.amazonaws.services.kms.AWSKMS;
21+
import com.amazonaws.services.kms.AWSKMSClientBuilder;
22+
23+
/**
24+
* This demonstrates how to use the {@link MostRecentProvider} backed by a
25+
* {@link MetaStore} and the {@link DirectKmsMaterialProvider} to encrypt
26+
* your data. Before you can use this, you need to set up a table to hold the
27+
* intermediate keys.
28+
*/
29+
public class MostRecentEncryptedItem {
30+
31+
public static void main(String[] args) throws GeneralSecurityException {
32+
final String mode = args[0];
33+
final String region = args[1];
34+
final String tableName = args[2];
35+
final String keyTableName = args[3];
36+
final String cmkArn = args[4];
37+
final String materialName = args[5];
38+
39+
if (mode.equalsIgnoreCase("--setup")) {
40+
AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.standard().withRegion(region).build();
41+
MetaStore.createTable(ddb, keyTableName, new ProvisionedThroughput(1L, 1L));
42+
return;
43+
}
44+
45+
encryptRecord(tableName, keyTableName, region, cmkArn, materialName);
46+
}
47+
48+
private static void encryptRecord(String tableName, String keyTableName, String region, String cmkArn, String materialName) throws GeneralSecurityException {
49+
// Sample record to be encrypted
50+
final String partitionKeyName = "partition_attribute";
51+
final String sortKeyName = "sort_attribute";
52+
final Map<String, AttributeValue> record = new HashMap<>();
53+
record.put(partitionKeyName, new AttributeValue().withS("is this"));
54+
record.put(sortKeyName, new AttributeValue().withN("55"));
55+
record.put("example", new AttributeValue().withS("data"));
56+
record.put("some numbers", new AttributeValue().withN("99"));
57+
record.put("and some binary", new AttributeValue().withB(ByteBuffer.wrap(new byte[]{0x00, 0x01, 0x02})));
58+
record.put("leave me", new AttributeValue().withS("alone")); // We want to ignore this attribute
59+
60+
// Set up our configuration and clients. All of this is thread-safe and can be reused across calls.
61+
// Provider Configuration to protect the data keys
62+
final AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.standard().withRegion(region).build();
63+
final AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region).build();
64+
final DirectKmsMaterialProvider kmsProv = new DirectKmsMaterialProvider(kms, cmkArn);
65+
final DynamoDBEncryptor keyEncryptor = DynamoDBEncryptor.getInstance(kmsProv);
66+
final MetaStore metaStore = new MetaStore(ddb, keyTableName, keyEncryptor);
67+
//Provider configuration to protect the data
68+
final MostRecentProvider cmp = new MostRecentProvider(metaStore, materialName, 60_000);
69+
70+
// Encryptor creation
71+
final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmp);
72+
73+
// Information about the context of our data (normally just Table information)
74+
final EncryptionContext encryptionContext = new EncryptionContext.Builder()
75+
.withTableName(tableName)
76+
.withHashKeyName(partitionKeyName)
77+
.withRangeKeyName(sortKeyName)
78+
.build();
79+
80+
// Describe what actions need to be taken for each attribute
81+
final EnumSet<EncryptionFlags> signOnly = EnumSet.of(EncryptionFlags.SIGN);
82+
final EnumSet<EncryptionFlags> encryptAndSign = EnumSet.of(EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN);
83+
final Map<String, Set<EncryptionFlags>> actions = new HashMap<>();
84+
for (final String attributeName : record.keySet()) {
85+
switch (attributeName) {
86+
case partitionKeyName: // fall through
87+
case sortKeyName:
88+
// Partition and sort keys must not be encrypted but should be signed
89+
actions.put(attributeName, signOnly);
90+
break;
91+
case "leave me":
92+
// For this example, we are neither signing nor encrypting this field
93+
break;
94+
default:
95+
// We want to encrypt and sign everything else
96+
actions.put(attributeName, encryptAndSign);
97+
break;
98+
}
99+
}
100+
// End set-up
101+
102+
// Encrypt the plaintext record directly
103+
final Map<String, AttributeValue> encrypted_record = encryptor.encryptRecord(record, actions, encryptionContext);
104+
105+
// We could now put the encrypted item to DynamoDB just as we would any other item.
106+
// We're skipping it to to keep the example simpler.
107+
108+
System.out.println("Plaintext Record: " + record);
109+
System.out.println("Encrypted Record: " + encrypted_record);
110+
111+
// Decryption is identical. We'll pretend that we retrieved the record from DynamoDB.
112+
final Map<String, AttributeValue> decrypted_record = encryptor.decryptRecord(encrypted_record, actions, encryptionContext);
113+
System.out.println("Decrypted Record: " + decrypted_record);
114+
}
115+
}

0 commit comments

Comments
 (0)