Raw AES keyrings - AWS Encryption SDK

Raw AES keyrings

The AWS Encryption SDK lets you use an AES symmetric key that you provide as a wrapping key that protects your data key. You need to generate, store, and protect the key material, preferably in a hardware security module (HSM) or key management system. Use a Raw AES keyring when you need to provide the wrapping key and encrypt the data keys locally or offline.

The Raw AES keyring encrypts data by using the AES-GCM algorithm and a wrapping key that you specify as a byte array. You can specify only one wrapping key in each Raw AES keyring, but you can include multiple Raw AES keyrings, alone or with other keyrings, in a multi-keyring.

The Raw AES keyring is equivalent to and interoperates with the JceMasterKey class in the AWS Encryption SDK for Java and the RawMasterKey class in the AWS Encryption SDK for Python when they are used with an AES encryption keys. You can encrypt data with one implementation and decrypt the data with any other implementation using the same wrapping key. For details, see Keyring compatibility.

Key namespaces and names

To identify the AES key in a keyring, the Raw AES keyring uses a key namespace and key name that you provide. These values are not secret. They appear in plain text in the header of the encrypted message that the encrypt operation returns. We recommend using a key namespace your HSM or key management system and a key name that identifies the AES key in that system.

Note

The key namespace and key name are equivalent to the Provider ID (or Provider) and Key ID fields in the JceMasterKey and RawMasterKey.

The AWS Encryption SDK for C and AWS Encryption SDK for .NET reserve the aws-kms key namespace value for KMS keys. Do not use this namespace value in a Raw AES keyring or Raw RSA keyring with these libraries.

If you construct different keyrings to encrypt and decrypt a given message, the namespace and name values are critical. If the key namespace and key name in the decryption keyring isn't an exact, case-sensitive match for the key namespace and key name in the encryption keyring, the decryption keyring isn't used, even if the key material bytes are identical.

For example, you might define a Raw AES keyring with key namespace HSM_01 and key name AES_256_012. Then, you use that keyring to encrypt some data. To decrypt that data, construct a Raw AES keyring with the same key namespace, key name, and key material.

The following examples show how to create a Raw AES keyring. The AESWrappingKey variable represents the key material you provide.

C

To instantiate a Raw AES keyring in the AWS Encryption SDK for C, use aws_cryptosdk_raw_aes_keyring_new(). For a complete example, see raw_aes_keyring.c.

struct aws_allocator *alloc = aws_default_allocator(); AWS_STATIC_STRING_FROM_LITERAL(wrapping_key_namespace, "HSM_01"); AWS_STATIC_STRING_FROM_LITERAL(wrapping_key_name, "AES_256_012"); struct aws_cryptosdk_keyring *raw_aes_keyring = aws_cryptosdk_raw_aes_keyring_new( alloc, wrapping_key_namespace, wrapping_key_name, aes_wrapping_key, wrapping_key_len);
C# / .NET

To create a Raw AES keyring in AWS Encryption SDK for .NET, use the materialProviders.CreateRawAesKeyring() method. For a complete example, see RawAESKeyringExample.cs.

The following example uses version 4.x of the AWS Encryption SDK for .NET.

// Instantiate the AWS Encryption SDK and material providers var esdk = new ESDK(new AwsEncryptionSdkConfig()); var mpl = new MaterialProviders(new MaterialProvidersConfig()); var keyNamespace = "HSM_01"; var keyName = "AES_256_012"; // This example uses the key generator in Bouncy Castle to generate the key material. // In production, use key material from a secure source. var aesWrappingKey = new MemoryStream(GeneratorUtilities.GetKeyGenerator("AES256").GenerateKey()); // Create the keyring that determines how your data keys are protected. var createKeyringInput = new CreateRawAesKeyringInput { KeyNamespace = keyNamespace, KeyName = keyName, WrappingKey = aesWrappingKey, WrappingAlg = AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 }; var keyring = materialProviders.CreateRawAesKeyring(createKeyringInput);
JavaScript Browser

The AWS Encryption SDK for JavaScript in the browser gets its cryptographic primitives from the WebCrypto API. Before you construct the keyring, you must use RawAesKeyringWebCrypto.importCryptoKey() to import the raw key material into the WebCrypto backend. This assures that the keyring is complete even though all calls to WebCrypto are asynchronous.

Then, to instantiate a Raw AES keyring, use the RawAesKeyringWebCrypto() method. You must specify the AES wrapping algorithm ("wrapping suite) based on the length of your key material. For a complete example, see aes_simple.ts (JavaScript Browser).

The following example uses the buildClient function to specify the default commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT. You can also use the buildClient to limit the number of encrypted data keys in an encrypted message. For more information, see Limiting encrypted data keys.

import { RawAesWrappingSuiteIdentifier, RawAesKeyringWebCrypto, synchronousRandomValues, buildClient, CommitmentPolicy, } from '@aws-crypto/client-browser' const { encrypt, decrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) const keyNamespace = 'HSM_01' const keyName = 'AES_256_012' const wrappingSuite = RawAesWrappingSuiteIdentifier.AES256_GCM_IV12_TAG16_NO_PADDING /* Import the plaintext AES key into the WebCrypto backend. */ const aesWrappingKey = await RawAesKeyringWebCrypto.importCryptoKey( rawAesKey, wrappingSuite ) const rawAesKeyring = new RawAesKeyringWebCrypto({ keyName, keyNamespace, wrappingSuite, aesWrappingKey })
JavaScript Node.js

To instantiate a Raw AES keyring in the AWS Encryption SDK for JavaScript for Node.js, create an instance of the RawAesKeyringNode class. You must specify the AES wrapping algorithm ("wrapping suite") based on the length of your key material. For a complete example, see aes_simple.ts (JavaScript Node.js).

The following example uses the buildClient function to specify the default commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT. You can also use the buildClient to limit the number of encrypted data keys in an encrypted message. For more information, see Limiting encrypted data keys.

import { RawAesKeyringNode, buildClient, CommitmentPolicy, RawAesWrappingSuiteIdentifier, } from '@aws-crypto/client-node' const { encrypt, decrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) const keyName = 'AES_256_012' const keyNamespace = 'HSM_01' const wrappingSuite = RawAesWrappingSuiteIdentifier.AES256_GCM_IV12_TAG16_NO_PADDING const rawAesKeyring = new RawAesKeyringNode({ keyName, keyNamespace, aesWrappingKey, wrappingSuite, })
Java

To instantiate a Raw AES keyring in the AWS Encryption SDK for Java, use matProv.CreateRawAesKeyring().

final CreateRawAesKeyringInput keyringInput = CreateRawAesKeyringInput.builder() .keyName("AES_256_012") .keyNamespace("HSM_01") .wrappingKey(AESWrappingKey) .wrappingAlg(AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16) .build(); final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); IKeyring rawAesKeyring = matProv.CreateRawAesKeyring(keyringInput);
Python

The following example instantiates the AWS Encryption SDK client with the default commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT. For a complete example, see raw_aes_keyring_example.py in the AWS Encryption SDK for Python repository in GitHub.

# Instantiate the AWS Encryption SDK client client = aws_encryption_sdk.EncryptionSDKClient( commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) # Define the key namespace and key name key_name_space = "HSM_01" key_name = "AES_256_012" # Optional: Create an encryption context encryption_context: Dict[str, str] = { "encryption": "context", "is not": "secret", "but adds": "useful metadata", "that can help you": "be confident that", "the data you are handling": "is what you think it is", } # Instantiate the material providers mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( config=MaterialProvidersConfig() ) # Create Raw AES keyring keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( key_namespace=key_name_space, key_name=key_name, wrapping_key=AESWrappingKey, wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 ) raw_aes_keyring: IKeyring = mat_prov.create_raw_aes_keyring( input=keyring_input )