# VIKINGS wiki

It's better when it's simple

User Tools

Site Tools


howtos:linuxbsd:gpg

Creating a GPG key (and Optional Transition from an old key)

Quick guide for GnuPG 2.2 or newer. Result: a certify-only Ed25519 primary key with separate signing and encryption subkeys. Chapter 4 is optional and only needed if you replace an existing key.

GnuPG/GPG? PGP? OpenGPG?

TL;DR: PGP and GPG are not the same. The proprietary PGP product plays no role in FLOSS today, but the OpenPGP standard does.

  • PGP (Pretty Good Privacy) is the original commercial program from 1991, now owned by Broadcom. The name is a trademark.
  • OpenPGP is the open standard that defines the key, message and signature formats.
  • GnuPG / GPG is the free/libre software implementation of OpenPGP, and gpg is its command-line program.

PGP and GnuPG are compatible because both implement OpenPGP. The precise terms are “OpenPGP key” and “GnuPG”. Many people say “PGP key” casually and mean an OpenPGP key. Others, like us, say “GPG key” and also mean an OpenPGP key. It can be confusing, but we are all talking about the same thing ;-)

1. Key layout

Key Algorithm Usage Expiry
Primary ed25519 C (certify only) never
Subkey 1 ed25519 S (sign) 2 years
Subkey 2 cv25519 E (encrypt) 2 years

The primary key only certifies. Daily work uses the subkeys. The primary key does not expire, the subkeys expire and are extended later.

2. Create the key

2.1 Primary key (certify only)

gpg --quick-generate-key 'Your Name <you@example.org>' ed25519 cert never

You will be asked for a passphrase.

2.2 Store the fingerprint

If the keyring already contains keys with the same address, pick the newest one:

export KEYFP=$(gpg --list-keys --with-colons you@example.org | awk -F: '/^pub/ {c=$6} /^fpr/ && c {print c, $10; c=""}' | sort -n | tail -1 | cut -d' ' -f2)
echo $KEYFP
gpg -K --keyid-format long $KEYFP

Check: ed25519, [C] and today's date. Do not copy fingerprints from web pages or chats, they may contain invisible characters. If in doubt: echo “$KEYFP” | xxd | head -2.

2.3 Add subkeys

gpg --quick-add-key $KEYFP ed25519 sign 2y
gpg --quick-add-key $KEYFP cv25519 encr 2y

Instead of 2y you can give an ISO date (YYYY-MM-DD) or a date with time (YYYYMMDDThhmmss). The time is interpreted as UTC, a trailing Z marks it explicitly. Example for 13:17 local time (CEST, UTC+2) on 2028-10-02:

gpg --quick-add-key $KEYFP ed25519 sign 20281002T111700Z

2.4 Trust and revocation certificate

gpg --edit-key $KEYFP
gpg> trust

Choose 5 (ultimate), confirm with y, then quit.

gpg --gen-revoke $KEYFP > revoke-new.asc

Store the revocation certificate offline.

2.5 Verify

gpg -K --keyid-format long $KEYFP
gpg --export $KEYFP | gpg --list-packets | grep -E 'sigclass|key flags'

Expected: sec [C], ssb [S], ssb [E]. Key flags: 01 for the primary key, 02 for the signing subkey, 0C for the encryption subkey.

3. Publish the new key

3.1 Export

gpg --armor --export $KEYFP > new-key.asc

3.2 Website

Publish new-key.asc (ASCII armor) and show the full fingerprint as text next to the download. Optional link:

<a rel="pgpkey" href="new-key.asc">PGP key</a>

3.3 Web Key Directory (optional)

The key must be binary (not armored) and named after the hash of the address:

gpg --with-wkd-hash -k you@example.org
gpg --no-armor --export $KEYFP > HASH

Place it at https://example.org/.well-known/openpgpkey/hu/HASH and add an empty file policy one level above. Test:

gpg -v --auto-key-locate clear,wkd,nodefault --locate-key you@example.org

3.4 Keyservers

Keys cannot be deleted from keyservers. Upload only when everything is verified.

gpg --keyserver hkps://keys.openpgp.org --send-keys $KEYFP

keys.openpgp.org shows an email address only after verification. For that, upload with:

gpg --export $KEYFP | curl -T - https://keys.openpgp.org

Open the returned link and confirm the mail. keys.openpgp.org does not distribute third-party signatures. For those, also upload to hkps://keyserver.ubuntu.com.

4. Optional: Transition from an old key

Only needed if the new key replaces an existing one (for example RSA to EC). Order matters: sign, announce, then revoke and publish.

4.1 Set variables

export OLDFP=$(gpg --list-keys --with-colons OLD_KEYID | awk -F: '/^fpr/ {print $10; exit}')
echo $OLDFP

Both $OLDFP and $KEYFP must be full 40-character fingerprints. –quick-sign-key rejects short key IDs (“is not a fingerprint”).

4.2 Cross-sign the keys

gpg --local-user $OLDFP --quick-sign-key $KEYFP
gpg --local-user $KEYFP --quick-sign-key $OLDFP
gpg --check-sigs $KEYFP
gpg --check-sigs $OLDFP

Each key must show a sig! line from the other key. All UIDs of the old key are signed.

4.3 Write the transition statement

Save as transition-YYYY-MM-DD.txt and insert the full fingerprints (gpg –fingerprint $OLDFP $KEYFP):

KEY TRANSITION STATEMENT - YYYY-MM-DD

I am transitioning from my old RSA key to a new key based on elliptic
curve cryptography (Ed25519 / Curve25519).

OLD KEY (revoked, do not use any more):
  rsa4096/OLD_KEYID, created YYYY-MM-DD
  <OLD FINGERPRINT>

NEW KEY:
  ed25519 (certify), created YYYY-MM-DD
  <NEW FINGERPRINT>

Reason: transition to elliptic curve cryptography.

The old key has been revoked as superseded. The new key is signed by the
old key, and the old key is signed by the new one. This statement is
signed with both keys.

Please fetch the new key, verify the fingerprint through a second
channel if possible, and stop encrypting to the old key.

Contact: you@example.org

Sign it with both keys:

gpg --local-user $OLDFP --local-user $KEYFP --clearsign transition-YYYY-MM-DD.txt
gpg --verify transition-YYYY-MM-DD.txt.asc

Two “Good signature” lines are expected. The warning “not a detached signature” is harmless when the plain .txt lies next to the .asc. Only the .asc is published.

The statement is optional but useful: a revocation reason is only a short note and does not tell people where to go, while the statement names the successor and is signed by both keys.

4.4 Revoke the old key

gpg --output revoke-old.asc --gen-revoke $OLDFP

Answers: y, reason 2 (Key is superseded), description e.g. Transition to elliptic curve key <NEW FINGERPRINT>, empty line, y, passphrase.

gpg --import revoke-old.asc
gpg -k --keyid-format long $OLDFP | head -3

The output must show [revoked: …]. Revocation is final once published. Keep the old key and its revocation, they are needed to verify old signatures and decrypt old data.

4.5 Publish

gpg --armor --export $OLDFP > old-key-revoked.asc
gpg --import-options show-only --import old-key-revoked.asc

The second command must list a rev line for the old key.

  • Website: add old-key-revoked.asc and transition-YYYY-MM-DD.txt.asc next to new-key.asc.
  • Keyservers: gpg –keyserver hkps://keys.openpgp.org –send-keys $OLDFP (and optionally keyserver.ubuntu.com).
  • WKD: serve only the new key.

4.6 Inform contacts

  • Send individual mails or use BCC.
  • Sign the mail with the new key, plain text.
  • Attach new-key.asc and transition-YYYY-MM-DD.txt.asc, name both fingerprints in the body.
  • Do not attach the old key, send at most the revoked version.
  • Ask important contacts to verify the fingerprint via a second channel.

5. Cleanup and maintenance

  • Switch Git signing, pass, SSH via GPG and similar tools to the new key.
  • Delete test and unused keys: gpg –delete-secret-and-public-key FINGERPRINT.
  • Remove stray key files with shred -u.
  • Extend the subkeys before they expire:
gpg --quick-set-expire $KEYFP 2y '*'
howtos/linuxbsd/gpg.txt · Last modified: by thum