Configuring the AWS Database Encryption SDK
Our client-side encryption library was renamed to the AWS Database Encryption SDK. This developer guide still provides information on the DynamoDB Encryption Client. |
The AWS Database Encryption SDK is designed to be easy to use. Although the AWS Database Encryption SDK has several configuration options, the default values are carefully chosen to be practical and secure for most applications. However, you might need to adjust your configuration to improve performance or include a custom feature in your design.
Topics
Selecting a programming language
The AWS Database Encryption SDK for DynamoDB is available in multiple programming languages. The language implementations are designed to be fully interoperable and to offer the same features, although they might be implemented in different ways. Typically, you use the library that is compatible with your application.
Selecting wrapping keys
The AWS Database Encryption SDK generates a unique symmetric data key to encrypt each field. You don't need to configure, manage, or use the data keys. The AWS Database Encryption SDK does it for you.
However, you must select one or more wrapping keys to encrypt each data key. The AWS Database Encryption SDK supports AWS Key Management Service (AWS KMS) symmetric encryption KMS keys and asymmetric RSA KMS keys. It also supports AES symmetric keys and RSA asymmetric keys that you provide in different sizes. You are responsible for the safety and durability of your wrapping keys, so we recommend that you use an encryption key in a hardware security module or a key infrastructure service, such as AWS KMS.
To specify your wrapping keys for encryption and decryption, you use a keyring. Depending on the type of keyring you use, you can specify one wrapping key or multiple wrapping keys of the same or different types. If you use multiple wrapping keys to wrap a data key, each wrapping key will encrypt a copy of the same data key. The encrypted data keys (one per wrapping key) are stored in the material description stored alongside the encrypted field. To decrypt the data, the AWS Database Encryption SDK must first use one of your wrapping keys to decrypt an encrypted data key.
We recommend using one of the AWS KMS keyrings whenever possible. The AWS Database Encryption SDK provides the AWS KMS keyring and the AWS KMS Hierarchical keyring, which reduces the number of calls made to AWS KMS. To specify an AWS KMS key in a keyring, use a supported AWS KMS key identifier. If you use the AWS KMS Hierarchical keyring, you must specify the key ARN. For details about the key identifiers for an AWS KMS key, see Key Identifiers in the AWS Key Management Service Developer Guide.
-
When you encrypt with an AWS KMS keyring, you can specify any valid key identifier (key ARN, alias name, alias ARN, or key ID) for a symmetric encryption KMS key. If you use an asymmetric RSA KMS key, you must specify the key ARN.
If you specify an alias name or alias ARN for a KMS key when encrypting, the AWS Database Encryption SDK saves the key ARN currently associated with that alias; it does not save the alias. Changes to the alias don't affect the KMS key used to decrypt your data keys.
-
By default, the AWS KMS keyring decrypts records in strict mode (where you specify particular KMS keys). You must use a key ARN to identify AWS KMS keys for decryption.
When you encrypt with an AWS KMS keyring, the AWS Database Encryption SDK stores the key ARN of the AWS KMS key in the material description with the encrypted data key. When decrypting in strict mode, the AWS Database Encryption SDK verifies that the same key ARN appears in the keyring before it attempts to use the wrapping key to decrypt the encrypted data key. If you use a different key identifier, the AWS Database Encryption SDK will not recognize or use the AWS KMS key, even if the identifiers refer to the same key.
-
When decrypting in discovery mode, you don't specify any wrapping keys. First, the AWS Database Encryption SDK attempts to decrypt the record with the key ARN stored in the material description. If that doesn't work, the AWS Database Encryption SDK asks AWS KMS to decrypt the record using the KMS key that encrypted it, regardless of who owns or has access to that KMS key.
To specify a raw AES key or a raw RSA key pair as a wrapping key in a keyring, you must specify a namespace and a name. When decrypting, you must use the exact same namespace and name for each raw wrapping key as you used when encrypting. If you use a different namespace or name, the AWS Database Encryption SDK will not recognize or use the wrapping key, even if the key material is the same.
Creating a discovery filter
When decrypting data encrypted with KMS keys, it's a best practice to decrypt in strict mode, that is, to limit the wrapping keys used to only those that you specify. However, if necessary, you can also decrypt in discovery mode, where you don't specify any wrapping keys. In this mode, AWS KMS can decrypt the encrypted data key using the KMS key that encrypted it, regardless of who owns or has access to that KMS key.
If you must decrypt in discovery mode, we recommend that you always use a discovery filter, which limits the KMS keys that can be used to those in a specified AWS account and partition. The discovery filter is optional, but it's a best practice.
Use the following table to determine the partition value for your discovery filter.
Region | Partition |
---|---|
AWS Regions | aws |
China Regions | aws-cn |
AWS GovCloud (US) Regions | aws-us-gov |
The following example shows how to create a discovery filter. Before using the code, replace the example values with valid values for your AWS account and partition.
Working with multitenant databases
With the AWS Database Encryption SDK, you can configure client-side encryption for databases with a shared schema by isolating each tenant with distinct encryption materials. When considering a multitenant database, take some time to review your security requirements and how multitenancy might impact them. For example, using a multitenant database might impact your ability to combine the AWS Database Encryption SDK with another server-side encryption solution.
If you have multiple users performing encrypt operations within your database, you can use one of the AWS KMS keyrings to provide each user with a distinct key to use in their cryptographic operations. Managing the data keys for a multitenant client-side encryption solution can be complicated. We recommend organizing your data by tenant whenever possible. If the tenant is identified by the primary key values (for example, the partition key in an Amazon DynamoDB table), then managing your keys is easier.
You can use the AWS KMS keyring to isolate each tenant with a distinct AWS KMS keyring and AWS KMS keys. Based on the volume of AWS KMS calls made per tenant, you might want to use the AWS KMS Hierarchical keyring to minimize your calls to AWS KMS. The AWS KMS Hierarchical keyring is a cryptographic materials caching solution that reduces the number of AWS KMS calls by using AWS KMS protected branch keys persisted in an Amazon DynamoDB table, and then locally caching branch key materials used in encrypt and decrypt operations. You must use the AWS KMS Hierarchical keyring to implement searchable encryption in your database.
Creating signed beacons
The AWS Database Encryption SDK uses standard beacons and
compound beacons to provide searchable encryption solutions that enable
you to search encrypted records without decrypting the entire database queried. However,
the AWS Database Encryption SDK also supports signed beacons that can be configured
entirely from plaintext signed fields. Signed beacons are a type of
compound beacon that index and perform complex queries on SIGN_ONLY
and
SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
fields.
For example, if you have a multitenant database, you might want to create a signed beacon that enables you to query your database for records encrypted by a specific tenant's key. For more information, see Querying beacons in a multitenant database.
You must use the AWS KMS Hierarchical keyring to create signed beacons.
To configure a signed beacon, provide the following values.
You can define your signed parts in locally or globally defined lists. We recommend defining your signed parts in a global list in the beacon version whenever possible. By defining signed parts globally, you can define each part once and then reuse the parts in multiple compound beacon configurations. If you only intend to use a signed part once, you can define it in a local list in the signed beacon configuration. You can reference both local and global parts in your constructor list.
If you define your signed parts lists globally, you must provide a list of constructor parts that identify all of the possible ways the signed beacon can assemble the fields in your beacon configuration.
Note
To define signed parts lists globally, you must use version 3.2 or later of the AWS Database Encryption SDK. Deploy the new version to all readers before defining any new parts globally.
You cannot update existing beacon configurations to define signed parts lists globally.
- Beacon name
-
The name you use when querying the beacon.
A signed beacon name cannot be the same name as an unencrypted field. No two beacons can have the same beacon name.
- Split character
-
The character used to separate the parts that make up your signed beacon.
The split character cannot appear in the plaintext values of any of the fields that the signed beacon is constructed from.
- Signed parts list
-
Identifies the signed fields included in the signed beacon.
Each part must include a name, source, and prefix. The source is the
SIGN_ONLY
orSIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT
field that the part identifies. The source must be a field name or an index referring to the value of a nested field. If your part name identifies the source, you can omit the source and the AWS Database Encryption SDK will automatically use the name as its source. We recommend specifying the source as the part name whenever possible. The prefix can be any string, but it must be unique. No two signed parts in a signed beacon can have the same prefix. We recommend using a short value that distinguishes the part from other parts served by the compound beacon.We recommend defining your signed parts globally whenever possible. You might consider defining a signed part locally if you only intend on using it in one compound beacon. A locally defined part cannot have the same prefix or name as a globally defined part.
- Constructor list (Optional)
-
Identifies the constructors that define the different ways that the signed parts can be assembled by the signed beacon.
If you do not specify a constructor list, the AWS Database Encryption SDK assembles the signed beacon with the following default constructor.
-
All signed parts in the order they were added to the signed parts list
-
All parts are required
- Constructors
-
Each constructor is an ordered list of constructor parts that defines one way that the signed beacon can be assembled. The constructor parts are joined together in the order they are added to the list, with each part separated by the specified split character.
Each constructor part names a signed part, and defines whether that part is required or optional within the constructor. For example, if you want to query a signed beacon on
Field1
,Field1.Field2
, andField1.Field2.Field3
, markField2
andField3
as optional and create one constructor.Each constructor must have at least one required part. We recommend making the first part in each constructor required so that you can use the
BEGINS_WITH
operator in your queries.A constructor succeeds if all its required parts are present in the record. When you write a new record, the signed beacon uses the constructor list to determine if the beacon can be assembled from the values provided. It attempts to assemble the beacon in the order that the constructors were added to the constructor list, and it uses the first constructor that succeeds. If no constructors succeed, the beacon is not written to the record.
All readers and writers should specify the same order of constructors to ensure that their query results are correct.
Use the following procedures to specify your own constructor list.
-
Create a constructor part for each signed part to define whether or not that part is required.
The constructor part name must be the name of the signed field.
The following example demonstrates how to create constructor part for one signed field.
-
Create a constructor for each possible way that the signed beacon can be assembled using the constructor parts you created in Step 1.
For example, if you want to query on
Field1.Field2.Field3
andField4.Field2.Field3
, then you must create two constructors.Field1
andField4
can both be required because they are defined in two separate constructors. -
Create a constructor list that includes all of the constructors that you created in Step 2.
-
Specify the
constructorList
when you create your signed beacon.
-