Using the Java client-side encryption library for DynamoDB
Our client-side encryption library was renamed to the AWS Database Encryption SDK. This developer guide still provides information on the DynamoDB Encryption Client. |
This topic explains some of the functions and helper classes in version 3.x of the Java client-side encryption library for DynamoDB.
For details about programming with the Java client-side encryption library for DynamoDB, see the Java examples, the Java examples
Item encryptors
At its core, the AWS Database Encryption SDK for DynamoDB is an item encryptor. You can use version 3.x of the Java client-side encryption library for DynamoDB to encrypt, sign, verify, and decrypt your DynamoDB table items in the following ways.
- The DynamoDB Enhanced Client
-
You can configure the DynamoDB Enhanced Client with the
DynamoDbEncryptionInterceptor
to automatically encrypt and sign items client-side with your DynamoDBPutItem
requests. With the DynamoDB Enhanced Client, you can define your attribute actions using an annotated data class. We recommend using the DynamoDB Enhanced Client whenever possible.The DynamoDB Enhanced Client does not support searchable encryption.
Note
The AWS Database Encryption SDK does not support annotations on nested attributes.
- The low-level DynamoDB API
-
You can configure the low-level DynamoDB API with the
DynamoDbEncryptionInterceptor
to automatically encrypt and sign items client-side with your DynamoDBPutItem
requests.You must use the low-level DynamoDB API to use searchable encryption.
- The lower-level
DynamoDbItemEncryptor
-
The lower-level
DynamoDbItemEncryptor
directly encrypts and signs or decrypts and verifies your table items without calling DynamoDB. It does not make DynamoDBPutItem
orGetItem
requests. For example, you can use the lower-levelDynamoDbItemEncryptor
to directly decrypt and verify a DynamoDB item that you have already retrieved.The lower-level
DynamoDbItemEncryptor
does not support searchable encryption.
Attribute actions in the AWS Database Encryption SDK for DynamoDB
Attribute actions determine which attribute values are encrypted and signed, which are only signed, which are signed and included in the encryption context, and which are ignored.
Note
To use the SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
cryptographic action,
you must use version 3.3 or later of the AWS Database Encryption SDK. Deploy the new version to all readers
before updating your data model to include
SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
.
If you use the low-level DynamoDB API or the lower-level
DynamoDbItemEncryptor
, you must manually define your attribute actions.
If you use the DynamoDB Enhanced Client you can either manually define your attribute
actions, or you can use an annotated data class to generate a
TableSchema
. To simplify the configuration process, we
recommend using an annotated data class. When you use an annotated data class, you only
have to model your object once.
Note
After you define your attribute actions, you must define which attributes are
excluded from the signatures. To make it easier to add new unsigned attributes in
the future, we recommend choosing a distinct prefix (such as ":
") to
identify your unsigned attributes. Include this prefix in the attribute name for all
attributes marked DO_NOTHING
as you define your DynamoDB schema and
attribute actions.
Use an annotated data class to specify your attribute actions with the
DynamoDB Enhanced Client and DynamoDbEncryptionInterceptor
. The
AWS Database Encryption SDK for DynamoDB uses the standard DynamoDB attribute annotations
Note
To use the SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
cryptographic action,
you must use version 3.3 or later of the AWS Database Encryption SDK. Deploy the new version to all readers
before updating your data model to include
SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
.
See SimpleClass.java
By default, primary key attributes are signed but not encrypted
(SIGN_ONLY
) and all other attributes are encrypted and signed
(ENCRYPT_AND_SIGN
). If you define any attributes
as SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
, then the partition and sort
attributes must also be SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
. To specify exceptions, use the encryption
annotations defined in the Java client-side encryption library for DynamoDB. For example, if you want a particular
attribute to only be signed use the @DynamoDbEncryptionSignOnly
annotation. If you want a particular attribute to be signed and included in the
encryption context, use the @DynamoDbEncryptionSignAndIncludeInEncryptionContext
.
If you want a particular attribute to be neither signed nor
encrypted (DO_NOTHING
), use the
@DynamoDbEncryptionDoNothing
annotation.
Note
The AWS Database Encryption SDK does not support annotations on nested attributes.
The following example shows the annotations used to define ENCRYPT_AND_SIGN
,
SIGN_ONLY
, and DO_NOTHING
attribute actions. For an example that
shows the annotations used to define SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
, see
SimpleClass4.java
@DynamoDbBean public class SimpleClass { private String partitionKey; private int sortKey; private String attribute1; private String attribute2; private String attribute3; @DynamoDbPartitionKey @DynamoDbAttribute(value = "partition_key") public String getPartitionKey() { return this.partitionKey; } public void setPartitionKey(String partitionKey) { this.partitionKey = partitionKey; } @DynamoDbSortKey @DynamoDbAttribute(value = "sort_key") public int getSortKey() { return this.sortKey; } public void setSortKey(int sortKey) { this.sortKey = sortKey; } public String getAttribute1() { return this.attribute1; } public void setAttribute1(String attribute1) { this.attribute1 = attribute1; } @DynamoDbEncryptionSignOnly public String getAttribute2() { return this.attribute2; } public void setAttribute2(String attribute2) { this.attribute2 = attribute2; } @DynamoDbEncryptionDoNothing public String getAttribute3() { return this.attribute3; } @DynamoDbAttribute(value = ":attribute3") public void setAttribute3(String attribute3) { this.attribute3 = attribute3; } }
Use your annotated data class to create the TableSchema
as shown
in the following snippet.
final TableSchema<
SimpleClass
> tableSchema = TableSchema.fromBean(SimpleClass
.class);
To manually specify attribute actions, create a Map
object in
which the name-value pairs represent attribute names and the specified
actions.
Specify ENCRYPT_AND_SIGN
to encrypt and sign an attribute.
Specify SIGN_ONLY
to sign, but not encrypt, an attribute.
Specify SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
to sign
an attribute and include it in the encryption context. You
cannot encrypt an attribute without also signing it. Specify
DO_NOTHING
to ignore an attribute.
The partition and sort attributes must be either SIGN_ONLY
or
SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
. If you define any attributes
as SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
, then the partition and sort
attributes must also be SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
.
Note
To use the SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
cryptographic action,
you must use version 3.3 or later of the AWS Database Encryption SDK. Deploy the new version to all readers
before updating your data model to include
SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
.
final Map<String, CryptoAction> attributeActionsOnEncrypt = new HashMap<>(); // The partition attribute must be signed attributeActionsOnEncrypt.put("partition_key", CryptoAction.SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT); // The sort attribute must be signed attributeActionsOnEncrypt.put("sort_key", CryptoAction.SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT); attributeActionsOnEncrypt.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN); attributeActionsOnEncrypt.put("attribute2", CryptoAction.SIGN_ONLY); attributeActionsOnEncrypt.put("attribute3", CryptoAction.SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT); attributeActionsOnEncrypt.put(":attribute4", CryptoAction.DO_NOTHING);
Encryption configuration in the AWS Database Encryption SDK for DynamoDB
When you use the AWS Database Encryption SDK, you must explicitly define an encryption configuration for your DynamoDB table. The values required in your encryption configuration depend on whether you defined your attribute actions manually or with an annotated data class.
The following snippet defines a DynamoDB table encryption configuration using the DynamoDB
Enhanced Client, TableSchema
, and allowed unsigned attributes defined by a
distinct prefix.
final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>(); tableConfigs.put(ddbTableName, DynamoDbEnhancedTableEncryptionConfig.builder() .logicalTableName(ddbTableName) .keyring(kmsKeyring) .allowedUnsignedAttributePrefix(unsignedAttrPrefix) .schemaOnEncrypt(tableSchema) // Optional: only required if you use beacons .search(SearchConfig.builder() .writeVersion(1) // MUST be 1 .versions(beaconVersions) .build()) .build());
- Logical table name
-
A logical table name for your DynamoDB table.
The logical table name is cryptographically bound to all data stored in the table to simplify DynamoDB restore operations. We strongly recommend specifying your DynamoDB table name as the logical table name when you first define your encryption configuration. You must always specify the same logical table name. For decryption to succeed, the logical table name must match the name specified on encryption. In the event that your DynamoDB table name changes after restoring your DynamoDB table from a backup, the logical table name ensures that the decrypt operation still recognizes the table.
- Allowed unsigned attributes
-
The attributes marked
DO_NOTHING
in your attribute actions.The allowed unsigned attributes tell the client which attributes are excluded from the signatures. The client assumes that all other attributes are included in the signature. Then, when decrypting a record, the client determines which attributes it needs to verify and which to ignore from the allowed unsigned attributes you specified. You cannot remove an attribute from your allowed unsigned attributes.
You can define the allowed unsigned attributes explicitly by creating an array that lists all of your
DO_NOTHING
attributes. You can also specify a distinct prefix when naming yourDO_NOTHING
attributes and use the prefix to tell the client which attributes are unsigned. We strongly recommend specifying a distinct prefix because it simplifies the process of adding a newDO_NOTHING
attribute in the future. For more information, see Updating your data model.If you do not specify a prefix for all
DO_NOTHING
attributes, you can configure anallowedUnsignedAttributes
array that explicitly lists all of the attributes that the client should expect to be unsigned when it encounters them on decryption. You should only explicitly define your allowed unsigned attributes if absolutely necessary. - Search Configuration (Optional)
-
The
SearchConfig
defines the beacon version.The
SearchConfig
must be specified to use searchable encryption or signed beacons. - Algorithm Suite (Optional)
-
The
algorithmSuiteId
defines which algorithm suite the AWS Database Encryption SDK uses.Unless you explicitly specify an alternative algorithm suite, the AWS Database Encryption SDK uses the default algorithm suite. The default algorithm suite uses the AES-GCM algorithm with key derivation, digital signatures, and key commitment. Although the default algorithm suite is likely to be suitable for most applications, you can choose an alternate algorithm suite. For example, some trust models would be satisfied by an algorithm suite without digital signatures. For information about the algorithm suites that the AWS Database Encryption SDK supports, see Supported algorithm suites in the AWS Database Encryption SDK.
To select the AES-GCM algorithm suite without ECDSA digital signatures, include the following snippet in your table encryption configuration.
.algorithmSuiteId( DBEAlgorithmSuiteId.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_SYMSIG_HMAC_SHA384)
Updating items with the AWS Database Encryption SDK
The AWS Database Encryption SDK does not support ddb:UpdateItem for
items that have been encrypted or signed. To update an encrypted or signed item, you
must use ddb:PutItem. When you
specify the same primary key as an existing item in your
PutItem
request, the new item completely replaces the existing item. You can also use
CLOBBER
to clear and replace all attributes on save after updating your items.
Decrypting signed sets
In versions 3.0.0 and 3.1.0 of the AWS Database Encryption SDK, if you define a set type attribute as
SIGN_ONLY
, the values of the set are canonicalized in the order
that they are provided. DynamoDB does not preserve the order of sets. As a
result, there is a chance that signature validation of the item that contains
the set will fail. Signature validation fails when the values of the set are
returned in a different order than they were provided to the AWS Database Encryption SDK, even if
the set attributes contain the same values.
Note
Versions 3.1.1 and later of the AWS Database Encryption SDK canonicalize the values of all set type attributes, so that the values are read in the same order that they were written to DynamoDB.
If signature validation fails, the decrypt operation fails and returns the following error message.
software.amazon.cryptography.dbencryptionsdk.structuredencryption.model.StructuredEncryptionException: No recipient tag matched. |
If you receive the above error message, and believe that the item you are
trying to decrypt includes a set that was signed using version 3.0.0 or 3.1.0, see
the DecryptWithPermute