Raw RSA keyrings - AWS Encryption SDK

Raw RSA keyrings

The Raw RSA keyring performs asymmetric encryption and decryption of data keys in local memory with an RSA public and private keys that you provide. You need to generate, store, and protect the private key, preferably in a hardware security module (HSM) or key management system. The encryption function encrypts the data key under the RSA public key. The decryption function decrypts the data key using the private key. You can select from among the several RSA padding modes.

A Raw RSA keyring that encrypts and decrypts must include an asymmetric public key and private key pair. However, you can encrypt data with a Raw RSA keyring that has only a public key, and you can decrypt data with a Raw RSA keyring that has only a private key. You can include any Raw RSA keyring in a multi-keyring. If you configure a Raw RSA keyring with a public and private key, be sure that they are part of the same key pair. Some language implementations of the AWS Encryption SDK will not construct a Raw RSA keyring with keys from different pairs. Others rely on you to verify that your keys are from the same key pair.

The Raw RSA keyring is equivalent to and interoperates with the JceMasterKey in the AWS Encryption SDK for Java and the RawMasterKey in the AWS Encryption SDK for Python when they are used with RSA asymmetric 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.

Note

The Raw RSA keyring does not support asymmetric KMS keys. If you want to use asymmetric RSA KMS keys, version 4.x of the AWS Encryption SDK for .NET and version 3.x of the AWS Encryption SDK for Java support AWS KMS keyrings that use symmetric encryption (SYMMETRIC_DEFAULT) or asymmetric RSA AWS KMS keys.

If you encrypt data with a Raw RSA keyring that includes the public key of an RSA KMS key, neither the AWS Encryption SDK nor AWS KMS can decrypt it. You cannot export the private key of an AWS KMS asymmetric KMS key into a Raw RSA keyring. The AWS KMS Decrypt operation cannot decrypt the encrypted message that the AWS Encryption SDK returns.

When constructing a Raw RSA keyring in the AWS Encryption SDK for C, be sure to provide the contents of the PEM file that includes each key as a null-terminated C-string, not as a path or file name. When constructing a Raw RSA keyring in JavaScript, be aware of potential incompatibility with other language implementations.

Namespaces and names

To identify the RSA key material in a keyring, the Raw RSA 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 the key namespace and key name that identifies the RSA key pair (or its private key) in your HSM or key management 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 reserves the aws-kms key namespace value for KMS keys. Do not use it in a Raw AES keyring or Raw RSA keyring with the AWS Encryption SDK for C.

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 keys are from the same key pair.

The key namespace and key name of the key material in the encryption and decryption keyrings must be same whether the keyring contains the RSA public key, the RSA private key, or both keys in the key pair. For example, suppose you encrypt data with a Raw RSA keyring for an RSA public key with key namespace HSM_01 and key name RSA_2048_06. To decrypt that data, construct a Raw RSA keyring with the private key (or key pair), and the same key namespace and name.

Padding mode

You must specify a padding mode for Raw RSA keyrings used for encryption and decryption, or use features of your language implementation that specify it for you.

The AWS Encryption SDK supports the following padding modes, subjects to the constraints of each language. We recommend an OAEP padding mode, particularly OAEP with SHA-256 and MGF1 with SHA-256 Padding. The PKCS1 padding mode is supported only for backward compatibility.

  • OAEP with SHA-1 and MGF1 with SHA-1 Padding

  • OAEP with SHA-256 and MGF1 with SHA-256 Padding

  • OAEP with SHA-384 and MGF1 with SHA-384 Padding

  • OAEP with SHA-512 and MGF1 with SHA-512 Padding

  • PKCS1 v1.5 Padding

The following examples show how to create a Raw RSA keyring with the public and private key of an RSA key pair and the OAEP with SHA-256 and MGF1 with SHA-256 padding mode. The RSAPublicKey and RSAPrivateKey variables represent the key material you provide.

C

To create a Raw RSA keyring in the AWS Encryption SDK for C, use aws_cryptosdk_raw_rsa_keyring_new.

When constructing a Raw RSA keyring in the AWS Encryption SDK for C, be sure to provide the contents of the PEM file that includes each key as a null-terminated C-string, not as a path or file name. For a complete example, see raw_rsa_keyring.c.

struct aws_allocator *alloc = aws_default_allocator(); AWS_STATIC_STRING_FROM_LITERAL(key_namespace, "HSM_01"); AWS_STATIC_STRING_FROM_LITERAL(key_name, "RSA_2048_06"); struct aws_cryptosdk_keyring *rawRsaKeyring = aws_cryptosdk_raw_rsa_keyring_new( alloc, key_namespace, key_name, private_key_from_pem, public_key_from_pem, AWS_CRYPTOSDK_RSA_OAEP_SHA256_MGF1);
C# / .NET

To instantiate a Raw RSA keyring in the AWS Encryption SDK for .NET, use the materialProviders.CreateRawRsaKeyring() method. For a complete example, see RawRSAKeyringExample.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 = "RSA_2048_06"; // Get public and private keys from PEM files var publicKey = new MemoryStream(System.IO.File.ReadAllBytes("RSAKeyringExamplePublicKey.pem")); var privateKey = new MemoryStream(System.IO.File.ReadAllBytes("RSAKeyringExamplePrivateKey.pem")); // Create the keyring input var createRawRsaKeyringInput = new CreateRawRsaKeyringInput { KeyNamespace = keyNamespace, KeyName = keyName, PaddingScheme = PaddingScheme.OAEP_SHA512_MGF1, PublicKey = publicKey, PrivateKey = privateKey }; // Create the keyring var rawRsaKeyring = materialProviders.CreateRawRsaKeyring(createRawRsaKeyringInput);
JavaScript Browser

The AWS Encryption SDK for JavaScript in the browser gets its cryptographic primitives from the WebCrypto library. Before you construct the keyring, you must use importPublicKey() and/or importPrivateKey() 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. The object that the import methods take includes the wrapping algorithm and its padding mode.

After importing the key material, use the RawRsaKeyringWebCrypto() method to instantiate the keyring. When constructing a Raw RSA keyring in JavaScript, be aware of potential incompatibility with other language implementations.

For a complete example, see rsa_simple.ts (JavaScript Browser).

const privateKey = await RawRsaKeyringWebCrypto.importPrivateKey( privateRsaJwKKey ) const publicKey = await RawRsaKeyringWebCrypto.importPublicKey( publicRsaJwKKey ) const keyNamespace = 'HSM_01' const keyName = 'RSA_2048_06' const keyring = new RawRsaKeyringWebCrypto({ keyName, keyNamespace, publicKey, privateKey, })
JavaScript Node.js

To instantiate a Raw RSA keyring in AWS Encryption SDK for JavaScript for Node.js, create a new instance of the RawRsaKeyringNode class. The wrapKey parameter holds the public key. The unwrapKey parameter holds the private key. The RawRsaKeyringNode constructor calculates a default padding mode for you, although you can specify a preferred padding mode.

When constructing a raw RSA keyring in JavaScript, be aware of potential incompatibility with other language implementations.

For a complete example, see rsa_simple.ts (JavaScript Node.js).

const keyNamespace = 'HSM_01' const keyName = 'RSA_2048_06' const keyring = new RawRsaKeyringNode({ keyName, keyNamespace, rsaPublicKey, rsaPrivateKey})
Java
final CreateRawRsaKeyringInput keyringInput = CreateRawRsaKeyringInput.builder() .keyName("RSA_2048_06") .keyNamespace("HSM_01") .paddingScheme(PaddingScheme.OAEP_SHA256_MGF1) .publicKey(RSAPublicKey) .privateKey(RSAPrivateKey) .build(); final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); IKeyring rawRsaKeyring = matProv.CreateRawRsaKeyring(keyringInput);