Three primitives. One curve family.
Identity is Ed25519, encryption is X25519 sealed-box, symmetric AEAD is XChaCha20-Poly1305. All libsodium-compatible. No bespoke constructions, no in-house crypto.
Identity — Ed25519
Every device has a single super_priv / super_pub Ed25519 keypair generated at fd0 init. super_pub is the account identifier (32 bytes, displayed as upIamMlsgn… in base32). super_priv never leaves the device unencrypted; the vault file holds it sealed under each enrolled auth method.
Encryption — X25519 + XChaCha20-Poly1305
For asymmetric flows (sealing the per-scope key to a teammate's card, recovery exports), fd0 derives an X25519 public key from the Ed25519 identity via the standard birational map and uses libsodium-compatible sealed-box. Symmetric encryption (vault body, AEAD-sealed secrets) uses XChaCha20-Poly1305 with 24-byte random nonces and the domain string as the associated data.
YubiKey-PIV X25519
On firmware ≥ 5.7, slot 9d holds an on-card X25519 keypair generated and bound to the card. fd0 wraps the symmetric vault key to that public key via ECDH; unwrap requires the card to perform the ECDH op on-chip. The slot private key never leaves the device. Optional touch + PIN policies apply per unwrap.
Determinism vs. malleability
Ed25519 signatures are deterministic. AEAD nonces are random per encryption, so the same plaintext under the same key produces a fresh ciphertext every time — but the determinism of the signature input means two clients signing the same event over the same prev_hash produce byte-identical signatures, simplifying replay detection.