Best practices for the AWS Encryption SDK - AWS Encryption SDK

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. 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 and Versions of the AWS Encryption SDK.

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 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 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. 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 uses only the wrapping keys in a particular AWS Region. You can also configure AWS KMS keyrings and AWS KMS master key providers to use only the wrapping keys 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 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 identity of the unique data key that encrypted your data, key commitment 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. By default, all of your messages are encrypted and decrypted with key commitment. Version 1.7.x 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 and a new message format 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 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 Limiting encrypted data keys.

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.