What is a did:key?
A did:key is a self-contained digital identity. No server issues it. No authority approves it. It is a public key written in a standard format. It is who you are to the vault.
You never have to generate one manually. tn init creates it
for you the first time you run the SDK. The rest of this page is for the
curious and for anyone who wants to bring their own key.
The shape of it
A did:key is three parts glued together:
# the scheme, the method, the multibase-encoded public key
did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
^ ^ ^
| | ¦
| | → multibase-encoded public key (Ed25519, secp256k1, P-256, …)
| → method: this DID's data lives inline, not in a registry
→ a W3C Decentralized Identifier
Because the DID is the public key, anyone with the string can verify a signature from you. No lookup. No registry. No network round-trip. That is why the TN vault uses did:key as its account identifier: your DID is self-evident and the vault proves it with a single challenge-response.
The workflow
- Your machine generates a keypair locally: a private key that never leaves your disk, and a public key.
- The public key gets multibase-encoded and prefixed with
did:key:. That string is your DID. - You tell the vault "this is me" by presenting the DID.
- The vault replies with a random nonce.
- Your private key signs the nonce. The vault verifies the signature against the public key inside the DID.
- You get a JWT for the next 24 hours. No password was involved at any step.
When you run tn init, the SDK generates the keypair, writes it
to keys/local.private (locked down to your user), and derives
keys/local.public, which is your did:key. It then
registers that DID with the vault on first sync. Nothing to copy, nothing
to paste.
If you prefer to generate your own, read on.
Bring your own key
You might already have a keypair from a wallet, a hardware device, or another tool. Or you want to understand exactly what is happening under the hood. Either way, you need a small DID library.
didkit or py-multiformats
The SDK uses these internally. pip install didkit or use cryptography + manual multibase encoding.
@digitalbazaar/did-method-key
The reference implementation. Also try did-resolver + key-did-resolver from Ceramic.
ssi by Spruce
Production-grade did:key generation and verification. Compiles to WASM for browser use.
github.com/hyperledger/aries-framework-go
Includes a did:key resolver. Overkill if you only need generation, but battle-tested.
Generate one in Python
# using the same primitives the TN SDK uses
from cryptography.hazmat.primitives.asymmetric import ed25519
import base58
# 1. generate the keypair
priv = ed25519.Ed25519PrivateKey.generate()
pub = priv.public_key()
# 2. get the raw 32-byte public key
pub_bytes = pub.public_bytes_raw()
# 3. prefix with Ed25519 multicodec (0xed01) and multibase-encode (base58btc, z prefix)
multicodec = b"\xed\x01" + pub_bytes
did = "did:key:z" + base58.b58encode(multicodec).decode()
print(did)
# did:key:z6Mkhai...
Generate one with the TN CLI (easiest)
# one command, keys written to ./keys/
tn init my-project
# show me my DID
tn whoami
# did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
How the vault uses your DID
The vault treats your DID as the primary key for your account. The first time you authenticate, a row is created. From then on, any project you create, any key file you back up, and any pickup area you receive keys in is scoped to that DID.
You can also link additional DIDs to a single account. Useful if you have a device key on your laptop and another on your phone, or if you signed up with email/password and later added a hardware-backed did:key. Logging in with any linked identity returns the full account , projects, files, and all.
What about the private key. Is it backed up?
Yes. That is the whole point of the vault. Your private key and the rest of your ceremony get backed up so you can restore them on a new machine. Without that, losing your laptop means losing every identity and every group key you had.
The important part is how it gets backed up:
Your private key is wrapped client-side with a key derived from your device unlock secret (or hardware module, or recovery passphrase) before it is uploaded. The vault stores opaque ciphertext blobs. It has no way to read them.
When you run tn wallet restore on a new machine, the blobs
come back down and are decrypted locally using that same unlock
secret. The vault never touches plaintext key material at any point.
Signing vs. storing. Two different moments.
- At login: the private key signs a nonce on your machine. Only the signature leaves. The vault verifies it against the public half inside your DID.
- At backup: the private key is wrapped with your local unlock secret and the ciphertext is uploaded. The vault holds it, but cannot read it.
- At restore: the ciphertext comes back to a new machine, you provide the unlock secret, and the key is unwrapped locally.
So: the vault never sees your private key in the clear. It holds a locked copy on your behalf. If the vault is ever compromised, the attacker gets encrypted blobs they cannot open.
← Back to the vault