Tink: What format does tink give your keys in? Pem or der?

174 Views Asked by At

First time user of tink (and overall cryptography noob, but I'm learning)

I'm able to create a private key using

tinkey create-keyset --key-template [MY TEMPLATE] --out-format json --out foo.json

then once I have that file I try to create the public keyset via

tinkey create-public-keyset --in-format=json --in=foo.json

The output is

{"primaryKeyId":3104918340,"key":[{"keyData":{"typeUrl":"type.googleapis.com/google.crypto.tink.HpkePublicKey","value":"EgYIAxACGAIaYQTKiU+xhistDls5CMGMC311ZRfELnUGdfLXBx++SHiMOMOzsaFryaKljLlHHKegOeC6vbG8AXXpoPrvaouxtU5CgHCXGEczYwo9p/PHN4gKnJFfJJWCerzC5lEtV4SJUVo=","keyMaterialType":"ASYMMETRIC_PUBLIC"},"status":"ENABLED","keyId":3104918340,"outputPrefixType":"TINK"}]}

So now I need to send pem across the wire to a server, but my server team keeps telling me that I'm giving them an invalid pem document. I was under the understanding that the valud in the json above is pem format. Any tips?

2

There are 2 best solutions below

2
VonC On

As noted by President James K. Polk, you are not dealing with PEM in the first place.

The output you have shown is a JSON representation of a keyset, which is Tink's own format for storing keys. The value inside the value field is base64-encoded binary data, not PEM or DER formatted data.

Tink key objects are structured in a way that encapsulates all necessary information for cryptographic operations, including the key material itself and metadata like the key type, status, and key ID. The keyData field within a Tink key object contains the actual key material, encoded in a type-specific format and usually base64-encoded in JSON outputs.

So you would have to:

  • use the typeUrl field to understand the cryptographic algorithm and key type (e.g., RSA, ECDSA, AES).
  • decode the base64-encoded value field from the keyData object to get the raw key material.
  • use appropriate cryptographic libraries (depending on the key type) to interpret the raw key material and convert it into a standard format. For asymmetric keys like RSA or ECDSA, you would typically convert the key material into a key object and then serialize it to PEM format.

As a generic pseudo-code:

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
import base64
import json

# Placeholder: Load your Tink keyset JSON, identify the key type, and decode the key material
# That is very dependent on the key type and the specifics of the Tink key format

# Assuming you have the key material as a Python bytes object for an RSA key
key_material = b'...'  # That would be the result of decoding the base64 'value' for the correct key type

# Convert the RSA key material to an RSA key object (example)
# Again, you will need to adapt that, based on actual key type and format
public_key = serialization.load_der_public_key(key_material)

# Convert to PEM format
pem = public_key.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
)

print(pem.decode('utf-8'))
1
Jerico On

Neither its base64-encoded. Here is a good article from Google that goes over it: https://developers.google.com/tink/wire-format

It goes over the key's bites and stuff.