Data encryption using AWS KMS Key

David Cheong
6 min readAug 21, 2020

Security always a top priority when come to the system design and development, encryption is vital when deal with sensitive data which prevent the access by any unauthorized user.

AWS KMS (Key Management Service) is the service that manages encryption keys on AWS. These encryption keys are called “ Customer Master Keys” or CMKs for short. KMS uses Hardware Security Modules (Physical devices, commonly known as HSM) to store CMKs. AWS KMS is integrated with many AWS services and it uses AWS CloudTrail to track the usage logs of the keys for audit and compliance needs.

Customer Master Key (CMK) vs Data Key

CMKs are created and managed by AWS KMS. However, CMK is only used to encrypt a small amount of data less than 4KBs. AWS does not encrypt the gigabytes of data using CMK. If you have large data to encrypt, then use Data Keys.

Data Keys are generated from CMKs. There is a direct relationship between Data Key and a CMK. However, AWS does NOT store or manage Data Keys. Instead, you have to manage them.

You can use the customer master key to generate unlimited number of unique data keys.

In this article, I will share on how to create the encryption data key using the AWS KMS to encrypt the data and decrypt the data. This is only deal with the encryption at rest.

Step 1: Creating the CMK in AWS console

To create the key, first login to the AWS KMS console page. Remember the KMS is a regional managed service, where the key created is limit to that specific region only, so make sure you select the right region, for my case, I’m using the ap-souteeast-1 region to create my key.

Click on the create a key on the page

Select Symmetric key and click next. Symmetric key is refer to using the same key for both encryption and decryption of data, this is suitable for most of the use case.

On the Advanced options, you may just leave it default to use the KMS provided key material to generate the key.

“Use a symmetric CMK for most use cases that require encrypting and decrypting data. The symmetric encryption algorithm that AWS KMS uses is fast, efficient, and assures the confidentiality and authenticity of data.” — AWS Documentation

Provide the labels for your key, this alias may use for the identify the key in the script later on if you do not wish to use the long key-id.

Select the user who you want to provide the key administration permission

Select the user who you can use this key, this can be a IAM user or Role (incase you want your EC2 to assume the role to use they key)

Finally review the permission for the key and click on finish to complete the key creation.

You should see your new customer managed key available in the list. Next we will use this CMK to generate the data key and also to encrypt, decrypt the data.

Step 2: Encrypt data using AWS KMS CLI

First create a text file which will use for the encryption purpose and write some content into the file. After create the file, we need to decode the file to base64 as the KMS encryption only accept the base64 as input.

$ echo "my website: https://tech.david-cheong.com" > plaintext.txt 
$ base64 -i plaintext.txt -o plaintext.bin

Once the plaintext base64 file is ready, than we can start to do the encryption using the KMS encrypt cli. We need to pass in the key id (for this article, I’m using the key alias) and also the base64 file which we just converted.

Once we pass in the key-id and the file to encrypt, it will return the Ciphertext Blob, key Id as well as the encryption algorithm that we are using.

aws kms encrypt --key-id alias/demo --plaintext fileb://plaintext.bin 
{ "CiphertextBlob":"AQICAHhafwr0R1gD87hzIMWvZg4iolG3wyPx5ACoDbngRFUo2QGfroeBVinLA9Hw5AWTpCkEAAAAmzCBmAYJKoZIhvcNAQcGoIGKMIGHAgEAMIGBBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDNucopAAyw7639WqLgIBEIBUWd1u6wj5Uogdzwp9YTunH1Gc+s93/SH63BOk/S9fGOPL4S3fViRBClxFyF6hYQsJtl1beg0It5aW/mFp7ldtD0kmn/wKizC59lue5TMCpAwljji5",
"KeyId": "arn:aws:kms:ap-southeast-1:298942976044:key/caaed47a-5151-4b6b-8542-39698bd76d38",
"EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}

To get only the encrypted content, we will need to query the CiphertextBlob field and store the content into a file call encrypted.txt.

$ aws kms encrypt --key-id alias/demo --plaintext fileb://plaintext.txt --query CiphertextBlob --output text | base64 -d > encrypted.txt 
$ ls
encrypted.txt plaintext.bin plaintext.txt

If you try to cat the content for the encrypted.txt file, you should get the following dummy content, this is because the content is base64 encoded.

This is actually our encrypted content from the input plaintext, in the encrypted content, AWS KMS actually store the encrypted data key inside, so when we try to decrypt the file, we no need to pass in the key id again, and AWS KMS already know which key to use for the decryption.

More Detail: https://docs.aws.amazon.com/cli/latest/reference/kms/encrypt.html

Step 3: Decrypt the data

To decrypt the data, we may just pass in the encrypted file into the CLI and AWS KMS will return the json which contain key id, plaintext as well as the encryption algorithm that are using.

$ aws kms decrypt --ciphertext-blob fileb://encrypted.txt 
{
"KeyId": "arn:aws:kms:ap-southeast-1:298942976044:key/caaed47a-5151-4b6b-8542-39698bd76d38",
"Plaintext": "bXkgd2Vic2l0ZTogaHR0cHM6Ly90ZWNoLmRhdmlkLWNoZW9uZy5jb20K",
"EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}

To get back our content, need to pass in 2 parameters when call the cli.

$ aws kms decrypt --ciphertext-blob fileb://encrypted.txt --query Plaintext --output text | base64 -d > decrypted.txt 
$ cat decrypted.txt
my website: https://tech.david-cheong.com

More detail : https://docs.aws.amazon.com/cli/latest/reference/kms/encrypt.html

After we pass in the query and output parameter into the cli, than we do the base64 decoded and save the content into the file call decrypted.txt.

Now if you open the decrypted.txt file, you should get back the original plaintext data.

This is a very simple demo on how to use the AWS KMS customer master key to generate the data key and encrypt our data. AWS also provide the SDK for multiple programming language such as Nodejs, Java and more in order for developer to actually can encrypt the data easily.

Congratulations! We have successfully completed the encryption and decryption of our sensitive data.

Originally published at https://tech.david-cheong.com on August 21, 2020.

--

--