Keypairs & signing
kovra can custody an asymmetric keypair: it generates the key, seals the private half under the vault master key, and never writes the private key to disk or prints it. You operate through kovra — signing, verifying, encrypting, decrypting — without the private key ever leaving the vault.
Generate a keypair
Section titled “Generate a keypair”kovra keygen creates the key and shows only the public half. Choose
ed25519 (signing and encryption) or rsa (signing/SSH only):
~ % kovra keygen secret:dev/ssh/deploy --type ed25519Generated dev/ssh/deploy (ed25519, Medium).ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDnM/+Nl+/2Y/uEZNK5Q7ZEdQEMmOGXB6PTQg2hWJaSwThe entry lists with a typed mode of keypair:ed25519. Reprint the public key
any time — this is free and never prompts:
~ % kovra pubkey secret:dev/ssh/deployssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDnM/+Nl+/2Y/uEZNK5Q7ZEdQEMmOGXB6PTQg2hWJaSwSign and verify
Section titled “Sign and verify”kovra sign signs data from a file or stdin; the signature goes to stdout.
kovra verify checks it. Signing with a high/prod key asks you to
bioProve it; verifying is
always free:
~ % printf 'release v1.2.3' | kovra sign secret:dev/ssh/deploy > sig.bin~ % printf 'release v1.2.3' | kovra verify secret:dev/ssh/deploy --signature sig.binOK: signature is validVerification also works against a public-only entry — a peer’s public key you
stored with kovra add --public-key (it holds no private half), so you can verify
a colleague’s signatures without their private key.
Pass --reason to say what the signature is for. It works the same with a file or with stdin:
~ % kovra sign secret:dev/ssh/deploy --reason "Release manifest v1.2.3" manifest.md > manifest.sigThe reason is one line of at most 200 characters. kovra refuses it with exit code 2, before it opens the key or asks you, when it is empty, longer, or has a line break, a control, format, bidi, combining or invisible character, or a space other than the plain one; letters with accents pass. kovra preflight sign <coord> --reason "<text>" checks it the same way, so an agent learns beforehand that a reason would be refused.
What a signature approval shows
Section titled “What a signature approval shows”Every signature that asks you — with a high, inject-only or prod key — shows what is signed, with or without --reason:
- A sentence of kovra’s own: who asks, the file name (or standard input), its size and kind (text, PDF or binary), and the key with its environment. The details (environment, project, secret, who asks, command) follow in grey.
- The SHA-256 of the exact bytes the key signs, shown short: its first and last six characters,
ebbda6 … fb9e9c. Compare them withshasum -a 256 <file>of the file you meant to sign. The document window and the macOS dialog show all 64 characters. - A hidden-characters warning (⚠ The document has 2 hidden characters — review it before approving) when a text has characters that change or hide how it reads: bidi controls, zero-width characters, control characters, a carriage return that does not end a line. Review the document before approving.
- The reason, last, under Reason given by the requester — kovra does not verify it. The caller wrote it, and the caller may be a hijacked agent: read it as a claim, not as a fact.
Review the document
Section titled “Review the document”On the Mac, Review document… opens the document in a separate kovra window. It shows the bytes kovra read and is about to sign: the file is never read again, so changing it afterwards changes nothing.
- Text (up to 256 KiB): the source, with line numbers, never cut at the edge. Hidden characters show as escapes (
\u{202e}), each listed under the header with its line and what it does. - Markdown and HTML (a file ending in
.md,.markdown,.htmlor.htm): two tabs, Source and Rendered, and the window opens on Rendered. The source is what is signed: the rendered view can hide content (an HTML comment, a link’s real destination, hidden text), as its banner says. Check Source before approving. - PDF (up to 8 MiB): rendered for reading; links, forms and scripts do nothing. A PDF can show less than it contains, so the SHA-256 is the exact statement of what is signed.
- Binary data, a larger document, or one kovra can’t show (a text too long once escaped, a PDF that does not open or is encrypted): not shown, never even a fragment. The window says why; compare the SHA-256 instead.
You can’t approve while the document window is open: the sensor’s place reads Close the document to approve (without Touch ID, Approve with Touch ID is greyed out). Close it with its close button, ⌘W or Esc, and the review window takes the focus back: the sensor arms on its own after a moment, with no click. If another program took the focus or covered either window while you were reading, click the review window first, as usual. The time to answer keeps running while you read.
On the paired phone, kovra Mobile shows the full SHA-256, the hidden-characters warning when there is one and the reason, and says the document is shown at the Mac only: the document never leaves your Mac. To read it, approve at the Mac.
Encrypt and decrypt
Section titled “Encrypt and decrypt”For an ed25519 keypair, kovra can also encrypt to the public key and decrypt
with the private key (an age-based sealed box). Encrypting is free;
decrypting with a high/prod key asks you to bioProve it:
~ % printf 'a short secret note' | kovra encrypt secret:dev/ssh/deploy > ct.bin~ % kovra decrypt secret:dev/ssh/deploy ct.bina short secret noteRSA keypairs sign and verify (and work as SSH keys) but do not support
encryption — use ed25519 when you need sealing.
Why this matters
Section titled “Why this matters”The private key is generated inside the vault and never materializes on disk or in your shell. An agent or a script can ask kovra to use the key — sign a release, open a sealed message — but cannot exfiltrate it, and every use of a sensitive key is gated and audited. For loading a key into an SSH session, see the governed ssh-agent.