How many encryption and signing key formats are there? The answer to this — is a great deal. Why? Well, these days we can wrap an encryption key with a JSON format, and which provides additional information on how the encryption key can be used.
For a computer, these keys are 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 its 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.
Let’s look at creating key for AES, DHKEM (Hybrid ML-KEM), ECDSA, ECIES, Ed25519, HKDF, HMAC, JWT, RSA PKCS#1 v1.5, RSA PSS and XChaCha20:
For this, we can use tinkey to run:
$ java -jar "tinkey_deploy.jar" create-keyset - key-template AES128_EAX - out-format JSON - out 1.json
$ cat 1.json
{"primaryKeyId":2180785869,"key":
[{"keyData":{
"typeUrl":"type.googleapis.com_google.crypto.tink.AesEaxKey",
"value":"EgIIEBoQkkUmFOG1mkQFBTuuLyy6Mw==",
"keyMaterialType":"SYMMETRIC"},
"status":"ENABLED",
"keyId":2180785869,
"outputPrefixType":"TINK"}]
}
The code is here:
Google Tink with Go (PRF)For AES_EAX [here]:
{
"primaryKeyId": 1396503152,
"key": [
{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.AesEaxKey",
"value": "EgIIEBoQ6RkAIuX/Atj/SkqcpswobA==",
"keyMaterialType": "SYMMETRIC"
},
"status": "ENABLED",
"keyId": 1396503152,
"outputPrefixType": "TINK"
}
]
}
For ChaCha20 [here]:
{
"primaryKeyId": 1961123280,
"key": [
{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.ChaCha20Poly1305Key",
"value": "EiBGO18rw7WEmiWmDhWtdeLh9yifxqh8ZiRkEc+w0Axaxw==",
"keyMaterialType": "SYMMETRIC"
},
"status": "ENABLED",
"keyId": 1961123280,
"outputPrefixType": "TINK"
}
]
}
For DH-ML-KEM [here]:
{
"primaryKeyId": 471886363,
"key": [
{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.HpkePrivateKey",
"value": "EksSBggCEAEYARpBBEPwo/feGpb3vlP+PqHmfNcyx4MFiUhmgI6UTlYeOE3CuPlPEr29y10xpEnU7Rbz/68rC/DKtIQgj9wxSqy2jIAaINRX8U+vDAMHohP7pB0eL4APBLGucNXmrNQ/LlKTXMde",
"keyMaterialType": "ASYMMETRIC_PRIVATE"
},
"status": "ENABLED",
"keyId": 471886363,
"outputPrefixType": "TINK"
}
]
}
For ECDSA [here]:
{
"primaryKeyId": 1264604753,
"key": [
{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey",
"value": "Ek4SBggDEAIYAhohADjXTBYypwLxLyv16U1Cjc65bOThbbuy6fLUW/KRPW2+IiEAeNVl+SBSsCTcan65Ak/INw0LxdA7QjxYjhlUwV9jv18aIQDt6E9K9l2uTaMqrptTL+fwMsy4jErqNQrzTLsYB242GQ==",
"keyMaterialType": "ASYMMETRIC_PRIVATE"
},
"status": "ENABLED",
"keyId": 1264604753,
"outputPrefixType": "TINK"
}
]
}
For Ed25519 [here]:
{
"primaryKeyId": 548270440,
"key": [
{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey",
"value": "EiBgPvg/MifqxLPxSSJNDX2sVf1vmsXTqA+adiDVHI5LaBoiEiBN/JwLTuGB1fan3TCMBLXPx6aeMhNQ7t/tpJXltxpZiQ==",
"keyMaterialType": "ASYMMETRIC_PRIVATE"
},
"status": "ENABLED",
"keyId": 548270440,
"outputPrefixType": "TINK"
}
]
}
For RSA PSS [here]:
{
"primaryKeyId": 744063254,
"key": [
{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey",
"value": "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",
"keyMaterialType": "ASYMMETRIC_PRIVATE"
},
"status": "ENABLED",
"keyId": 744063254,
"outputPrefixType": "TINK"
}
]
}