Psst, our application has a secret!
And keeping that secret a secret can often be a challenging problem.
All of our secrets can have different requirements causing varying degrees of complexity for saving and retrieving. As developers, it's imperative we understand fully the implication of a leaked secret, and then choose the appropriate level of protection.
Along comes Amazon's Key Management System (KMS) to make our lives a little easier.
Key Management System
Amazon's Key Management System (KMS) makes it easy to create and control encryption keys used to encrypt our secrets. And, as a bonus, it can integrate with AWS CloudTrail to provide an audit trail of all key usage.
KMS has two primary encryption methods:
- Simple Encryption is when we pass our data directly to KMS for encryption. We can pass up to 4 KB of arbitrary data such as a database password, a configuration file or other sensitive information. Simple Encryption is suitable for data with no strict restrictions against cloud management.
- Envelope Encryption is when we want to manage the encryption ourselves locally using AES, but we require a data key to seed the encryption. KMS can generate a unique encrypted data key which we can use locally for our encryption algorithm. Envelope Encryption is suitable for regulatory or compliance requirements, such as HIPAA, that have very strict rules on where data can be managed.
KMS Setup
To use KMS, we first need to:
- Create a Customer Master Encryption Key
- Create an IAM role or user that has permission to use the Encryption Key
Simple Encryption
Encryption:
Now, let's use the AWS CLI to encrypt a file:
- $key = A valid Encryption Key ID/ARN
- $sourceFile = Source file you want to encrypt
- $encryptedFile = Location of encrypted output file
Linux/OSX:
aws kms encrypt –key-id $key –plaintext fileb://$sourceFile –output text –query CiphertextBlob | base64 –decode > "$encryptedFile"
Windows:
aws kms encrypt –key-id $key –plaintext fileb://$sourceFile –output text –query CiphertextBlob > Temp.$encryptedFile.base64
certutil -decode Temp.$encryptedFile.base64 $encryptedFile
Note the base64 decoding after the encrypt. Both KMS encrypt and decrypt return a base64 encoded string. However, decrypt will not take base64 as input. If we want to decrypt our encrypted secret, we need to decode and save it as a binary file.
Decryption:
To decrypt the file:
- $encryptedFile = Encrypted source file you want to decrypt
- $decryptedFile = Location of decrypted output file
Linux/OSX:
aws kms decrypt –ciphertext-blob fileb://$encryptedFile –output text –query Plaintext | base64 –decode > $decryptedFile
Windows:
aws kms decrypt –ciphertext-blob fileb://$sourceFile –output text –query Plaintext –region "us-east-1" > Temp.$decryptedFile.base64
certutil -decode Temp.$decryptedFile.base64 $decryptedFile
Voila! Simple as pie!
Envelope Encryption
With Envelope Encryption, we'll manage the encryption of our data using AES 256 encryption algorithm. First, we'll need to ask KMS to generate us a data key.
Generate Data Key:
To generate a unique Data Key:
- $key = A valid Encryption Key ID/ARN
- $encryptionSpec = A valid Encryption spec: AES_256 | AES_128
- $encryptedDataKeyFile = Location of encrypted output file
aws kms generate-data-key –key-id $key –key-spec AES_256 –output
text –query CiphertextBlob | base64 –decode > "$encryptedDataKeyFile"
We can now store our encrypted Data Key in a secure spot, preferably in a location that does not have easy access to our KMS Master Key.
Decrypt Data Key:
Now to use our new generated data key, we need to decrypt it via KMS, just like we did in simple encryption:
- $encryptedDataKeyFile = Encrypted data key file you want to decrypt
- $decryptedFile = Location of decrypted output file
aws kms decrypt –ciphertext-blob fileb://$encryptedDataKeyFile –output text –query Plaintext | base64 –decode > $decryptedFile
We'll use our decrypted data key whenever we want to encrypt or decrypt our actual secrets. I'll leave the implementation of AES encryption up to you.
Remember to clean up the unused files after our application is done with the secret.
Or even better, download and implement the above using an appropriate SDK. It's just as simple!