Skip to content

Manage your keys

Your identity is two cryptographic keys. You almost never touch them directly — TOVIO generates them silently when the repository gets an identity, and keeps them encrypted in your operating system's keychain. This guide explains what they are, where they live, how to add a second machine, and how to rotate them when you need to, without losing access to anything.

Phase 1 feature

Phase 1 identity creation, encrypted key storage, export/import/recovery, rotation, device enrollment, proof of possession, and key-transparency primitives are implemented. Enterprise threshold/KMS/HSM Key Authorities remain a v2 profile.

What your keys are

Every identity holds two independent keys, created together when the identity is provisioned — at tovio init --mode team (or agentic), or later by tovio identity init on a Simple repo:

  • An Ed25519 signing key — signs your commits, audit entries, and capability tokens. It proves you made a change.
  • An X25519 key-agreement key — receives the wrapped content keys that let you decrypt protected files. It is how protected content is made readable to you.

They do different jobs and are never interchangeable. You did not have to set either one up — there is no key ceremony — and a Simple-mode repository has neither, which is why it has no policies and no DID to manage.

Where your keys live

Your private keys are stored on your machine, encrypted at rest, under .tovio/ in your repository:

  • Identity private keys live under .tovio/identity/.
  • Cached wrapped/derived keys live under .tovio/keys/.

Both are sealed with a wrapping key held in your OS keychain — macOS Keychain, Windows Credential Manager, or the Linux Secret Service. The keychain holds the wrapping key; TOVIO holds the sealed blobs. Neither your private keys nor any content key are ever written into the synced object store, and they never travel over the network.

Your private key never leaves your machine

Because protected content is encrypted to your key, the key is the only thing that can read it. Back it up. Losing it is a data-loss event, not a re-clone — read recover a lost key before you ever need it, and make sure the recovery phrase init wrote for you is somewhere safe.

Check your key health

tovio key status lists the attribute certificates this identity holds — the value, its state, when it expires, and who issued it:

$ tovio key status
Identity did:key:559ebdc73461a50848b2020a2919dd25f973af54c00494114e46ea5976aa23fc — 2 attribute certificate(s):
  role=senior  [expiring]  expires 1796083200  issued by did:key:1a2b3c…
  team=payments  [valid]  no expiry  issued by you

A certificate's state is one of valid, expiring, expired, invalid-signature, or unknown-issuer — so a lapse and a certificate you cannot trust are distinguishable at a glance, and an issuer that is you is labelled you rather than repeating your DID. The expiry is printed as raw Unix seconds.

A repository owner who is their own Key Authority holds no certificates, and the command says so rather than showing an empty list:

$ tovio key status
Identity did:key:559ebdc73461a50848b2020a2919dd25f973af54c00494114e46ea5976aa23fc
  holds no attribute certificates (a self-sovereign owner / Key Authority, or none granted yet).

To confirm the key itself is present and sealed, use tovio identity show:

$ tovio identity show
Identity: did:key:559ebdc73461a50848b2020a2919dd25f973af54c00494114e46ea5976aa23fc
  key-agreement key (pk_kx):  0533099c724fa75ee101231825e1507e1c0231d5be792bf4839513a0f513d103
  secret sealed in keychain:  yes
  share .tovio/identity.pub so a teammate can `tovio access grant --identity <file>`.

A certificate about to lapse shows as [expiring] before it becomes [expired], and a denial caused by a lapsed — rather than missing — attribute is reported as TVO-KEY-001 by tovio access check. If you are the Key Authority, tovio key renew re-issues the caller-signed certificates you issued with a fresh window:

$ tovio key renew

Renewing your own certificate against a remote Key Authority is a follow-on

tovio key renew covers the self-KA (Team) case, where you issued the certificates yourself. Asking somebody else's Key Authority to renew a certificate it issued to you is not built; today the KA holder re-runs tovio access grant. Nor does tovio status carry an attribute-expiry banner — the expiry banners there are for agent tokens. Check tovio key status yourself, or act on the TVO-KEY-001 a denial reports.

Rotate your identity keys

Rotating means replacing your keypair with a fresh one while preserving continuity — old signatures stay verifiable, and you keep access to everything you could read before. Do this if you suspect your key was exposed, or on a routine schedule.

$ tovio key rotate

What happens, and why it is safe:

  • A rotation statement naming the old and new public keys is signed by your outgoing key. That signature proves the new key is really yours — a chain that fails verification is refused outright, and TOVIO will not admit an old key that arrives through it.
  • The protected content at HEAD is re-sealed to the new key, and your attribute claims are re-issued, before the keychain identity is swapped. New signatures use the new key.
  • Your old key is retained (still encrypted at rest) so pre-HEAD content wrapped only to it stays readable. TOVIO tries the current key-agreement secret first, then falls back through the retained old secrets, most-recent first. Nothing you could read becomes unreadable.
  • The whole sequence is crash-resumable: at every crash point the repository is readable by either the old or the new identity, and the rotation can be resumed or rolled back.

If you are the Key Authority

When the rotated identity is also the repository's Key Authority (the Solo/Team owner-is-KA case), rotation does more: every still-valid teammate attribute claim is re-issued under your new key, the rotation history is kept as a verified chain anchored at the repository's genesis key, and the audit log gains a signed key_rotate entry — signed by the new key and carrying the previous segment's head — that keeps the chain verifiable across the boundary. This is handled for you. Note the scope: rotation re-seals current HEAD, and older objects rely on old-key retention; a full-history re-seal is the separate tovio key recover path.

Add a second device

Do not copy your key to a second machine. Your identity is a stable principal plus a roster of enrolled devices, each holding its own secret that never leaves the machine it was generated on. That is what tovio device is for:

# on the new machine
$ tovio device enroll --name laptop
# it generates that device's own key and prints its public keys plus a pairing code
# copy the two public keys and the code across

# on a machine you already trust
$ tovio device approve --pubsig PUB_SIG --pubkx PUB_KX --code PAIRING_CODE

tovio device list shows the roster, and tovio device revoke drops a device and re-seals HEAD's protected content to the reduced set — so a lost laptop is a revocation, not a key rotation.

Back up the root device key

tovio key export and tovio key import are a different tool: a passphrase-encrypted backup of this identity's root device secret, for recovery after keychain loss, or for moving the root to a new machine as the same principal. They are not the way to add a second device.

$ tovio key export ./identity-backup.bin --passphrase-file ./pass.txt
# later, on the machine restoring the root
$ tovio key import ./identity-backup.bin --passphrase-file ./pass.txt

The passphrase must be read from a file — never a command-line argument or an environment variable, which would leave it in the process table and your shell history. The backup is AES-256-GCM under an Argon2id-derived key; move it over a trusted channel and delete both files when you are done. If the key itself is gone rather than merely unreachable, key import cannot help you — that is the tovio key recover path, which needs the separate recovery phrase.

Next steps

Last reviewed September 9, 2026

Suggest an improvement to this page Not for security reports — see disclosure