JSON and Encryption Keys

So what does an encryption key look like these days? Well, it depends on whether you are a computer or a human. For a computer, it is just…

JSON and Encryption Keys

So what does an encryption key look like these days? Well, it depends on whether you are a computer or a human. For a computer, it is just a bunch of 1’s and 0’s, but for humans, we are not so good at interpreting binary. Two common formats are DER (binary) and PEM (Base64). When interpreted as hexadecimal, DER looks something like this [here]:

The PEM format is a little more structured with a special header and footer, and with Base64 text in between:

None of these file formats gives much away about the details of the key, such as i’s identifier, the type of encryption used, and so on. And so the JSON format is often used to view a key, and Google Tink is a great place to view the key. With this we can define a symmetric key, and where we give the key and ID, and then define the key type (as we can use a range of encryption methods). In the following we use an AES GCM key: [link]

{
"primaryKeyId": 1331912396,
"key": [{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey",
"keyMaterialType": "SYMMETRIC",
"value": "GhBpskWWTrE27e2w67X4TzfS"
},
"outputPrefixType": "TINK",
"keyId": 1331912396,
"status": "ENABLED"
}]
}

The key is “GhBpskWWTrE27e2w67X4TzfS”. The hexadecimal format is:

1A1069B245964EB136EDEDB0EBB5F84F37D2

and which is 36 hex characters, and which is 144 bits. This gives 128 bits for the key and a few extra bits for some parameters.

For a MAC (Message Authentication Code), we use a shared secret key and then can use this to check the signature of the message [here]. Again in this case we are generating a 128-bit AES GCM key [here]:

{
"primaryKeyId": 1331912396,
"key": [{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey",
"keyMaterialType": "SYMMETRIC",
"value": "GhBpskWWTrE27e2w67X4TzfS"
},
"outputPrefixType": "TINK",
"keyId": 1331912396,
"status": "ENABLED"
}]
}

In a digital signing, we use a key pair (a public key and a private key). The private key is used to sign for a message, and then the public key proves the signer. In this case, we create an Elliptic Curve key pair on the sender side [link]:

{
“primaryKeyId”: 438545957,
“key”: [{
“keyData”: {
“typeUrl”: “type.googleapis.com/google.crypto.tink.EcdsaPrivateKey”,
“keyMaterialType”: “ASYMMETRIC_PRIVATE”,
“value”: “Ek0SBggDEAIYAhohAP4v0pziVF9He/fn8BgApUHOu2Y1TkMcejrYC4U24M3xIiBAf0AIU72H5uVIP1S6ULGLaDf4td3/RIb4F58z2Md/khogJsuTDxaY/Q0CmENKlTQIOCXEZ+qvdAW0Rkvix6Wehl4=”
},
“outputPrefixType”: “TINK”,
“keyId”: 438545957,
“status”: “ENABLED”
}]
}

We then extract the public key to prove the signing:

{
“primaryKeyId”: 438545957,
“key”: [{
“keyData”: {
“typeUrl”: “type.googleapis.com/google.crypto.tink.EcdsaPublicKey”,
“keyMaterialType”: “ASYMMETRIC_PUBLIC”,
“value”: “EgYIAxACGAIaIQD+L9Kc4lRfR3v35/AYAKVBzrtmNU5DHHo62AuFNuDN8SIgQH9ACFO9h+blSD9UulCxi2g3+LXd/0SG+BefM9jHf5I=”
},
“outputPrefixType”: “TINK”,
“keyId”: 438545957,
“status”: “ENABLED”
}]
}

The hexadecimal format is this is 12060803100218021A2100FE2FD29CE2545F477BF7E7F01800A541CEBB66354E431C7A3AD80B8536E0CDF12220407F400853BD87E6E5483F54BA50B18B6837F8B5DDFF4486F8179F33D8C77F92, and which is 154 hexadecimal characters (616 bits — which is made up of a 512-bit public key and a few extra bytes to define the format of the key).

And in many applications, we use a hybrid approach, where we can protect the symmetric key with a key pair. In the following we use ECIES encryption to protect the symmetric key we create and then use the public key[link]. The private key is then used to decrypt the symmetric key:

{
“primaryKeyId”: 1992984960,
“key”: [{
“keyData”: {
“typeUrl”: “type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey”,
“keyMaterialType”: “ASYMMETRIC_PUBLIC”,
“value”: “EkQKBAgCEAMSOhI4CjB0eXBlLmdvb2dsZWFwaXMuY29tL2dvb2dsZS5jcnlwdG8udGluay5BZXNHY21LZXkSAhAQGAEYARohAOaHVTjvjhpGaHv5mhuXz3Nc+Mb7RE5sMyAsv7YCB8UjIiAOaSLbqRE7ddVM14kWiNoPWB/U2MNluwLlAjw39zwAlw==”
},
“outputPrefixType”: “TINK”,
“keyId”: 1992984960,
“status”: “ENABLED”
}]
}

And there’s a method that allows you to authenticate your encryption using additional data, such as the sequence number of a data packet or the TCP port used. This is named authenticated encryption with associated data (AEAD), and here’s an example key using AES-SIV [here]:

{
"primaryKeyId": 1428191678,
"key": [{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.AesSivKey",
"keyMaterialType": "SYMMETRIC",
"value": "EkAFkhmlhYkmClmpz/vGzojJVgA/IQIMSty7rL8TXxyu9m/W0ZtzCddmSLFj7r8V/R0CywJ89KxdMVzdR+GDQH2w"
},
"outputPrefixType": "TINK",
"keyId": 1428191678,
"status": "ENABLED"
}]
}

So there you go, your encryption keys can be viewed in JSON.

AWS KMS

In AWS KMS (Key Management Store), we use an ARN (Amazon Resource Reference) reference, such as:

arn:aws:kms:us-east-1:713702076703:key/
c1ef5c60-b186-4a43-a71e-f3d55c211e5earn:aws:kms:us-east-1:103269750866:
alias/MySymKey

The key itself is stored in the HSM (Hardware Security Module). When we encrypt, we can then just use the alias:

aws kms encrypt  --key-id alias/MySymKey   
--plaintext fileb://1.txt --query CiphertextBlob
--output text > 1.out

We can see it has an alias for that we can define a simple name for it. In KMS, we also define a use policy for the key:

{
"Id": "key-consolepolicy-3",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::103269750866:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::103269750866:user/asecuritysite",
"arn:aws:iam::103269750866:user/s3bucketuser",
"arn:aws:iam::103269750866:role/AWS-QuickSetup-StackSet-Local-AdministrationRole",
"arn:aws:iam::103269750866:user/bill",
"arn:aws:iam::103269750866:user/ses-smtp-user.20200705-105358",
"arn:aws:iam::103269750866:user/ses-smtp-user.20200621-094554",
"arn:aws:iam::103269750866:user/dbuser",
"arn:aws:iam::103269750866:role/AmazonEC2RoleforSSM",
"arn:aws:iam::103269750866:role/aws-ec2-spot-fleet-tagging-role",
"arn:aws:iam::103269750866:user/ses-smtp-user.20200620-112942"
]
},
"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::103269750866:user/asecuritysite",
"arn:aws:iam::103269750866:user/s3bucketuser",
"arn:aws:iam::103269750866:role/AWS-QuickSetup-StackSet-Local-AdministrationRole",
"arn:aws:iam::103269750866:user/bill",
"arn:aws:iam::103269750866:user/ses-smtp-user.20200705-105358",
"arn:aws:iam::103269750866:user/ses-smtp-user.20200621-094554",
"arn:aws:iam::103269750866:user/dbuser",
"arn:aws:iam::103269750866:role/AmazonEC2RoleforSSM",
"arn:aws:iam::103269750866:role/aws-ec2-spot-fleet-tagging-role",
"arn:aws:iam::103269750866:user/ses-smtp-user.20200620-112942"
]
},
"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::103269750866:user/asecuritysite",
"arn:aws:iam::103269750866:user/s3bucketuser",
"arn:aws:iam::103269750866:role/AWS-QuickSetup-StackSet-Local-AdministrationRole",
"arn:aws:iam::103269750866:user/bill",
"arn:aws:iam::103269750866:user/ses-smtp-user.20200705-105358",
"arn:aws:iam::103269750866:user/ses-smtp-user.20200621-094554",
"arn:aws:iam::103269750866:user/dbuser",
"arn:aws:iam::103269750866:role/AmazonEC2RoleforSSM",
"arn:aws:iam::103269750866:role/aws-ec2-spot-fleet-tagging-role",
"arn:aws:iam::103269750866:user/ses-smtp-user.20200620-112942"
]
},
"Action": [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
],
"Resource": "*",
"Condition": {
"Bool": {
"kms:GrantIsForAWSResource": "true"
}
}
}
]
}

For public-key encryption, we obviously need to extract the public key. We can do this with a PEM form [here]:

But also extract as a JSON format [here]:

% aws kms get-public-key --key-id alias/PublicKeyForDemo
{
"KeyId": "arn:aws:kms:us-east-1:103269750866:key/de30e8e6-c753-4a2c-881a-53c761242644",
"PublicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsXDtHOdCeteObzugPf6ENjeft6CDGjbaR9t40++q4jqtSd5JsdYel1Rn3mYL+oXqKQJz9o+aoXdCcMFkhu6wqqDVbIOPT2nsXIuO3p+0G7uUS93g3cc5RodEAn3jb2yBjHjvfs9OBSBM7bh6Kw21YuN/omU1GaL/d4o7+NYu0mDEAmb0Nh+1Q6lrpf+bu1YZ31gVpbLd78xGlv1dz2nqyBG8VaZW90fr05jDjcpDnWm1O9QXl0pEhwNGcvcsxcHodslAZrlzKUre/nZ5MTNL3uigw8w5l2uQLRFiIBpLlHKpcNBaxZu3Za5Mk2Dvj+1+L2PejLydAPfqQB5N8dsOAQIDAQAB",
"CustomerMasterKeySpec": "RSA_2048",
"KeySpec": "RSA_2048",
"KeyUsage": "ENCRYPT_DECRYPT",
"EncryptionAlgorithms": [
"RSAES_OAEP_SHA_1",
"RSAES_OAEP_SHA_256"
]
}

Conclusions

The beauty of JSON is that we can define fields using a key-value format, and can then encapsulate virtually any data object. As it is a text-based format, it is easy for us to port from one system to another. So, it’s PEM for the core key elements, but JSON allows for the key and all the associated metadata.