# Keys Public record of the cryptographic keys of Alexander Hess (i.e., "me" in this repository): What they are, how they are handled, and how to verify them. There are two audiences for this repository: - **I** want a how-to: [`OPENPGP.md`](OPENPGP.md) and [`AGE.md`](AGE.md) hold the policies and ceremonies, and the [`scripts/`](scripts/) run them. - **Readers** want to confirm my keys and my identity: Everything needed for that is in the [Verify](#verify) section below. ## Verify The fingerprint of my [current PGP key](public-key.asc) is in [`KEYS.md`](KEYS.md), which is signed. Compare the fingerprint with at least one source outside this repository to confirm my identity: - [WKD](https://wiki.gnupg.org/WKD), for example, via `gpg --locate-keys ah@alexander-hess.com` - The keyservers listed in [`OPENPGP.md`](OPENPGP.md), for example, `gpg --keyserver hkps://keys.openpgp.org --search-keys alexander@webartifex.de` - [`KEYS.md`](KEYS.md) obtained from my websites: - [alexander-hess.com](https://www.alexander-hess.com/KEYS.md) - [webartifex.de](https://www.webartifex.de/KEYS.md) Then: ```bash gpg --import public-key.asc gpg --verify KEYS.md.asc KEYS.md gpg --verify OPENPGP.md.asc OPENPGP.md gpg --verify AGE.md.asc AGE.md ``` Each `gpg --verify` will print two things: 1. `Good signature from "Alexander Hess <...>"`: The file is intact and was signed by this key. 2. `WARNING: This key is not certified with a trusted signature!`: Because `gpg` likely has no record that this key is mine. So, a good signature plus a matching `Primary key fingerprint` line is the full result. To silence the warning on your machine, tell `gpg` about your check: ```bash gpg --lsign-key # after comparing the fingerprint yourself ``` If you trusted one of the two keys I retired in 2026, they certified the current one, and the supersession is recorded in [`ceremonies/`](ceremonies/): ```bash gpg --import history/344EA5AB10D868E0-public.asc history/6D11C1E91D3B0265-public.asc gpg --check-signatures 8B1140ADB5185334E9FA513B75681C8167312680 gpg --verify ceremonies/2026-07-08_supersession.md.asc ceremonies/2026-07-08_supersession.md ``` ## Contents The files in this repository are described below. ### OpenPGP How I implement [OpenPGP](https://www.openpgp.org/): - [`KEYS.md`](KEYS.md): Current keys, signed - [`KEYS.md.asc`](KEYS.md.asc): Detached signature, renewed at every ceremony - [`OPENPGP.md`](OPENPGP.md): OpenPGP policies, ceremonies, and history - [`OPENPGP.md.asc`](OPENPGP.md.asc): Detached signature, renewed at every ceremony - [`public-key.asc`](public-key.asc): Armored export of the current OpenPGP key - [`snapshots/`](snapshots/): Yearly exports of the current OpenPGP key - [`ceremonies/`](ceremonies/): Signed records of exceptional events - [`history/`](history/): Armored public keys of all previous OpenPGP keys ### `age` Besides OpenPGP, I also use the modern [`age`](https://github.com/FiloSottile/age) encryption: - [`AGE.md`](AGE.md): `age` policies - [`AGE.md.asc`](AGE.md.asc): Detached signature, renewed at every ceremony - [`age-recipient.txt`](age-recipient.txt): `age` public key for `age -R` - [`ceremonies/`](ceremonies/): Signed record of when a recipient became valid or rotated because `age` keys carry no metadata of their own ### Scripts `sh` scripts for my own use: - [`bootstrap.sh`](scripts/bootstrap.sh): Imports and trusts all keys on a new machine, then verifies all files - [`sign.sh`](scripts/sign.sh): Renews the detached signatures - [`verify.sh`](scripts/verify.sh): Verifies all signed files against the pinned signing subkey, warns when the key is about to expire, and cross-checks `age-recipient.txt` - [`snapshot.sh`](scripts/snapshot.sh): Exports the current key to `snapshots/` and `public-key.asc` - [`publish.sh`](scripts/publish.sh): Pushes the current key to the keyservers