Generate a new PGP key
Document how the new key was created
This commit is contained in:
parent
1dbd62eb45
commit
0211c311d4
1 changed files with 113 additions and 8 deletions
121
KEYS.md
121
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 <ah@alexander-hess.com>` |
|
||||
| Other UID 1 | `Alexander Hess <alexander@webartifex.biz>` |
|
||||
| Other UID 2 | `Alexander Hess <alexander@webartifex.de>` |
|
||||
|
|
@ -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 <ah@alexander-hess.com>
|
||||
# passphrase: 32 random chars from Vaultwarden
|
||||
|
||||
gpg --edit-key <FPR>
|
||||
adduid # Alexander Hess <alexander@webartifex.biz>
|
||||
adduid # Alexander Hess <alexander@webartifex.de>
|
||||
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 <FPR>
|
||||
# => Vaultwarden login "Key Info" with all key IDs
|
||||
|
||||
gpg --gen-revoke <FPR>
|
||||
# reason 1 = compromised
|
||||
# => Vaultwarden note "Revocation Certificate"
|
||||
|
||||
gpg --armor --export-secret-keys <FPR>
|
||||
# => 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 <FPR> > /tmp/subkeys.asc
|
||||
gpg --delete-secret-keys <FPR>
|
||||
gpg --import /tmp/subkeys.asc
|
||||
gpg --list-secret-keys <FPR> # Must show sec# and two ssb!
|
||||
````
|
||||
|
||||
Re-passphrase the deployed subkeys with a memorable phrase
|
||||
for daily and headless signing:
|
||||
|
||||
````bash
|
||||
gpg --edit-key <FPR>
|
||||
passwd
|
||||
quit
|
||||
|
||||
gpg --armor --export-secret-subkeys <FPR> > /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 "<FPR>:6:" | gpg --import-ownertrust
|
||||
|
||||
gpg --list-secret-keys <FPR> # Must show sec# and two ssb!
|
||||
echo test | gpg --pinentry-mode loopback -u <S_SUBKEY_FPR>! --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
|
||||
```
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue