From 0211c311d457ec39f8152418886fa762407c4eb4 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Wed, 8 Jul 2026 15:29:55 +0200 Subject: [PATCH] Generate a new PGP key Document how the new key was created --- KEYS.md | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 113 insertions(+), 8 deletions(-) diff --git a/KEYS.md b/KEYS.md index d61e0ee..0b2ebc8 100644 --- a/KEYS.md +++ b/KEYS.md @@ -13,18 +13,19 @@ gpg --verify KEYS.md.asc KEYS.md ## Current Key -> PLACEHOLDER +> [`8B11 40AD B518 5334 E9FA 513B 7568 1C81 6731 2680`](https://keys.openpgp.org/vks/v1/by-fingerprint/8B1140ADB5185334E9FA513B75681C8167312680) + on OpenPGP | Field | Value | |-------------|-------------------------------------------------------| -| Fingerprint | `XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX` | -| Key ID | `XXXXXXXXXXXXXXXX` (fingerprint's last 16 chars) | +| Fingerprint | `8B11 40AD B518 5334 E9FA 513B 7568 1C81 6731 2680` | +| Key ID | `75681C8167312680` (fingerprint's last 16 chars) | | Primary | ed25519 `[C]` OFFLINE (i.e., `sec#` on all machines) | | Subkey 1 | cv25519 `[E]` | | Subkey 2 | ed25519 `[S]` internal | -| Created | 2026-MM-DD | -| Expires | always **End of January** (next: 2027-MM-DD) | +| Created | 2026-07-08 | +| Expires | always **End of January** (next: 2027-01-31) | | Primary UID | `Alexander Hess ` | | Other UID 1 | `Alexander Hess ` | | Other UID 2 | `Alexander Hess ` | @@ -34,8 +35,8 @@ gpg --verify KEYS.md.asc KEYS.md | Key ID | Type | Purpose | Expires | |--------------------|------|----------------------------|------------| -| `XXXXXXXXXXXXXXXX` | E | encryption | 2027-01-31 | -| `XXXXXXXXXXXXXXXX` | S | signing on my own machines | 2027-01-31 | +| `253A7FFDDF34BE5E` | E | encryption | 2027-01-31 | +| `B46EDB4DFC26805D` | S | signing on my own machines | 2027-01-31 | ### Policies @@ -81,7 +82,7 @@ gpg --verify KEYS.md.asc KEYS.md ### Publication to Keyservers ````bash -FPR=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +FPR=8B1140ADB5185334E9FA513B75681C8167312680 for KS in \ hkps://keys.openpgp.org \ @@ -98,3 +99,107 @@ done => Click the links mailed to all addresses - *Hockeypuck* servers (the other four) are append-only: They merge and never delete => Run after *every* change + + +## Ceremonies + +- The `gpg-agent` caches passphrases + => Run `gpg-connect-agent reloadagent /bye` + before any step that must actually prompt +- Over `ssh`, the import may hang, + for example, if the agent tries to raise a graphical pinentry + => `gpgconf --kill gpg-agent` and `gpg ... --pinentry-mode loopback` + (Note: `loopback` asks for a new passphrase only ONCE without confirmation) +- Scratch keyrings isolate any step from the main keyring: + +```bash + # Disposable $GNUPGHOME + T=$(mktemp -d) + chmod 700 "$T" + + # To scope any operation to "$T" + gpg --homedir "$T" ... + + # To stop the scratch agent + gpgconf --homedir "$T" --kill gpg-agent + rm -rf "$T" +``` + + +### To generate a brand-new Key + +This section documents how we created the current key in the first place. + +````bash +gpg --expert --full-generate-key +# (11) ECC (set your own) => toggle S off => only Certify => (1) Curve 25519 +# expiry: end of NEXT January +# UID: Alexander Hess +# passphrase: 32 random chars from Vaultwarden + +gpg --edit-key + adduid # Alexander Hess + adduid # Alexander Hess + uid 1 # Select the UID to become the default... + primary # ...and flag it + addkey # (12) ECC (encrypt only) => Curve 25519 => same expiry + addkey # (10) ECC (sign only) => Curve 25519 => same expiry + save + +gpg --list-secret-keys --with-subkey-fingerprints +# => Vaultwarden login "Key Info" with all key IDs + +gpg --gen-revoke +# reason 1 = compromised +# => Vaultwarden note "Revocation Certificate" + +gpg --armor --export-secret-keys +# => Vaultwarden note "Full Secret Key" +```` + +Ensure everything goes into **Vaultwarden**. +Verify the keys from Vaultwarden *before* the destructive part below. + +Split the keys so that machines only ever hold the subkeys + while the primary secret key stays in Vaultwarden only: + +````bash +gpg --armor --export-secret-subkeys > /tmp/subkeys.asc +gpg --delete-secret-keys +gpg --import /tmp/subkeys.asc +gpg --list-secret-keys # Must show sec# and two ssb! +```` + +Re-passphrase the deployed subkeys with a memorable phrase + for daily and headless signing: + +````bash +gpg --edit-key + passwd + quit + +gpg --armor --export-secret-subkeys > /tmp/subkeys-deploy.asc +# => Vaultwarden note "Deployed Secret Keys" +```` + +Verify the deploy keys from Vaultwarden with a scratch keyring, + sign test with the memorable phrase, + then distribute to the machines: + +```bash +# On each machine: +gpgconf --kill gpg-agent +gpg --import subkeys-deploy.asc +echo ":6:" | gpg --import-ownertrust + +gpg --list-secret-keys # Must show sec# and two ssb! +echo test | gpg --pinentry-mode loopback -u ! --sign -o /dev/null + +shred -u subkeys-deploy.asc +``` + +Finally, clean up the temporary files: + +```bash +shred -u /tmp/subkeys.asc /tmp/subkeys-deploy.asc +```