AWS Encryption SDK
Developer Guide
AWS Encryption SDK: Developer Guide
Copyright © Amazon Web Services, Inc. and/or its affiliates. All rights reserved.
Amazon's trademarks and trade dress may not be used in connection with any product or service that is not Amazon's, in any manner that is likely to cause confusion among customers, or in any manner that disparages or discredits Amazon. All other trademarks not owned by Amazon are the property of their respective owners, who may or may not be affiliated with, connected to, or sponsored by Amazon.
Table of Contents
What is the AWS Encryption SDK? ... 1
Developed in open-source repositories ... 2
Compatibility with encryption libraries and services ... 2
Support and maintenance ... 2
Learning more ... 3
Sending feedback ... 4
Concepts ... 4
Envelope encryption ... 5
Data key ... 6
Wrapping key ... 7
Keyrings and master key providers ... 7
Encryption context ... 8
Encrypted message ... 8
Algorithm suite ... 9
Cryptographic materials manager ... 9
Symmetric and asymmetric encryption ... 9
Key commitment ... 10
Commitment policy ... 11
Digital signatures ... 12
How the SDK works ... 12
How the AWS Encryption SDK encrypts data ... 12
How the AWS Encryption SDK decrypts an encrypted message ... 13
Supported algorithm suites ... 13
Recommended: AES-GCM with key derivation, signing, and key commitment ... 14
Other supported algorithm suites ... 14
Getting started ... 16
Best practices ... 17
Configuring the SDK ... 20
Select a programming language ... 20
Select wrapping keys ... 20
Use multi-Region AWS KMS keys ... 21
Choosing an algorithm suite ... 33
Limit encrypted data keys ... 38
Work with streaming data ... 40
Cache data keys ... 40
Using keyrings ... 41
How keyrings work ... 41
Keyring compatibility ... 43
Choosing a keyring ... 44
AWS KMS keyrings ... 44
Raw AES keyrings ... 52
Raw RSA keyrings ... 53
Multi-keyrings ... 56
Programming languages ... 59
C ... 59
Install and build ... 60
Using the C SDK ... 60
Examples ... 63
Java ... 68
Prerequisites ... 68
Installation ... 69
Example code ... 69
JavaScript ... 77
Compatibility ... 78
Installation ... 79
Modules ... 80
Examples ... 82
Python ... 86
Prerequisites ... 86
Installation ... 87
Example code ... 87
Command line interface ... 94
Installing the CLI ... 95
How to use the CLI ... 97
Examples ... 107
Syntax and parameter reference ... 123
Versions ... 131
Data key caching ... 134
How to use data key caching ... 134
Using data key caching: Step-by-step ... 135
Data key caching example: Encrypt a string ... 140
Setting cache security thresholds ... 150
Data key caching details ... 151
How data key caching works ... 152
Creating a cryptographic materials cache ... 154
Creating a caching cryptographic materials manager ... 154
What is in a data key cache entry? ... 155
Encryption context: How to select cache entries ... 155
Is my application using cached data keys? ... 156
Data key caching example ... 156
Local cache results ... 157
Example code ... 158
AWS CloudFormation template ... 165
Versions of the AWS Encryption SDK ... 176
Versions earlier than 1.7.x ... 177
Version 1.7.x ... 177
Version 1.8.x ... 179
Version 1.9.x ... 179
Version 2.0.x ... 179
Version 2.1.x ... 180
Version 2.2.x ... 180
Version 2.3.x ... 181
Version 3.0.x ... 181
Migrating to versions 2.0.x and later ... 182
How to migrate and deploy ... 185
Stage 1: Update your application to version 1.7.x ... 185
Stage 2: Update your application to version 2.0.x ... 186
Updating AWS KMS master key providers ... 186
Migrating to strict mode ... 187
Migrating to discovery mode ... 189
Updating AWS KMS keyrings ... 191
Setting your commitment policy ... 193
How to set your commitment policy ... 194
Troubleshooting migration to versions 2.0.x and later ... 198
Deprecated or removed objects ... 198
Configuration conflict: Commitment policy and algorithm suite ... 198
Configuration conflict: Commitment policy and ciphertext ... 199
Key commitment validation failed ... 199
Other encryption failures ... 200
Other decryption failures ... 200
Rollback considerations ... 200
Frequently asked questions ... 201
Reference ... 204
Message format reference ... 204
Header structure ... 205
Body structure ... 210
Footer structure ... 213
Message format examples ... 213
Framed data (message format version 1) ... 214
Framed data (message format version 2) ... 216
Non-framed data (message format version 1) ... 218
Body AAD reference ... 220
Algorithms reference ... 221
Initialization vector reference ... 224
Document history ... 225
Recent updates ... 225
Earlier updates ... 226
What is the AWS Encryption SDK?
The AWS Encryption SDK is a client-side encryption library designed to make it easy for everyone to encrypt and decrypt data using industry standards and best practices. It enables you to focus on the core functionality of your application, rather than on how to best encrypt and decrypt your data. The AWS Encryption SDK is provided free of charge under the Apache 2.0 license.
The AWS Encryption SDK answers questions like the following for you:
• Which encryption algorithm should I use?
• How, or in which mode, should I use that algorithm?
• How do I generate the encryption key?
• How do I protect the encryption key, and where should I store it?
• How can I make my encrypted data portable?
• How do I ensure that the intended recipient can read my encrypted data?
• How can I ensure my encrypted data is not modified between the time it is written and when it is read?
With the AWS Encryption SDK, you define a master key provider (p. 7) (Java or Python) or a
keyring (p. 7) (C or JavaScript) that determines which master keys you use to protect your data. Then you encrypt and decrypt your data using straightforward methods provided by the AWS Encryption SDK.
The AWS Encryption SDK does the rest.
Without the AWS Encryption SDK, you might spend more effort on building an encryption solution than on the core functionality of your application. The AWS Encryption SDK answers these questions by providing the following things.
A default implementation that adheres to cryptography best practices
By default, the AWS Encryption SDK generates a unique data key for each data object that it encrypts. This follows the cryptography best practice of using unique data keys for each encryption operation.
The AWS Encryption SDK encrypts your data using a secure, authenticated, symmetric key algorithm.
For more information, see the section called “Supported algorithm suites” (p. 13).
A framework for protecting data keys with master keys
The AWS Encryption SDK protects the data keys that encrypt your data by encrypting them under one or more master keys. By providing a framework to encrypt data keys with more than one master key, the AWS Encryption SDK helps make your encrypted data portable.
For example, you can encrypt data under multiple AWS KMS keys, each in a different AWS Region.
Then you can copy the encrypted data to any of the regions and use the AWS KMS key in that region to decrypt it. You can also encrypt data under an AWS KMS key in AWS KMS and a master key in an on-premises HSM, enabling you to later decrypt the data even if one of the options is unavailable.
A formatted message that stores encrypted data keys with the encrypted data
The AWS Encryption SDK stores the encrypted data and encrypted data key together in an encrypted message (p. 8) that uses a defined data format. This means you don't need to keep track of or protect the data keys that encrypt your data because the AWS Encryption SDK does it for you.
Some language implementations of the AWS Encryption SDK require an AWS SDK, but the AWS
Encryption SDK doesn't require an AWS account and it doesn't depend on any AWS service. You need an AWS account only if you choose to use AWS KMS keys to protect your data.
Developed in open-source repositories
The AWS Encryption SDK is developed in open-source repositories on GitHub. You can use these repositories to view the code, read and submit issues, and find information that is specific to your language implementation.
• AWS Encryption SDK for C — aws-encryption-sdk-c
• AWS Encryption CLI — aws-encryption-sdk-cli
• AWS Encryption SDK for Java — aws-encryption-sdk-java
• AWS Encryption SDK for JavaScript — aws-encryption-sdk-javascript
• AWS Encryption SDK for Python — aws-encryption-sdk-python
Compatibility with encryption libraries and services
The AWS Encryption SDK is supported in several programming languages (p. 59). All language implementations are interoperable. You can encrypt with one language implementation and decrypt with another. Interoperability might be subject to language constraints. If so, these constraints are described in the topic about the language implementation. Also, when encrypting and decrypting, you must use compatible keyrings, or master keys and master key providers. For details, see the section called “Keyring compatibility” (p. 43).
However, the AWS Encryption SDK cannot interoperate with other libraries. Because each library returns encrypted data in a different format, you cannot encrypt with one library and decrypt with another.
DynamoDB Encryption Client and Amazon S3 client-side encryption
The AWS Encryption SDK cannot decrypt data encrypted by the DynamoDB Encryption Client or Amazon S3 client-side encryption. And these libraries cannot decrypt the encrypted message (p. 8) the AWS Encryption SDK returns.
AWS Key Management Service (AWS KMS)
The AWS Encryption SDK can use AWS KMS keys and data keys to protect your data. For example, you can configure the AWS Encryption SDK to encrypt your data under one or more AWS KMS keys in your AWS account. However, you must use the AWS Encryption SDK to decrypt that data.
The AWS Encryption SDK cannot decrypt the ciphertext that the AWS KMS Encrypt or ReEncrypt operations return. Similarly, the AWS KMS Decrypt operation cannot decrypt the encrypted message (p. 8) the AWS Encryption SDK returns.
The AWS Encryption SDK supports only symmetric AWS KMS keys. You cannot use an asymmetric AWS KMS key for encryption or signing in the AWS Encryption SDK. The AWS Encryption SDK generates its own ECDSA signing keys for algorithm suites (p. 13) that sign messages.
For help deciding which library or service to use, see How to Choose an Encryption Tool or Service in AWS Cryptographic Services and Tools.
Support and maintenance
The AWS Encryption SDK uses the same maintenance policy that the AWS SDK and Tools use, including its versioning and life-cycle phases. As a best practice (p. 17), we recommend that you use the
latest available version of the AWS Encryption SDK for your programming language, and upgrade as new versions are released. When a version requires significant changes, such as the upgrade from AWS Encryption SDK versions earlier than 1.7.x to versions 2.0.x and later, we provide detailed instructions (p. 182) to help you.
Each programming language implementation of the AWS Encryption SDK is developed in a separate open-source GitHub repository. The life-cycle and support phase of each version is likely to vary among repositories. For example, a given version of the AWS Encryption SDK might be in the general availability (full support) phase in one programming language, but the end-of-support phase in a different programming language. We recommend that you use a fully supported version whenever possible and avoid versions that are no longer supported.
To find the life-cycle phase of AWS Encryption SDK versions for your programming language, see the SUPPORT_POLICY.rst file in each AWS Encryption SDK repository.
• AWS Encryption SDK for C — SUPPORT_POLICY.rst
• AWS Encryption CLI — SUPPORT_POLICY.rst
• AWS Encryption SDK for Java — SUPPORT_POLICY.rst
• AWS Encryption SDK for JavaScript — SUPPORT_POLICY.rst
• AWS Encryption SDK for Python — SUPPORT_POLICY.rst
For more information, see Versions of the AWS Encryption SDK (p. 176) and AWS SDKs and Tools maintenance policy in the AWS SDKs and Tools Reference Guide.
Learning more
For more information about the AWS Encryption SDK and client-side encryption, try these sources.
• To get started quickly, see Getting started (p. 16).
• For best practice guidelines, see Best practices for the AWS Encryption SDK (p. 17).
• For information about how this SDK works, see How the SDK works (p. 12).
• For help with the terms and concepts used in this SDK, see Concepts in the AWS Encryption SDK (p. 4).
• For detailed technical information, see the Reference (p. 204).
• For the technical specification for the AWS Encryption SDK, see the AWS Encryption SDK Specification in GitHub.
• For answers to your questions about using the AWS Encryption SDK, read and post on the AWS Crypto Tools Discussion Forum.
For information about implementations of the AWS Encryption SDK in different programming languages.
• C: See AWS Encryption SDK for C (p. 59), the AWS Encryption SDK C documentation, and the aws- encryption-sdk-c repository on GitHub.
• Command Line Interface: See AWS Encryption SDK command line interface (p. 94), Read the Docs for the AWS Encryption CLI, and the aws-encryption-sdk-cli repository on GitHub.
• Java: See AWS Encryption SDK for Java (p. 68), the AWS Encryption SDK Javadoc, and the aws- encryption-sdk-java repository on GitHub.
JavaScript: See the section called “JavaScript” (p. 77) and the aws-encryption-sdk-javascript repository on GitHub.
• Python: See AWS Encryption SDK for Python (p. 86), the AWS Encryption SDK Python documentation, and the aws-encryption-sdk-python repository on GitHub.
Sending feedback
We welcome your feedback! If you have a question or comment, or an issue to report, please use the following resources.
• If you discover a potential security vulnerability in the AWS Encryption SDK, please notify AWS security. Do not create a public GitHub issue.
• To provide feedback on the AWS Encryption SDK, file an issue in the GitHub repository for the programming language you are using.
• To provide feedback on this documentation, use the Feedback link on this page. You can also file an issue or contribute to aws-encryption-sdk-docs, the open-source repository for this documentation on GitHub.
Concepts in the AWS Encryption SDK
This section introduces the concepts used in the AWS Encryption SDK, and provides a glossary and reference. It's designed to help you understand how the AWS Encryption SDK works and the terms we use to describe it.
Need help?
• Learn how the AWS Encryption SDK uses envelope encryption (p. 5) to protect your data.
• Learn about the elements of envelope encryption: the data keys (p. 6) that protect your data and the wrapping keys (p. 7) that protect your data keys.
• Learn about the keyrings (p. 7) and master key providers (p. 7) that determine which wrapping keys you use.
• Learn about the encryption context (p. 8) that adds integrity to your encryption process. It's optional, but it's a best practice that we recommend.
• Learn about the encrypted message (p. 8) that the encryption methods return.
• Then you're ready to use the AWS Encryption SDK in your preferred programming language (p. 59).
Topics
• Envelope encryption (p. 5)
• Data key (p. 6)
• Wrapping key (p. 7)
• Keyrings and master key providers (p. 7)
• Encryption context (p. 8)
• Encrypted message (p. 8)
• Algorithm suite (p. 9)
• Cryptographic materials manager (p. 9)
• Symmetric and asymmetric encryption (p. 9)
• Key commitment (p. 10)
• Commitment policy (p. 11)
• Digital signatures (p. 12)
Envelope encryption
The security of your encrypted data depends in part on protecting the data key that can decrypt it.
One accepted best practice for protecting the data key is to encrypt it. To do this, you need another encryption key, known as a key-encryption key or wrapping key (p. 7). The practice of using a wrapping key to encrypt data keys is known as envelope encryption.
Protecting data keys
The AWS Encryption SDK encrypts each message with a unique data key. Then it encrypts the data key under the wrapping key you specify. It stores the encrypted data key with the encrypted data in the encrypted message that it returns.
To specify your wrapping key, you use a keyring (p. 7) or master key provider (p. 7).
Encrypting the same data under multiple wrapping keys
You can encrypt the data key under multiple wrapping keys. You might want to provide different wrapping keys for different users, or wrapping keys of different types, or in different locations.
Each of the wrapping keys encrypts the same data key. The AWS Encryption SDK stores all of the encrypted data keys with the encrypted data in the encrypted message.
To decrypt the data, you need to provide a wrapping key that can decrypt one of the encrypted data keys.
Combining the strengths of multiple algorithms
To encrypt your data, by default, the AWS Encryption SDK uses a sophisticated algorithm suite (p. 13) with AES-GCM symmetric encryption, a key derivation function (HKDF), and signing.
To encrypt the data key, you can specify a symmetric or asymmetric encryption algorithm (p. 9) appropriate to your wrapping key.
In general, symmetric key encryption algorithms are faster and produce smaller ciphertexts than asymmetric or public key encryption. But public key algorithms provide inherent separation of roles and easier key management. To combine the strengths of each, you can encrypt your data with symmetric key encryption, and then encrypt the data key with public key encryption.
Data key
A data key is an encryption key that the AWS Encryption SDK uses to encrypt your data. Each data key is a byte array that conforms to the requirements for cryptographic keys. Unless you're using data key caching (p. 134), the AWS Encryption SDK uses a unique data key to encrypt each message.
You don't need to specify, generate, implement, extend, protect or use data keys. The AWS Encryption SDK does that work for you when you call the encrypt and decrypt operations.
To protect your data keys, the AWS Encryption SDK encrypts them under one or more key-encryption keys known as wrapping keys (p. 7) or master keys. After the AWS Encryption SDK uses your
plaintext data keys to encrypt your data, it removes them from memory as soon as possible. Then it stores the encrypted data keys with the encrypted data in the encrypted message (p. 8) that the encrypt operations return. For details, see the section called “How the SDK works” (p. 12).
TipIn the AWS Encryption SDK, we distinguish data keys from data encryption keys. Several of the supported algorithm suites (p. 9), including the default suite, use a key derivation function that prevents the data key from hitting its cryptographic limits. The key derivation function takes the data key as input and returns a data encryption key that is actually used to encrypt the data. For this reason, we often say that data is encrypted "under" a data key rather than "by" the data key.
Each encrypted data key includes metadata, including the identifier of the wrapping key that encrypted it. This metadata makes it easier for the AWS Encryption SDK to identify valid wrapping keys when decrypting.
Wrapping key
A wrapping key (or master key) is a key-encryption key that the AWS Encryption SDK uses to encrypt the data key (p. 6) that encrypts your data. Each plaintext data key can be encrypted under one or more wrapping keys. You determine which wrapping keys are used to protect your data when you configure a keyring (p. 7) or master key provider (p. 7).
NoteWrapping key refers to the keys in a keyring or master key provider. Master key is typically associated with the MasterKey class that you instantiate when you use a master key provider.
The AWS Encryption SDK supports several commonly used wrapping keys, such as AWS Key Management Service (AWS KMS) symmetric AWS KMS keys, raw AES-GCM (Advanced Encryption Standard/Galois Counter Mode) keys, and raw RSA keys. You can also extend or implement your own wrapping keys.
When you use envelope encryption, you need to protect your wrapping keys from unauthorized access.
You can do this in any of the following ways:
• Use a web service designed for this purpose, such as AWS Key Management Service (AWS KMS).
• Use a hardware security module (HSM) such as those offered by AWS CloudHSM.
• Use other key management tools and services.
If you don't have a key management system, we recommend AWS KMS. The AWS Encryption SDK integrates with AWS KMS to help you protect and use your wrapping keys. However, the AWS Encryption SDK does not require AWS or any AWS service.
Keyrings and master key providers
To specify the wrapping keys you use for encryption and decryption, you use a keyring (C and JavaScript) or a master key provider (Java, Python, CLI). You can use the keyrings and master key providers that the AWS Encryption SDK provides or design your own implementations. The AWS Encryption SDK provides keyrings and master key providers that are compatible with each other subject to language constraints.
For details, see Keyring compatibility (p. 43).
A keyring generates, encrypts, and decrypts data keys. When you define a keyring, you can specify the wrapping keys (p. 7) that encrypt your data keys. Most keyrings specify at least one wrapping key or a service that provides and protects wrapping keys. You can also define a keyring with no wrapping keys or a more complex keyring with additional configuration options. For help choosing and using the keyrings that the AWS Encryption SDK defines, see Using keyrings (p. 41). Keyrings are supported in C and JavaScript.
A master key provider is an alternative to a keyring. The master key provider returns the wrapping keys (or master keys) you specify. Each master key is associated with one master key provider, but a master key provider typically provides multiple master keys. Master key providers are supported in Java, Python, and the AWS Encryption CLI.
You must specify a keyring (or master key provider) for encryption. You can specify the same keyring (or master key provider), or a different one, for decryption. When encrypting, the AWS Encryption SDK uses all of the wrapping keys you specify to encrypt the data key. When decrypting, the AWS Encryption SDK uses only the wrapping keys you specify to decrypt an encrypted data key. Specifying wrapping keys for decryption is optional, but it's a AWS Encryption SDK best practice (p. 17).
For details about specifying wrapping keys, see Select wrapping keys (p. 20).
Encryption context
To improve the security of your cryptographic operations, include an encryption context in all requests to encrypt data. Using an encryption context is optional, but it is a cryptographic best practice that we recommend.
An encryption context is a set of name-value pairs that contain arbitrary, non-secret additional authenticated data. The encryption context can contain any data you choose, but it typically consists of data that is useful in logging and tracking, such as data about the file type, purpose, or ownership.
When you encrypt data, the encryption context is cryptographically bound to the encrypted data so that the same encryption context is required to decrypt the data. The AWS Encryption SDK includes the encryption context in plaintext in the header of the encrypted message (p. 8) that it returns.
The encryption context that the AWS Encryption SDK uses consists of the encryption context that you specify and a public key pair that the cryptographic materials manager (p. 9) (CMM) adds.
Specifically, whenever you use an encryption algorithm with signing (p. 221), the CMM adds a name- value pair to the encryption context that consists of a reserved name, aws-crypto-public-key, and a value that represents the public verification key. The aws-crypto-public-key name in the encryption context is reserved by the AWS Encryption SDK and cannot be used as a name in any other pair in the encryption context. For details, see AAD (p. 206) in the Message Format Reference.
The following example encryption context consists of two encryption context pairs specified in the request and the public key pair that the CMM adds.
"Purpose"="Test", "Department"="IT", aws-crypto-public-key=<public key>
To decrypt the data, you pass in the encrypted message. Because the AWS Encryption SDK can extract the encryption context from the encrypted message header, you are not required to provide the encryption context separately. However, the encryption context can help you to confirm that you are decrypting the correct encrypted message.
• In the AWS Encryption SDK Command Line Interface (p. 94) (CLI), if you provide an encryption
context in a decrypt command, the CLI verifies that the values are present in the encryption context of the encrypted message before it returns the plaintext data.
• In other languages, the decrypt response includes the encryption context and the plaintext data. The decrypt function in your application should always verify that the encryption context in the decrypt response includes the encryption context in the encrypt request (or a subset) before it returns the plaintext data.
When choosing an encryption context, remember that it is not a secret. The encryption context is displayed in plaintext in the header of the encrypted message (p. 8) that the AWS Encryption SDK returns. If you are using AWS Key Management Service, the encryption context also might appear in plaintext in audit records and logs, such as AWS CloudTrail.
For examples of submitting and verifying an encryption context in your code, see the examples for your preferred programming language (p. 59).
Encrypted message
When you encrypt data with the AWS Encryption SDK, it returns an encrypted message.
An encrypted message is a portable formatted data structure (p. 204) that includes the encrypted data along with encrypted copies of the data keys, the algorithm ID, and, optionally, an encryption context (p. 8) and a digital signature (p. 12). Encrypt operations in the AWS Encryption SDK return an encrypted message and decrypt operations take an encrypted message as input.
Combining the encrypted data and its encrypted data keys streamlines the decryption operation and frees you from having to store and manage encrypted data keys independently of the data that they encrypt.
For technical information about the encrypted message, see Encrypted Message Format (p. 204).
Algorithm suite
The AWS Encryption SDK uses an algorithm suite to encrypt and sign the data in the encrypted message (p. 8) that the encrypt and decrypt operations return. The AWS Encryption SDK supports several algorithm suites (p. 13). All of the supported suites use Advanced Encryption Standard (AES) as the primary algorithm, and combine it with other algorithms and values.
The AWS Encryption SDK establishes a recommended algorithm suite as the default for all encryption operations. The default might change as standards and best practices improve. You can specify an alternate algorithm suite in requests to encrypt data or when creating a cryptographic materials manager (CMM) (p. 9), but unless an alternate is required for your situation, it is best to
use the default. The current default is AES-GCM with an HMAC-based extract-and-expand key derivation function (HKDF), key commitment (p. 10), an Elliptic Curve Digital Signature Algorithm (ECDSA) (p. 12) signature, and a 256-bit encryption key.
If your application requires high performance and the users who are encrypting data and those who are decrypting data are equally trusted, you might consider specifying an algorithm suite without a digital signature. However, we strongly recommend an algorithm suite that includes key commitment and a key derivation function. Algorithm suites without these features are supported only for backward compatibility.
Cryptographic materials manager
The cryptographic materials manager (CMM) assembles the cryptographic materials that are used to encrypt and decrypt data. The cryptographic materials include plaintext and encrypted data keys, and an optional message signing key. You never interact with the CMM directly. The encryption and decryption methods handle it for you.
You can use the default CMM or the caching CMM (p. 134) that the AWS Encryption SDK provides, or write a custom CMM. And you can specify a CMM, but it's not required. When you specify a keyring or master key provider, the AWS Encryption SDK creates a default CMM for you. The default CMM gets the encryption or decryption materials from the keyring or master key provider that you specify. This might involve a call to a cryptographic service, such as AWS Key Management Service(AWS KMS).
Because the CMM acts as a liaison between the AWS Encryption SDK and a keyring (or master key provider), it is an ideal point for customization and extension, such as support for policy enforcement and caching. The AWS Encryption SDK provides a caching CMM to support data key caching. (p. 134)
Symmetric and asymmetric encryption
Symmetric encryption uses the same key to encrypt and decrypt data.
Asymmetric encryption uses a mathematically related data key pair. One key in the pair encrypts the data;
only the other key in the pair can decrypt the data. For details, see Cryptographic algorithms in the AWS Cryptographic Services and Tools Guide.
The AWS Encryption SDK uses envelope encryption (p. 5). It encrypts your data with a symmetric data key. It encrypts the symmetric data key with one or more symmetric or asymmetric wrapping keys.
It returns an encrypted message (p. 8) that includes the encrypted data and at least one encrypted copy of the data key.
Encrypting your data (symmetric encryption)
To encrypt your data, the AWS Encryption SDK uses a symmetric data key (p. 6) and an algorithm suite (p. 9) that includes a symmetric encryption algorithm. To decrypt the data, the AWS Encryption SDK uses the same data key and the same algorithm suite.
Encrypting your data key (symmetric or asymmetric encryption)
The keyring (p. 7) or master key provider (p. 7) that you supply to an encrypt and decrypt operation determines how the symmetric data key is encrypted and decrypted. You can choose a keyring or master key provider that uses symmetric encryption, such as a AWS KMS keyring, or one that uses asymmetric encryption, such as a raw RSA keyring or JceMasterKey.
Key commitment
The AWS Encryption SDK supports key commitment (sometimes known as robustness), a security
property that guarantees that each ciphertext can be decrypted only to a single plaintext. To do this, key commitment guarantees that only the data key that encrypted your message will be used to decrypt it.
Encrypting and decrypting with key commitment is an AWS Encryption SDK best practice (p. 17).
Most modern symmetric ciphers (including AES) encrypt a plaintext under a single secret key, such as the unique data key (p. 6) that the AWS Encryption SDK uses to encrypt each plaintext message.
Decrypting this data with the same data key returns a plaintext that is identical to the original.
Decrypting with a different key will usually fail. However, it's possible to decrypt a ciphertext under two different keys. In rare cases, it is feasible to find a key that can decrypt a few bytes of ciphertext into a different, but still intelligible, plaintext.
The AWS Encryption SDK always encrypts each plaintext message under one unique data key. It might encrypt that data key under multiple wrapping keys (or master keys), but the wrapping keys always encrypt the same data key. Nonetheless, a sophisticated, manually crafted encrypted message (p. 8) might actually contain different data keys, each encrypted by a different wrapping key. For example, if one user decrypts the encrypted message it returns 0x0 (false) while another user decrypting the same encrypted message gets 0x1 (true).
To prevent this scenario, the AWS Encryption SDK supports key commitment when encrypting and decrypting. When the AWS Encryption SDK encrypts a message with key commitment, it
cryptographically binds the unique data key that produced the ciphertext to the key commitment string, a non-secret data key identifier. Then it stores key commitment string in the metadata of the encrypted message. When it decrypts a message with key commitment, the AWS Encryption SDK verifies that the data key is the one and only key for that encrypted message. If data key verification fails, the decrypt operation fails.
Support for key commitment is introduced in version 1.7.x, which can decrypt messages with key
commitment, but won't encrypt with key commitment. You can use this version to fully deploy the ability to decrypt ciphertext with key commitment. Version 2.0.x includes full support for key commitment.
By default, it encrypts and decrypts only with key commitment. This is an ideal configuration for applications that don't need to decrypt ciphertext encrypted by earlier versions of the AWS Encryption SDK.
Although encrypting and decrypting with key commitment is a best practice, we let you decide when it's used, and let you adjust the pace at which you adopt it. Beginning in version 1.7.x, AWS Encryption SDK supports a commitment policy (p. 11) that sets the default algorithm suite (p. 13) and limits the
algorithm suites that may be used. This policy determines whether your data is encrypted and decrypted with key commitment.
Key commitment results in a slightly larger (+ 30 bytes) encrypted message (p. 204) and takes more time to process. If your application is very sensitive to size or performance, you might choose to opt out of key commitment. But do so only if you must.
For more information about migrating to versions 1.7.x and 2.0.x, including their key commitment features, see Migrating to versions 2.0.x and later (p. 182). For technical information about key commitment, see the section called “Algorithms reference” (p. 221) and the section called “Message format reference” (p. 204).
Commitment policy
A commitment policy is a configuration setting that determines whether your application encrypts and decrypts with key commitment (p. 10). Encrypting and decrypting with key commitment is an AWS Encryption SDK best practice (p. 17).
Commitment policy has three values.
Note
You might have to scroll horizontally or vertically to see the entire table.
Commitment policy values
Value Encrypts with key
commitment Encrypts without
key commitment Decrypts with key
commitment Decrypts without key commitment ForbidEncryptAllowDecrypt
RequireEncryptAllowDecrypt
RequireEncryptRequireDecrypt
The commitment policy setting is introduced in AWS Encryption SDK version 1.7.x. It's valid in all supported programming languages (p. 59).
• ForbidEncryptAllowDecrypt decrypts with or without key commitment, but it won't encrypt with key commitment. This is the only valid value for commitment policy in version 1.7.x and it is used for all encrypt and decrypt operations. It's designed to prepare all hosts running your application to decrypt with key commitment before they ever encounter a ciphertext encrypted with key commitment.
• RequireEncryptAllowDecrypt always encrypts with key commitment. It can decrypt with or without key commitment. This value, introduced in version 2.0.x, lets you start encrypting with key commitment, but still decrypt legacy ciphertexts without key commitment.
• RequireEncryptRequireDecrypt encrypts and decrypts only with key commitment. This value is the default for version 2.0.x. Use this value when you are certain that all of your ciphertexts are encrypted with key commitment.
The commitment policy setting determines which algorithm suites you can use. Beginning in version 1.7.x, the AWS Encryption SDK supports algorithm suites (p. 13) for key commitment; with and
without signing. If you specify an algorithm suite that conflicts with your commitment policy, the AWS Encryption SDK returns an error.
For help setting your commitment policy, see Setting your commitment policy (p. 193).
Digital signatures
To ensure the integrity of a digital message as it goes between systems, you can apply a digital signature to the message. Digital signatures are always asymmetric. You use your private key to create the
signature, and append it to the original message. Your recipient uses a public key to verify that the message has not been modified since you signed it.
The AWS Encryption SDK encrypts your data using an authenticated encryption algorithm, AES-GCM, and the decryption process verifies the integrity and authenticity of an encrypted message without using a digital signature. But because AES-GCM uses symmetric keys, anyone who can decrypt the data key used to decrypt the ciphertext could also manually create a new encrypted ciphertext, causing a potential security concern. For instance, if you use an AWS KMS key as a wrapping key, this means that it is possible for a user with KMS Decrypt permissions to create encrypted ciphertexts without calling KMS Encrypt.
To avoid this issue, the AWS Encryption SDK supports adding an Elliptic Curve Digital Signature
Algorithm (ECDSA) signature to the end of encrypted messages. When a signing algorithm suite is used, the AWS Encryption SDK generates a temporary private key and public key pair for each encrypted message. The AWS Encryption SDK stores the public key in the encryption context of the data key and discards the private key, and no one can create another signature that verifies with the public key.
Because the algorithm binds the public key to the encrypted data key as additional authenticated data in the message header, a user who can only decrypt messages cannot alter the public key.
Signature verification adds a significant performance cost on decryption. If the users encrypting data and the users decrypting data are equally trusted, consider using an algorithm suite that does not include signing.
How the AWS Encryption SDK works
The workflows in this section explain how the AWS Encryption SDK encrypts data and decrypts encrypted messages (p. 8). These workflows describes the basic process using the default features.
For details about defining and using custom components, see the GitHub repository for each supported language implementation (p. 59).
The AWS Encryption SDK uses envelope encryption to protect your data. Each message is encrypted under a unique data key. Then the data key is encrypted by the wrapping keys you specify. To decrypt the encrypted message, the AWS Encryption SDK uses the wrapping keys you specify to decrypt at least one encrypted data key. Then it can decrypt the ciphertext and return a plaintext message.
Need help with the terminology we use in the AWS Encryption SDK? See the section called
“Concepts” (p. 4).
How the AWS Encryption SDK encrypts data
The AWS Encryption SDK provides methods that encrypt strings, byte arrays, and byte streams. For code examples, see the Examples topic in each Programming languages (p. 59) section.
1. Create a keyring (p. 41) (or master key provider (p. 7)) that specifies the wrapping keys that protect your data.
2. Pass the keyring and plaintext data to an encryption method. We recommend that you pass in an optional, non-secret encryption context (p. 8).
3. The encryption method asks the keyring for encryption materials. The keyring returns unique data encryption keys for the message: one plaintext data key and one copy of that data key encrypted by the each of the specified wrapping keys.
4. The encryption method uses the plaintext data key to encrypt the data, and then discards the plaintext data key. If you provide an encryption context (an AWS Encryption SDK best practice (p. 17)), the encryption method cryptographically binds the encryption context to the encrypted data.
5. The encryption method returns an encrypted message (p. 8) that contains the encrypted data, the encrypted data keys, and other metadata, including the encryption context, if you used one.
How the AWS Encryption SDK decrypts an encrypted message
The AWS Encryption SDK provides methods that decrypt the encrypted message (p. 8) and return plaintext. For code examples, see the Examples topic in each Programming languages (p. 59) section.
The keyring (p. 41) (or master key provider (p. 7)) that decrypts the encrypted message must be
compatible with the one used to encrypt the message. One of its wrapping keys must be able to decrypt an encrypted data key in the encrypted message. For information about compatibility with keyrings and master key providers, see the section called “Keyring compatibility” (p. 43).
1. Create a keyring or master key provider with wrapping keys that can decrypt your data. You can use the same keyring that you provided to the encryption method or a different one.
2. Pass the encrypted message (p. 8) and the keyring to a decryption method.
3. The decryption method asks the keyring or master key provider to decrypt one of the encrypted data keys in the encrypted message. It passes in information from the encrypted message, including the encrypted data keys.
4. The keyring uses its wrapping keys to decrypt one of the encrypted data keys. If it's successful, the response includes the plaintext data key. If none of the wrapping keys specified by the keyring or master key provider can decrypt an encrypted data key, the decrypt call fails.
5. The decryption method uses the plaintext data key to decrypt the data, discards the plaintext data key, and returns the plaintext data.
Supported algorithm suites in the AWS Encryption SDK
An algorithm suite is a collection of cryptographic algorithms and related values. Cryptographic systems use the algorithm implementation to generate the ciphertext message.
The AWS Encryption SDK algorithm suite uses the Advanced Encryption Standard (AES) algorithm in Galois/Counter Mode (GCM), known as AES-GCM, to encrypt raw data. The AWS Encryption SDK supports 256-bit, 192-bit, and 128-bit encryption keys. The length of the initialization vector (IV) is always 12 bytes. The length of the authentication tag is always 16 bytes.
By default, the AWS Encryption SDK uses an algorithm suite with AES-GCM with an HMAC-based extract- and-expand key derivation function (HKDF), signing, and a 256-bit encryption key. If the commitment policy (p. 11) requires key commitment (p. 10), the AWS Encryption SDK selects an algorithm suite that also supports key commitment; otherwise, it selects an algorithm suite with key derivation and signing, but not key commitment.
Recommended: AES-GCM with key derivation, signing, and key commitment
The AWS Encryption SDK recommends an algorithm suite that derives an AES-GCM encryption key by supplying a 256-bit data encryption key to the HMAC-based extract-and-expand key derivation function (HKDF). The AWS Encryption SDK adds an Elliptic Curve Digital Signature Algorithm (ECDSA) signature. To support key commitment (p. 10), this algorithm suite also derives a key commitment string – a non-secret data-key identifier – that is stored in the metadata of the encrypted message. This key commitment string is also derived through HKDF using a procedure similar to deriving the data encryption key.
AWS Encryption SDK Algorithm Suite Encryption
algorithm Data encryption key length (in bits)
Key derivation
algorithm Signature
algorithm Key commitment
AES-GCM 256 HKDF with
SHA-384 ECDSA with P-384
and SHA-384 HKDF with SHA-512
The HKDF helps you avoid accidental reuse of a data encryption key and reduces the risk of overusing a data key.
For signing, this algorithm suite uses ECDSA with a cryptographic hash function algorithm (SHA-384).
ECDSA is used by default, even when it is not specified by the policy for the underlying master key.
Message signing (p. 12) verifies the message sender was authorized to encrypt messages and provides non-repudiation. It is particularly useful when the authorization policy for a master key allows one set of users to encrypt data and a different set of users to decrypt data.
Algorithm suites with key commitment ensure that each ciphertext decrypts to only one plaintext.
They do this by validating the identity of the data key used as input to the encryption algorithm. When encrypting, these algorithm suites derive a key commitment string. Before decrypting, they validate that the data key matches the key commitment string. If it does not, the decrypt call fails.
Other supported algorithm suites
The AWS Encryption SDK supports the following alternate algorithm suites for backward compatibility.
In general, we do not recommend these algorithm suites. However, we recognize that signing can hinder performance significantly, so we offer a key committing suite with key derivation for those cases. For applications that must make more significant performance tradeoffs, we continue to offer suites that lack signing, key commitment, and key derivation.
AES-GCM without key commitment
Algorithm suites without key commitment do not validate the data key before decrypting. As a result, these algorithm suites might decrypt a single ciphertext into different plaintext messages.
However, because algorithm suites with key commitment produce a slightly larger (+30 bytes) encrypted message (p. 204) and take longer to process, they might not be the best choice for every application.
The AWS Encryption SDK supports an algorithm suite with key derivation, key commitment, signing, and one with key derivation and key commitment, but not signing. We do not recommend using an algorithm suite without key commitment. If you must, we recommend an algorithm suite with key derivation and key commitment, but not signing. However, if your application performance profile supports using an algorithm suite, using an algorithm suite with key commitment, key derivation, and signing is a best practice.
AES-GCM without signing
Algorithm suites without signing lack the ECDSA signature that provides authenticity and non- repudiation. Use these suites only when the users who encrypt data and those who decrypt data are equally trusted.
When using an algorithm suite without signing, we recommend that you choose one with key derivation and key commitment.
AES-GCM without key derivation
Algorithm suites without key derivation use the data encryption key as the AES-GCM encryption key, instead of using a key derivation function to derive a unique key. We discourage using this suite to generate ciphertext, but the AWS Encryption SDK supports it for compatibility reasons.
For more information about how these suites are represented and used in the library, see the section called “Algorithms reference” (p. 221).
Getting started with the AWS Encryption SDK
To use the AWS Encryption SDK, you need to configure keyring (p. 7) or master key provider (p. 7) with encryption keys. If you don't have a key infrastructure, we recommend using AWS Key Management Service (AWS KMS). Many of the code examples in the AWS Encryption SDK require an AWS KMS key.
To interact with AWS KMS, the AWS Encryption SDK requires the AWS SDK for your preferred programming language, such as the AWS SDK for Java 1.x, the AWS SDK for Python (Boto), the AWS SDK for JavaScript, or the AWS SDK for C++, which you use with the AWS Encryption SDK for C. The AWS Encryption SDK client library works with the AWS SDKs to support master keys stored in AWS KMS.
To prepare to use the AWS Encryption SDK with AWS KMS
1. Create an AWS account. To learn how, see How do I create and activate a new Amazon Web Services account? in the AWS Knowledge Center.
2. Create a symmetric encryption AWS KMS key. For help, see Creating Keys in the AWS Key Management Service Developer Guide.
TipTo use the AWS KMS key programmatically, you will need the key ID or Amazon Resource Name (ARN) of the AWS KMS key. For help finding the ID or ARN of an AWS KMS key, see Finding the Key ID and ARN in the AWS Key Management Service Developer Guide.
3. Create an IAM user with an access key. To learn how, see Creating IAM Users in the IAM User Guide.
When you create the user, for Access type, choose Programmatic access. After you create the user, choose Download.csv to save the AWS access key that represents your user credentials. Store the file in a secure location.
We recommend that you use AWS Identity and Access Management (IAM) access keys instead of AWS (root) account access keys. IAM lets you securely control access to AWS services and resources in your AWS account. For detailed best practice guidance, see Best Practices for Managing AWS Access Keys.
The Download.csv file contains an AWS access key ID and a secret access key that represents the AWS credentials of the user that you created. When you write code without using an AWS SDK, you use your access key to sign your requests to AWS. The signature assures AWS that the request came from you unchanged. However, when you use an AWS SDK, such as the AWS SDK for Java, the SDK signs all requests to AWS for you.
4. Set your AWS credentials using the instructions in the AWS SDK for Java, AWS SDK for JavaScript, AWS SDK for Python (Boto) or AWS SDK for C++ (for C), and the AWS access key in the
Download.csv file that you downloaded in step 3.
This procedure allows AWS SDKs to sign requests to AWS for you. Code samples in the AWS Encryption SDK that interact with AWS KMS assume that you have completed this step.
5. Download and install the AWS Encryption SDK. To learn how, see the installation instructions for the programming language (p. 59) that you want to use.
Best practices for the AWS Encryption SDK
The AWS Encryption SDK is designed to make it easy for you to protect your data using industry standards and best practices. While many best practices are selected for you in default values, some practices are optional but recommended whenever it's practical.
Use the latest version
When you start using the AWS Encryption SDK, use the latest version offered in your preferred programming language (p. 59). If you've been using the AWS Encryption SDK, upgrade to each latest version as soon as possible. This assures that you're using the recommended configuration and taking advantage of new security properties to protect your data. For details about supported versions, including guidance for migration and deployment, see Support and maintenance (p. 2) and Versions of the AWS Encryption SDK (p. 176).
If a new version deprecates elements in your code, replace them as soon as you can. Deprecation warnings and code comments typically recommend a good alternative.
To make significant upgrades easier and less prone to error, we occasionally provide a temporary or transitional release. Use these releases, and their accompanying documentation, to assure that you can upgrade your application without disrupting your production workflow.
Use default values
The AWS Encryption SDK designs best practices into its default values. Whenever possible, use them.
For cases where the default is impractical, we provide alternatives, such as algorithm suites without signing. We also provide opportunities to advanced users for customization, such a custom keyrings, master key providers, and cryptographic material managers (CMMs). Use these advanced alternatives cautiously and have your choices verified by a security engineer whenever possible.
Use an encryption context
To improve the security of your cryptographic operations, include an encryption context (p. 8) with a meaningful value in all requests to encrypt data. Using an encryption context is optional, but it is a cryptographic best practice that we recommend. An encryption context provides additional authenticated data (AAD) for authenticated encryption in the AWS Encryption SDK. Although it is not secret, the encryption context can help you to protect the integrity and authenticity of your encrypted data.
In the AWS Encryption SDK, you specify an encryption context only when encrypting. When decrypting, the AWS Encryption SDK uses the encryption context in the header of the encrypted message that the AWS Encryption SDK returns. Before your application returns plaintext data, verify that the encryption context that you used to encrypt the message is included in the encryption context that was used to decrypt the message. For details, see the examples in your programming language.
When you use the command line interface, the AWS Encryption SDK verifies the encryption context for you.
Protect your wrapping keys
The AWS Encryption SDK generates a unique data key to encrypt each plaintext message. Then it encrypts the data key with wrapping keys that you supply. If your wrapping keys are lost or deleted, your encrypted data is unrecoverable. If your keys are not secured, your data might be vulnerable.
Use wrapping keys that are protected by a secure key infrastructure, such as AWS Key Management Service (AWS KMS). When using raw AES or raw RSA keys, use a source of randomness and durable
storage that meets your security requirements. Generating and storing wrapping keys in a hardware security module (HSM), or a service that provides HSMs, such as AWS CloudHSM, is a best practice.
Use the authorization mechanisms of your key infrastructure to limit access to your wrapping keys to only the users that require it. Implement best practice principles, such as least privilege. When using AWS KMS keys, use key policies and IAM policies that implement best practice principles.
Specify your wrapping keys
It's always a best practice to specify your wrapping keys explicitly when decrypting, as well as encrypting. When you do, the AWS Encryption SDK uses only the keys that you specify. This practice assures that you only use the encryption keys that you intend. For AWS KMS wrapping keys, it also improves performance by preventing you from inadvertently using keys in a different AWS account or Region, or attempting to decrypt with keys that you don't have permission to use.
When encrypting, the keyrings and master key providers that the AWS Encryption SDK supplies require that you specify wrapping keys. They use all and only the wrapping keys you specify. You are also required to specify wrapping keys when encrypting and decrypting with raw AES keyrings, raw RSA keyrings, and JCEMasterKeys.
However, when decrypting with AWS KMS keyrings and master key providers, you are not required to specify wrapping keys. The AWS Encryption SDK can get the key identifier from the metadata of the encrypted data key. But specifying wrapping keys is a best practice that we recommend.
To support this best practice when working with AWS KMS wrapping keys, we recommend the following:
• Use AWS KMS keyrings that specify wrapping keys. When encrypting and decrypting, these keyrings use only the specified wrapping keys you specify.
• When using AWS KMS master keys and master key providers, use the strict mode constructors introduced in version 1.7.x (p. 177) of the AWS Encryption SDK. They create providers that encrypt and decrypt only with the wrapping keys you specify. Constructors for master key providers that always decrypt with any wrapping key are deprecated in version 1.7.x and deleted in version 2.0.x.
When specifying AWS KMS wrapping keys for decrypting is impractical, you can use discovery providers. The AWS Encryption SDK in C and JavaScript support AWS KMS discovery
keyrings (p. 49). Master key providers with a discovery mode are available for Java and Python in versions 1.7.x and later. These discovery providers, which are used only for decrypting with AWS KMS wrapping keys, explicitly direct the AWS Encryption SDK to use any wrapping key that encrypted a data key.
If you must use a discovery provider, use its discovery filter features to limit the wrapping keys they use. For example, the AWS KMS regional discovery keyring (p. 50) uses only the wrapping keys in a particular AWS Region. You can also configure AWS KMS keyrings and AWS KMS master key providers (p. 189) to use only the wrapping keys (p. 191) in particular AWS accounts. Also, as always, use key policies and IAM policies to control access to your AWS KMS wrapping keys.
Use digital signatures
It's a best practice to use an algorithm suite with signing. Digital signatures (p. 12) verify the message sender was authorized to send the message and protect the integrity of the message. All versions of the AWS Encryption SDK use algorithm suites with signing by default.
If your security requirements don't include digital signatures, you can select an algorithm suite without digital signatures. However, we recommend using digital signatures, especially when one group of users encrypts data and a different set of users decrypts that data.
Use key commitment
It is a best practice to use the key commitment security feature. By verifying the identify of the unique data key (p. 6) that encrypted your data, key commitment (p. 10) prevents you from decrypting any ciphertext that might result in more than one plaintext message.
The AWS Encryption SDK provides full support for encrypting and decrypting with key commitment beginning in version 2.0.x (p. 179). By default, all of your messages are encrypted and decrypted with key commitment. Version 1.7.x (p. 177) of the AWS Encryption SDK can decrypt ciphertexts with key commitment. It is designed to help users of earlier versions deploy version 2.0.x successfully.
Support for key commitment includes new algorithm suites (p. 13) and a new message format (p. 204) that produces a ciphertext only 30 bytes larger than a ciphertext without key commitment. The design minimizes its impact on performance so most users can enjoy the benefits of key commitment. If your application is very sensitive to size and performance, you might
decide to use the commitment policy (p. 11) setting to disable key commitment or allow the AWS Encryption SDK to decrypt messages without commitment, but do so only if you must.
Limit the number of encrypted data keys
It's a best practice to limit the number of encrypted data keys in messages that you decrypt, especially messages from untrusted sources. Decrypting a message with numerous encrypted data keys that you can't decrypt can cause extended delays, run up expenses, throttle your application and others that share your account, and potentially exhaust your key infrastructure. Without limits, an encrypted message can have up to 65,535 (2^16 - 1) encrypted data keys. For details, see Limit encrypted data keys (p. 38).
For more information about the AWS Encryption SDK security features that underlie these best practices, see Improved client-side encryption: Explicit KeyIds and key commitment in the AWS Security Blog.
Configuring the AWS Encryption SDK
The AWS Encryption SDK is designed to be easy to use. Although the AWS 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.
When configuring your implementation, review the AWS Encryption SDK best practices (p. 17) and implement as many as you can.
Topics
• Select a programming language (p. 20)
• Select wrapping keys (p. 20)
• Use multi-Region AWS KMS keys (p. 21)
• Choosing an algorithm suite (p. 33)
• Limit encrypted data keys (p. 38)
• Work with streaming data (p. 40)
• Cache data keys (p. 40)
Select a programming language
The AWS Encryption SDK is available in multiple programming languages (p. 59). 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. However, you might select a programming language for a particular implementation. For example, if you prefer to work with keyrings (p. 41), you might choose the AWS Encryption SDK for C or the AWS Encryption SDK for JavaScript.
Select wrapping keys
The AWS Encryption SDK generates a unique symmetric data key to encrypt each message. Unless you are using data key caching (p. 134), you don't need to configure, manage, or use the data keys. The AWS Encryption SDK does it for you.
However, you must select one or more wrapping keys to encrypt each data key. The AWS Encryption SDK supports AES symmetric keys and RSA asymmetric keys in different sizes. It also supports AWS Key Management Service (AWS KMS) symmetric AWS KMS keys. 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 (C and JavaScript) or a master key provider (Java, Python, AWS Encryption CLI). 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 with the encrypted data in the encrypted message that the AWS Encryption SDK returns.
To decrypt the data, the AWS Encryption SDK must first use one of your wrapping keys to decrypt an encrypted data key.
To specify an AWS KMS key in a keyring or master key provider, use a supported AWS KMS key identifier.
For details about the key identifiers for an AWS KMS key, see Key Identifiers in the AWS Key Management Service Developer Guide.
• When encrypting with the AWS Encryption SDK for Java, AWS Encryption SDK for JavaScript, AWS Encryption SDK for Python, or the AWS Encryption CLI, you can use any valid key identifier (key ID, key ARN, alias name, or alias ARN) for a KMS key. When encrypting with the AWS Encryption SDK for C, you can only use a key ID or key ARN.
If you specify an alias name or alias ARN for a KMS key when encrypting, the AWS 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.
• When decrypting in strict mode (where you specify particular wrapping keys), you must use a key ARN to identify AWS KMS keys. This requirement applies to all language implementations of the AWS Encryption SDK.
When you encrypt with an AWS KMS keyring, the AWS Encryption SDK stores the key ARN of the AWS KMS key in the metadata of the encrypted data key. When decrypting in strict mode, the AWS Encryption SDK verifies that the same key ARN appears in the keyring (or master key provider) before it attempts to use the wrapping key to decrypt the encrypted data key. If you use a different key identifier, the AWS Encryption SDK will not recognize or use the AWS KMS key, even if the identifiers refer to the same key.
To specify a raw AES key (p. 52) or a raw RSA key pair (p. 53) as a wrapping key in a keyring, you must specify a namespace and a name. In a master key provider, the Provider ID is the equivalent of the namespace and the Key ID is the equivalent of the 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 Encryption SDK will not recognize or use the wrapping key, even if the key material is the same.
Use multi-Region AWS KMS keys
You can use AWS Key Management Service (AWS KMS) multi-Region keys as wrapping keys in the AWS Encryption SDK. If you encrypt with a multi-Region key in one AWS Region, you can decrypt using a related multi-Region key in a different AWS Region. Support for multi-Region keys is introduced in version 2.3.x of the AWS Encryption SDK and version 3.0.x of the AWS Encryption CLI.
AWS KMS multi-Region keys are a set of AWS KMS keys in different AWS Regions that have the same key material and key ID. You can use these related keys as though they were the same key in different Regions. Multi-Region keys support common disaster recovery and backup scenarios that require encrypting in one Region and decrypting in a different Region without making a cross-Region call to AWS KMS. For information about multi-Region keys, see Using multi-Region keys in the AWS Key Management Service Developer Guide.
To support multi-Region keys, the AWS Encryption SDK includes AWS KMS multi-Region-aware keyrings and master key providers. The new multi-Region-aware symbol in each programming language supports both single-Region and multi-Region keys.
• For single-Region keys, the multi-Region-aware symbol behaves just like the single-Region AWS KMS keyring and master key provider. It attempts to decrypt ciphertext only with the single-Region key that encrypted the data.
• For multi-Region keys, the multi-Region-aware symbol attempts to decrypt ciphertext with the same multi-Region key that encrypted the data or with the related multi-Region key in the Region you specify.
You can specify multiple wrapping keys in the multi-Region-aware keyrings and master key providers.
However, you can specify only one key from each set of related multi-Region keys. If you specify more than one key identifier with the same key ID, the constructor call fails.
You can also use a multi-Region key with the standard, single-Region AWS KMS keyrings and master key providers. However, you must use the same multi-Region key in the same Region to encrypt and decrypt.
The single-Region keyrings and master key providers attempt to decrypt ciphertext only with the keys that encrypted the data.
The following examples show how to encrypt and decrypt data using multi-Region keys and the new multi-Region-aware keyrings and master key providers. These examples encrypt data in the us-east-1 Region and decrypt the data in the us-west-2 Region using related multi-Region keys in each Region.
Before running these examples, replace the example multi-Region key ARN with a valid value from your AWS account.
C
To encrypt with a multi-Region key, use the
Aws::Cryptosdk::KmsMrkAwareSymmetricKeyring::Builder() method to instantiate the keyring. Specify a multi-Region key.
This simple example does not include an encryption context (p. 8). For an example that uses an encryption context in C, see Encrypting and decrypting strings (p. 63).
For a complete example, see kms_multi_region_keys.cpp in the AWS Encryption SDK for C repository on GitHub.
/* Load error strings for debugging */
aws_cryptosdk_load_error_strings();
/* Initialize a multi-Region keyring */
const char *mrk_us_east_1 = "arn:aws:kms:us-east-1:111122223333:key/
mrk-1234abcd12ab34cd56ef1234567890ab";
struct aws_cryptosdk_keyring *mrk_keyring =
Aws::Cryptosdk::KmsMrkAwareSymmetricKeyring::Builder().Build(mrk_us_east_1);
/* Create a session; release the keyring */
struct aws_cryptosdk_session *session =
aws_cryptosdk_session_new_from_keyring_2(aws_default_allocator(), AWS_CRYPTOSDK_ENCRYPT, mrk_keyring);
aws_cryptosdk_session_set_commitment_policy(session, COMMITMENT_POLICY_REQUIRE_ENCRYPT_REQUIRE_DECRYPT);
aws_cryptosdk_keyring_release(mrk_keyring);
/* Encrypt the data
* aws_cryptosdk_session_process_full is designed for non-streaming data */
aws_cryptosdk_session_process_full(
session, ciphertext, ciphertext_buf_sz, &ciphertext_len, plaintext, plaintext_len));
/* Clean up the session */
aws_cryptosdk_session_destroy(session);
AWS Encryption CLI
This example encrypts the hello.txt file under a multi-Region key in the us-east-1 Region.
Because the example specifies a key ARN with a Region element, this example doesn't use the region attribute of the --wrapping-keys parameter.
When the key ID of the wrapping key doesn't specify a Region, you can use the region attribute of the --wrapping-keys to specify the region, such as --wrapping-keys key=$keyID region=us-east-1.
# To run this example, replace the fictitious key ARN with a valid value.
$ mrkUSEast1=arn:aws:kms:us-east-1:111122223333:key/
mrk-1234abcd12ab34cd56ef1234567890ab
$ aws-encryption-cli --encrypt \
--input hello.txt \
--wrapping-keys key=$mrkUSEast1 \ --metadata-output ~/metadata \ --encryption-context purpose=test \
--commitment-policy require-encrypt-require-decrypt \ --output .
Java
To encrypt with a multi-Region key, instantiate an AwsKmsMrkAwareMasterKeyProvider and specify a multi-Region key.
For a complete example, see BasicMultiRegionKeyEncryptionExample.java in the AWS Encryption SDK for Java repository on GitHub.
//Encrypt in us-east-1 Region // Instantiate the client
final AwsCrypto crypto = AwsCrypto.builder()
.withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt) .build();
// Multi-Region keys have a distinctive key ID that begins with 'mrk' // Specify a multi-Region key in us-east-1
final String mrkUSEast1 = "arn:aws:kms:us-east-1:111122223333:key/
mrk-1234abcd12ab34cd56ef1234567890ab";
// Instantiate an AWS KMS master key provider in strict mode for multi-Region keys // Configure it to encrypt with the multi-Region key in us-east-1
final AwsKmsMrkAwareMasterKeyProvider kmsMrkProvider = AwsKmsMrkAwareMasterKeyProvider .builder()
.buildStrict(mrkUSEast1);
// Create an encryption context
final Map<String, String> encryptionContext = Collections.singletonMap("Purpose", "Test");
// Encrypt your plaintext data
final CryptoResult<byte[], AwsKmsMrkAwareMasterKey> encryptResult = crypto.encryptData(
kmsMrkProvider, encryptionContext, sourcePlaintext);
byte[] ciphertext = encryptResult.getResult();
JavaScript Browser
To encrypt with a multi-Region key, use the
buildAwsKmsMrkAwareStrictMultiKeyringBrowser() method to create the keyring and specify a multi-Region key.
For a complete example, see kms_multi_region_simple.ts in the AWS Encryption SDK for JavaScript repository on GitHub.