How can I use AWS KMS asymmetric keys to encrypt a file using OpenSSL?
Last updated: 2022-08-04
I want to use the Key Management Service (AWS KMS) keys to encrypt a file using OpenSSL. How can I do this?
You can't encrypt large pieces of data with RSA keys. For example, to encrypt an RSA key pair size of 2048 bytes with RSAES_OAEP_SHA_256, the largest amount of that you can encrypt is 190 bytes. With Advanced Encryption Standard (AES) keys, you can split your data into smaller pieces using Cipher Block Chaining (CBC).
Follow these instructions to encrypt and decrypt keys using CBC.
Note: If you receive errors when running AWS Command Line Interface (AWS CLI) commands, make sure that you’re using the most recent AWS CLI version.
Create the RSA key pair, download the public key, and create an AES 256-bit key
1. Follow the instructions for creating the RSA key pair with the AWS Management Console.
2. Download the public key using the AWS CLI command get-public-key similar to the following:
$ aws kms get-public-key --key-id arn:aws:kms:eu-west-1:123456789012:key/d74f5077-811b-4447-af65-71f5f64f37d3 --output text --query 'PublicKey' > RSAPublic.b64 && base64 -d RSAPublic.b64 > RSAPublic.bin
3. Create an AES 256-bit key using the OpenSSL rand command to generate random data and then output to the key.bin file similar to the following:
$ openssl rand -base64 32 > key.bin
Encrypt your data
1. Encrypt your data using the key.bin file with the OpenSSL enc command encrypted in CBC similar to the following:
$ openssl enc -aes-256-cbc -salt -pbkdf2 -in FILE_TO_ENCRYPT -out FILE_TO_ENCRYPT.enc -pass file:./key.bin
- The -pbkdf2 command is only available with OpenSSL 1.1.1. Amazon Linux 2 AMI has OpenSSL 1.0.2 installed, which doesn't support the -pbkdf2 command.
- CBC allows you to encrypt files of any size.
- Replace the value FILE_TO_ENCRYPT with the name of the file that you want to encrypt.
2. Encrypt your AES 256-bit key key.bin with the AWS KMS public key. This verifies that the key to your data is secure. Only users that have access to your AWS KMS private key can access the key.bin key.
Run the OpenSSL pkeyutl command similar to the following:
$ openssl pkeyutl -in key.bin -out enc.key.bin -inkey RSAPublic.bin -keyform DER -pubin -encrypt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256
Note: The pkeyutl command uses an encryption algorithm that's supported for decryption by the AWS KMS API (RSAES_OAEP_SHA_256). The AWS KMS public key RSAPublic.bin encrypts the AES 256 Key and creates a new file named enc.key.bin.
3. Encrypt the key.bin file so that users can't access it unless they can decrypt the file enc.key.bin using the AWS CLI command rm similar to the following:
$ rm key.bin && rm FILE_TO_ENCRYPT
Note: You can also choose to delete the original file that you wanted to encrypt so that users can't access it.
You now have the following:
- The encrypted data in the FILE_TO_ENCRYPT.enc file.
- The encrypted AES 256-bit key enc.key.bin.
- The AWS KMS public key RSAPublic.bin.
Note: Users with encrypted data must send you these files to decrypt.
Decrypting the files sent to you
To retrieve the encrypted data, decrypt the AES 256-bit key, and then use that key to decrypt the data file FILE_TO_ENCRYPT.enc.
Note: You must have access to the AWS KMS API, because the AWS KMS private key can't be viewed in plaintext.
1. Decrypt the AES 256-bit key and submit the enc.key.bin file to the AWS KMS API using the AWS CLI command decrypt similar to the following:
$ aws kms decrypt --key-id arn:aws:kms:eu-west-1:123456789012:key/d74f5077-811b-4447-af65-71f5f64f37d3 --ciphertext-blob fileb://enc.key.bin --encryption-algorithm RSAES_OAEP_SHA_256 --output text --query 'Plaintext' | base64 --decode > decryptedKey.bin
2. Run the OpenSSL enc command using the decryptedKey.bin file to output to DECRYPTED_FILE similar to the following:
$ openssl enc -d -aes-256-cbc -pbkdf2 -in FILE_TO_ENCRYPT.enc -out DECRYPTED_FILE -pass file:./decryptedKey.bin
Note: Replace the value DECRYPTED_FILE with the name of the file that you want to decrypt.
You can compare the DECRYPTED_FILE and FILE_TO_ENCRYPT to make sure that the encryption and decryption completed successfully.