Security¶
Antiphon's security story has two halves that never overlap: the vault protects everything at rest, and OpenPGP protects what travels. Neither invents cryptography; both orchestrate audited tools you already run.
The vault¶
Everything sensitive, the Maildir, the notmuch index, OAuth tokens and account state, lives inside an encrypted vault. The guarantee is simple: sealed at rest, open in session, ciphertext only off the machine. When the vault is locked, nothing but ciphertext exists on disk; a backup tool copying the store copies ciphertext and never sees your mail.
The store lives at $XDG_DATA_HOME/antiphon/store and the
vault mounts its decrypted view at exactly that path, so
nothing else needs to know whether a vault is present. Until
you set one up, that path is an ordinary directory;
antiphon doctor tells you which it is.
Backends¶
Chosen in config.toml under [vault] backend; auto picks
the right one for the platform.
| Backend | Platform | Notes |
|---|---|---|
apfs |
macOS | Encrypted APFS sparse image via hdiutil, AES-256, no admin rights |
luks2 |
Linux | LUKS2 container via cryptsetup; open and mount run through a narrow, documented sudo allowance |
gocryptfs |
any | FUSE, rootless, the portable reserve |
Unlocking and locking¶
The passphrase is the floor: every vault has one and it
always works. The daemon unlocks headlessly through
passphrase_cmd, a command that prints the passphrase, never
stored in config:
[vault]
backend = "auto"
passphrase_cmd = "pass show antiphon/vault"
idle_lock_minutes = 30 # 0 = open until the daemon stops
Any secret-printing command works: pass, secret-tool
lookup, or on macOS security find-generic-password -w -s
antiphon-vault (antiphon setup creates exactly that
Keychain item). The secret reaches the underlying tool over a
private channel, never on a command line another process
could read.
The vault opens when the daemon starts and stays open so mail
keeps arriving while the client is closed. antiphond seals it
on a clean stop, and, with idle_lock_minutes above zero,
after that many minutes without a client connection, pausing
sync until the next client connects and unlocks it.
Setting it up¶
# set backend and passphrase_cmd in [vault] first, then:
antiphon vault create # create and mount the vault
antiphon doctor --init-store # lay out the store inside it
antiphond & # unlocks on start, seals on stop
antiphon
antiphon vault create refuses to shadow an existing plain
store; migrate an unencrypted store by moving it aside,
creating the vault, and copying the mail back in while it is
mounted.
OpenPGP¶
Antiphon does OpenPGP with Sequoia end to end. Verification is pure Rust inside the client; private-key operations (signing, decryption) are delegated to your running gpg-agent over its own protocol, so your keyring, smartcard and pinentry work exactly as they do everywhere else. Antiphon never reads secret key material.
Verifying¶
Verification trusts a directory of certificates you curate:
$XDG_CONFIG_HOME/antiphon/pgp/. Drop .asc or .pgp
exports there:
gpg --armor --export alice@example.com \
> ~/.config/antiphon/pgp/alice.asc
The pager then shows Good signature from … when a message
verifies against a cert in the directory, Unknown signature
for signers you have not added (claiming neither good nor
bad), and BAD signature when a trusted key matches and the
content does not check out. Both PGP/MIME and inline
cleartext signatures are handled. There is no web-of-trust or
TOFU automation: a cert is trusted because you put it there,
nothing else.
Signing and encrypting¶
Signing is off by default and enabled per identity with
pgp_sign = true (optionally pinning pgp_key to a
fingerprint). :sign, :nosign, :encrypt and :noencrypt
override the default for the next message only, and the
compose status line shows the live plan.
Sealing happens through gpg-agent after the editor closes, so pinentry or a smartcard touch appears exactly where gpg would put it. Encryption requires a cert for every To and Cc address, signs inside the encryption layer, and aborts to a draft naming the problem if anything is missing or refused: plaintext is never sent silently where protection was asked for. Received encrypted mail decrypts through the agent when opened, and signatures inside are verified against the same keyring.
antiphon doctor reports the keyring size and whether
gpg-agent is reachable, with how many signing keys it holds.