There are the steps to create GPG key pair and the additional steps to create a subkey.
gpg --full-generate-key
Please select what kind of key you want:
(1) RSA and RSA
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(9) ECC (sign and encrypt) *default*
(10) ECC (sign only)
(14) Existing key from card
Your selection? 9
Please select which elliptic curve you want:
(1) Curve 25519 *default*
(4) NIST P-384
(6) Brainpool P-256
Your selection? 1
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Once have a key pair we can create a subkey
gpg --edit-key 6BA43BDD3E73CD57855B9D77DEDE5447A7ABB295
gpg> addkey
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(10) ECC (sign only)
(12) ECC (encrypt only)
(14) Existing key from card
Your selection? 10
Please select which elliptic curve you want:
(1) Curve 25519 *default*
(4) NIST P-384
(6) Brainpool P-256
Your selection? 1
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 0
gpg> save
Repeat above for each machine to have their own, different signing key.
Export keys for offline backup:
gpg --output public.gpg.txt --armor --export 6BA43BDD3E73CD57855B9D77DEDE5447A7ABB294
gpg --output secret.gpg.txt --armor --export-secret-keys 6BA43BDD3E73CD57855B9D77DEDE5447A7ABB294
Get subkey ID's.
gpg --list-secret-keys --keyid-format=long
sec ed25519/xyz 2025-01-01 [SC]
6BA43BDD3E73CD57855B9D77DEDE5447A7ABB294
uid [ unknown] Name <[email protected]>
ssb cv25519/abc 2025-01-01 [E]
ssb ed25519/def 2025-01-01 [S]
ssb ed25519/ghi 2025-01-01 [S]
Generate one signing subkey for each machine. Note the exclaimation mark after the ID.
gpg --output machine1.gpg.txt --armor --export-secret-subkeys def!
gpg --output machine2.gpg.txt --armor --export-secret-subkeys ghi!
Delete the primary key.
gpg --delete-secret-keys 6BA43BDD3E73CD57855B9D77DEDE5447A7ABB294
gpg --delete-keys 6BA43BDD3E73CD57855B9D77DEDE5447A7ABB294
Finally import the subkey
gpg --import machine1.gpg.txt
Verify
gpg --list-secret-keys --keyid-format=long
sec# ed25519/xyz 2025-01-01 [SC]
6BA43BDD3E73CD57855B9D77DEDE5447A7ABB294
uid [ unknown] Name <[email protected]>
ssb ed25519/def 2025-01-01 [S]
The sec#
means a subkey is loaded.