Envelope Encryption using AWS CLI
Tags: aws, microservices, architecture, encryption
Published: 2020-09-10 12:44:01

## Background

I have already posted article on Envelope Encryption and how it works. Please take a look at that [article](https://dev.to/chiragdm/aws-kms-envelope-encryption-3689).

This article covers how can we encrypt/decrypt large amount of data by Envelope Encryption using AWS CLI.

## Prerequisite

This hands-on exercise requires AWS account and AWS CLI. You can get more information about installation and configuration of AWS CLI from [here](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html)

## Hands-on Exercise

**Generate Customer Master Key**

We have AWS CLI setup by now so first step is to create AWS CMK (Customer Master key) using KMS. We have got our Customer Master Key which we will be using for encryption.

    aws kms create-key --description "This key is used for envelope encryption"
    output:
    {
    "KeyMetadata": {
        "AWSAccountId": "************",
        "KeyId": "21763c54-353e-4099-8027-************",
        "Arn": "arn:aws:kms:us-east-1:************:key/21763c54-353e-4099-8027-************",
        "CreationDate": "2020-09-10T14:59:44.359000+05:30",
        "Enabled": true,
        "Description": "This key is used for envelope encryption",
        "KeyUsage": "ENCRYPT_DECRYPT",
        "KeyState": "Enabled",
        "Origin": "AWS_KMS",
        "KeyManager": "CUSTOMER",
        "CustomerMasterKeySpec": "SYMMETRIC_DEFAULT",
        "EncryptionAlgorithms": [
            "SYMMETRIC_DEFAULT"
        ]
    }


**1. Generate Data Key**

Let's generate Data key using CMK we generated earlier. It returns Data Key (Plaintext) and Encrypted Data key (CiphertextBlob).

    aws kms generate-data-key --key-id 21763c54-353e-4099-8027-************ --key-spec AES_256
    Output:
    {
    "CiphertextBlob": "************IPQE9CgC3MLxxTR8lu/AFcM2axxufFf5mB81aqlukaAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM5FCtUAUdCHJ72PYNAgEQgDs7EwfgzL4g4/E48AJTKVEKJq8EsuEM6hAlcZ6XWw0AlYpfLyXD910NSd/LasDtI2YkIp7wSitlpdkVuw==",
        "Plaintext": "XIJVOItN8cc40n/H8/Wzbs/u+57/H5ERL/gi/hArqZI=",
        "KeyId": "arn:aws:kms:us-east-1:************:key/21763c54-353e-4099-8027-************"
    }

**2. Decode Base64 encoded Data Key**

Keep note that Data Key and Encrypted Data key generated in previous step are Base64 encoded so we need to decode it first.

    echo 'XIJVOItN8cc40n/H8/Wzbs/u+57/H5ERL/gi/hArqZI=' | base64 --decode > ~/plaintext_data_key.txt

**3. Encrypt Data using Plaintext Data Key**

We are encrypting actual data using Decoded plaintext data key using AES256 encryption.

    echo "This is data I want to encrypt using plain data key"  | openssl enc -e -aes256 -k fileb:///Users/chirag/plaintext_data_key.txt > ~/encrypted_data.txt

**4. Package Encrypted Data and Data key**

We have now Encrypted Data and Encrypted Data Key which we can store together or separately on Data store. Make sure to store Encrypted Data key which will be required during decryption.

**5. Remove Plaintext Data Key**

We can remove Data key from system after Data encryption as it's sensitive information and we don't require it as we have stored Encrypted Data key so in future whenever required we can get back plaintext data key.

    rm ~/plaintext_data_key.txt

**6. Extract Data for Decryption**

Let's we want our encoded data back so first need to extract Encrypted Data key we stored earlier and then Decode it as it was also Base64 encoded.

    echo '************IPQE9CgC3MLxxTR8lu/AFcM2axxufFf5mB81aqlukaAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM5FCtUAUdCHJ72PYNAgEQgDs7EwfgzL4g4/E48AJTKVEKJq8EsuEM6hAlcZ6XWw0AlYpfLyXD910NSd/LasDtI2YkIp7wSitlpdkVuw==' | base64 --decode > ~/encrypted_data_key.txt

**7. Decrypt Encrypted Plaintext Data Key**

Once we get back Encrypted Data Key, we need to call Decrypt API to get Plaintext Data Key.

    aws kms decrypt --ciphertext-blob fileb:///Users/chirag/encrypted_data_key.txt
    Output:
    {
    "KeyId": "arn:aws:kms:us-east-1:************:key/21763c54-353e-4099-8027-************",
    "Plaintext": "XIJVOItN8cc40n/H8/Wzbs/u+57/H5ERL/gi/hArqZI=",
    "EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
    }

**8. Decode Base64 encoded Plaintext Data Key**

Again Decrypted Data Key we got is Base64 encoded so we need to decode it first.

    echo 'XIJVOItN8cc40n/H8/Wzbs/u+57/H5ERL/gi/hArqZI=' | base64 --decode > ~/decrypted_plaintext_data_key.txt

**9. Decrypt actual data using Plaintext Data Key**

Take actual encrypted data and decrypt it using same AES256 algorithm and we got actual data back.

    cat ~/encrypted_data.txt  | openssl enc -d -aes256 -k fileb:///Users/chirag/decrypted_plaintext_data_key.txt
    Output:
    This is data I want to encrypt using plain data key

**10. Remove Plaintext Data Key**

Cleanup Plaintext Data Key.

    rm ~/decrypted_plaintext_data_key.txt

**Note**: *I have masked all sensitive information here with "\*"*

## Conclusion

So we have gone through full cycle of encryption (steps 1-5) and decryption (steps 6-10) making use of Envelope Encryption using AWS KMS. 

This is how AWS internally performs Data encryption for large datasets in S3, EBS, RDS, etc.. when data encryption is enabled.

Thanks for joining me.