Symmetric Key Encryption in the Cloud

We are generally moving our security into the public cloud, and thus many of our keys are stored there. In AWS, we use KMS (Key Management…

https://asecuritysite.com

Symmetric Key Encryption in the Cloud

We are generally moving our security into the public cloud, and thus many of our keys are stored there. In AWS, we use KMS (Key Management System) and can create either symmetric keys or asymmetric keys (public keys).

Symmetric key

With symmetric key encryotion, Bob and Alice use the same encryption key to encrypt and decrypt. In the following case, Bob and Alice share the same encryption key, and where Bob encrypts plaintext to produce ciphertext. Alice then decrypts with the same key, in order to recover the plaintext:

Normally we use AES encryption for this. Initially in KMS, we create a new key within our Customer managed keys:

and then create the key:

Next, we give it a name:

And then define the administrative permission (those who can delete it):

And the usage:

The policy is then:

{
"Id": "key-consolepolicy-3",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::22222222:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::22222222:role/LabRole",
"arn:aws:iam::22222222:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor",
"arn:aws:iam::22222222:role/aws-service-role/events.amazonaws.com/AWSServiceRoleForCloudWatchEvents",
"arn:aws:iam::22222222:role/EMR_EC2_DefaultRole",
"arn:aws:iam::22222222:role/aws-service-role/elasticache.amazonaws.com/AWSServiceRoleForElastiCache",
"arn:aws:iam::22222222:role/aws-service-role/organizations.amazonaws.com/AWSServiceRoleForOrganizations",
"arn:aws:iam::22222222:role/EMR_DefaultRole",
"arn:aws:iam::22222222:role/EMR_AutoScaling_DefaultRole",
"arn:aws:iam::22222222:role/aws-service-role/cloud9.amazonaws.com/AWSServiceRoleForAWSCloud9",
"arn:aws:iam::22222222:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport"
]
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::22222222:role/LabRole",
"arn:aws:iam::22222222:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor",
"arn:aws:iam::22222222:role/aws-service-role/events.amazonaws.com/AWSServiceRoleForCloudWatchEvents",
"arn:aws:iam::22222222:role/EMR_EC2_DefaultRole",
"arn:aws:iam::22222222:role/aws-service-role/elasticache.amazonaws.com/AWSServiceRoleForElastiCache",
"arn:aws:iam::22222222:role/aws-service-role/organizations.amazonaws.com/AWSServiceRoleForOrganizations",
"arn:aws:iam::22222222:role/EMR_DefaultRole",
"arn:aws:iam::22222222:role/EMR_AutoScaling_DefaultRole",
"arn:aws:iam::22222222:role/aws-service-role/cloud9.amazonaws.com/AWSServiceRoleForAWSCloud9",
"arn:aws:iam::22222222:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport"
]
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "Allow attachment of persistent resources",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::22222222:role/LabRole",
"arn:aws:iam::22222222:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor",
"arn:aws:iam::22222222:role/aws-service-role/events.amazonaws.com/AWSServiceRoleForCloudWatchEvents",
"arn:aws:iam::22222222:role/EMR_EC2_DefaultRole",
"arn:aws:iam::22222222:role/aws-service-role/elasticache.amazonaws.com/AWSServiceRoleForElastiCache",
"arn:aws:iam::22222222:role/aws-service-role/organizations.amazonaws.com/AWSServiceRoleForOrganizations",
"arn:aws:iam::22222222:role/EMR_DefaultRole",
"arn:aws:iam::22222222:role/EMR_AutoScaling_DefaultRole",
"arn:aws:iam::22222222:role/aws-service-role/cloud9.amazonaws.com/AWSServiceRoleForAWSCloud9",
"arn:aws:iam::22222222:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport"
]
},
"Action": [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
],
"Resource": "*",
"Condition": {
"Bool": {
"kms:GrantIsForAWSResource": "true"
}
}
}
]
}

Now, we can create a file named 1.txt, and enter some text:

Once we have this, we can then encrypt the file using the “aws kms encrypt” command, and then use “fileb://1.txt” to refer to the file:

aws kms encrypt  --key-id alias/MySymKey   --plaintext fileb://1.txt   \
--query CiphertextBlob --output text > 1.out
echo "Ciphertext (Base64)"
cat 1.out

This produces a ciphertext blob, which is in Base64 format:

AQICAHgTBDpVTrBTrduWKdNnvMoMMUWjObqp+GqbghUx7qa6JwEQ7F2Fzubd+pcz3I06bFuLAAAAdjB0BgkqhkiG9w0BBwagZzBlAgEAMGAGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMgl3vWRVPyL7KK3klAgEQgDP+dQ4KsqT94hiARF8zlybFAtXJJBIucc8M952KHmkJzBGQQP4f8YQQ70DELV97ZXizzME=

We could transmit this in Base64 format, but we need to convert it into a binary format for us to now decrypt it. For this we use the “Base64 -d” command:

$ base64 -i 1.out  --decode > 1.enc
$ cat 1.enc

The result is a binary output:

$ cat 1.enc
x:UNSۖ)g
00e0` 1`He.0']3܍:l[v0t *H
]YOȾ+y%3u
D_3&$.q
i @@-_{exddd_v1_w_W3n_145559

Now we can decrypt this with our key, and using the command of:

$ aws kms decrypt --key-id alias/BillsNewKey --output text --query Plaintext \
--ciphertext-blob fileb://1.enc > 2.out

$ cat 2.out

The output of this is our secret message in Base64 format:

VGhpcyBpcyBteSBzZWNyZXQgZmlsZS4K

and now we can decode this into plaintext:

$ base64 -i 2.out  --decode
This is my secret file.

The commands we have used are:

aws kms encrypt  --key-id alias/BillsNewKey   --plaintext fileb://1.txt  \  
--query CiphertextBlob --output text > 1.out
echo "== Ciphertext (Base64)"
cat 1.out
echo "== Ciphertext (Binary)"
base64 -i 1.out --decode > 1.enc
cat 1.enc
aws kms decrypt --key-id alias/BillsNewKey --output text --query Plaintext \
--ciphertext-blob fileb://1.enc > 2.out
echo "== Plaintext (Base64)"
cat 2.out
echo "== Plaintext"
base64 -i 2.out --decode

and the result of this is:

== Ciphertext (Base64)
AQICAHgTBDpVTrBTrduWKdNnvMoMMUWjObqp+GqbghUx7qa6JwEfz+s9z3e0Mw0tOzuB5LuYAAAAdjB0BgkqhkiG9w0BBwagZzBlAgEAMGAGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMqqwXsxB5QlQGVqZWAgEQgDOyBv6KYg4wN2bU/ZKSJ+5opJXMrjQj9GGvuuD2/Jeto9Er5yS91/iCb896CzCSeqUYJeo=

== Ciphertext (Binary)
x:UNSۖ)g
00e0`v0t`He.0'=w*H
yBTVV3b07f'ḫ4#a+$oz
0z%

== Plaintext (Base64)
VGhpcyBpcyBteSBzZWNyZXQgZmlsZS4K

== Plaintext
This is my secret file.

Here’s a sample run in an AWS Foundation Lab environment:

Python encryption

Along with using the CLI, we can create the encryption using Python. In the following we use the boto3 library, and have a key ID of “98a90e1f-2cb5–4564-a3aa-d0c060cdcf0a” and which is in the US-East-1 region:

import base64
import binascii
import boto3

AWS_REGION = 'us-east-1'

def enable_kms_key(key_ID):
try:
response = kms_client.enable_key(KeyId=key_ID)

except ClientError:
print('KMS Key not working')
raise
else:
return response


def encrypt(secret, alias):
try:
ciphertext = kms_client.encrypt(KeyId=alias,Plaintext=bytes(secret, encoding='utf8'),
)
except ClientError:
print('Problem with encryption.')
raise
else:
return base64.b64encode(ciphertext["CiphertextBlob"])


def decrypt(ciphertext, alias):
try:
plain_text = kms_client.decrypt(KeyId=alias,CiphertextBlob=bytes(base64.b64decode(ciphertext)))
except ClientError:
print('Problem with decryption.')
raise
else:
return plain_text['Plaintext']

kms_client = boto3.client("kms", region_name=AWS_REGION)

KEY_ID = '98a90e1f-2cb5-4564-a3aa-d0c060cdcf0a'
kms = enable_kms_key(KEY_ID)
print(f'KMS key ID {KEY_ID} ')
msg='Hello'
print(f"Plaintext: {msg}")

cipher=encrypt(msg,KEY_ID)
print(f"Cipher {cipher}")
plaintext=decrypt(cipher,KEY_ID)
print(f"Plain: {plaintext.decode()}")

Each of the steps is similar to our CLI approach. A sample run gives:

KMS key ID 98a90e1f-2cb5-4564-a3aa-d0c060cdcf0a 
Plaintext: Hello
Cipher b'AQICAHgTBDpVTrBTrduWKdNnvMoMMUWjObqp+GqbghUx7qa6JwFvKVuh8YUJvpp0n+AGf4yiAAAAYzBhBgkqhkiG9w0BBwagVDBSAgEAME0GCSqGSIb3DQEHATAeBglghkg

Conclusions

We are moving to the Cloud, and our encryption keys are moving there too. Always make sure you limit the access to the keys, and possibly create a user account that has access to use them, and which is not the account that can delete the keys.

If your company wants to train staff in AWS, why not get in contact with us, as we are running the AWS Academy at Edinburgh Napier University.