The ceremony
Design phase: no ceremony command exists yet. This page describes what the commands will do (ADR 0002). The card library is piv-go; a spike (issue #26) still tests a primary key in a PIV slot.
A ceremony is a scripted, reviewable use of a root. It runs on the holder’s ordinary workstation, with no live CD and no air gap, because the root keys never leave their cards: a compromised workstation cannot copy a key it never holds. It can still try to trick the holder, which is why the checks below exist.
What the tool checks
Section titled “What the tool checks”- The card. Detect it, read its serial, and check the serial against the registry of known cards before anything is written.
- The attestation of every key it certifies. For a YubiKey on firmware 5.7 or newer the chain leads to Yubico Attestation Root 1 (
yubico-ca-1.pem) through Yubico’s intermediates; older cards chain to the earlier PIV root. A key that cannot be attested is refused, because an imported key cannot be attested (measured 2026-10-31). - What is about to be signed. Show the key’s fingerprint, its store, its lifetime and the serial before each touch. The holder confirms by comparing, not by pressing a button.
- The result. After signing, verify the certificate or binding against the request.
- The record. Write a hash-chained ceremony record that contains no PIN, no key and no secret.
A PIN is entered by the holder at the terminal. The tool never retries a wrong PIN and refuses to run when a retry counter is below three, because the card blocks after three attempts and then needs the PUK. PINs and admin PINs are kept in the holder’s password manager, one entry per card.
The three ceremonies
Section titled “The three ceremonies”| Ceremony | When | Card | Result |
|---|---|---|---|
| Yearly | Month 12 of the intermediates’ life | The card for the year | New 13-month certificates and subkey bindings, the card’s own root extended, a new keyring package and root list |
| Board add or replace | Between yearly ceremonies | The card for the year | A certificate and binding for the new board key |
| Root add, retire or revoke | A card is lost, retired or compromised | The surviving card | A new root, or a root list without the old one |
Each is a few commands. A lost root card walks through the last one.
A missed touch
Section titled “A missed touch”A missed touch comes back from the card after about 15 seconds as a generic security status, not as a touch timeout (measured 2026-10-31). Whether the tool reports it as “touch not received” is open.
Root validity and its extension
Section titled “Root validity and its extension”A root is valid for about three years, and each use extends it. The card that signs at a ceremony also extends its own root to about three years from that day:
- OpenPGP. A new self-signature on the primary moves its expiry.
- X.509. The root certificate is re-issued over the same key and the same subject, with a new validity.
- Pinning holds. Clients of the signed root list pin the public keys of the roots, not their certificates, and refuse a list with a lower version. A re-issued certificate has the same public key, so the pin holds.
- A dead or lost card shows itself. Its root is not extended, and runs out.
status warns about a root 6 months, 3 months and 30 days before it expires, with the exit codes 10, 11 and 12. Cards alternate, so a healthy root always has at least about a year left; a warning at 6 months means an extension was missed, with time left to act. The reasons are in ADR 0003.
Which code talks to the cards
Section titled “Which code talks to the cards”The CLI is written in Go, with piv-go as the card library. Both root keys of a card live in PIV slots: the X.509 root in slot 9c and the OpenPGP primary in a retired slot. ritueel builds the OpenPGP packets itself, and the card signs digests. That means one applet, one library and one binary, with no gpg or gpg-agent at run time, and the attestation works the same for both keys. The OpenPGP applet of the card stays free for the holder’s own daily use.
A spike on 2026-10-31 on two YubiKey 5 test cards (firmware 5.8.0, OpenPGP applet 3.4) compared the ways to reach the OpenPGP applet. It also showed that a key in a PIV slot makes back-signatures that gpg, gpgv and sqv accept. Findings that count against the other ways:
gpg2.2 binds an existing P-384 key as an encryption subkey, so a program has to build the binding packets itself either way.gpg2.2 sent two wrong PINs to a card, because it does not say which PIN it asks for.- A card key generated by
gpgalso gets encryption and authentication subkeys, which makes a 1,459-byte certificate against 766 bytes for a bare one.
Because every key is generated on the card, no key is ever in host memory, so the argument for a memory-safe helper that zeroises keys does not apply to key material.
Still to be shown: that certifications and bindings made by a primary held in a PIV slot are accepted by gpg, gpgv, sqv, apt and rpm. A spike runs this prototype test (issue #26).