Manage GnuPG securely
This article is about GnuPG setup from scratch and show how to manage the entire lifecycle securely. Here is a comprehensive overview of all the steps and commands, including the security best practices.
Chapter 1: Initial Setup and Key Creation
This stage establishes your key pair and trust level.
Create Master Key Pair incl. encryption subkey
gpg --full-gen-key
On the following dialog you use ECC algorithms (ed25519 for signing, cv25519 for encryption) and chose option (9) ECC (sign, encryption) standard. You set an expiration date (e.g., 5 years) for forward compatibility. Finally you choose a strong, unique passphrase!
Create signing Subkey
Do not use the Master Key for signing in your daily work. Create an additional separate subkey for signing (S).
gpg --edit-key <KEY-ID>
gpg\> addkey
You type addkey and then option (10) ECC (only sign).
Then you check the generated Master Key including the subkeys
gpg --list-secret-keys
sec ed25519 2025-12-25 [SC] [verfällt: 2030-12-24]
C957EA3BD909D1D3BA594D2CE14085D8197A0018
uid [ ultimativ ] Patrick Rottlaender [patrick@rottlaender.eu](mailto:patrick@rottlaender.eu)
ssb cv25519 2025-12-25 [E] [verfällt: 2030-12-24]
ssb ed25519 2025-12-25 [S] [verfällt: 2030-12-24]
sec: The secret master key (sec) is for Signing and Certification (SC).
KEY-ID: C957EA3BD909D1D3BA594D2CE14085D8197A0018.
ssb: The first subkey (ssb) is for encryption (E).
ssb: The second subkey (ssb) is for signing (S).
All Keys expire at 2030-12-24.
Set Trust Level
As you can see above my trust level is already ultimate. So here just for completion the command how to set the trust level on your keys.
Mark your own key as ultimately trusted so GnuPG relies on your certifications (key separation, subkey creation).
gpg --edit-key <KEY-ID>
gpg\> trust
Then type trust and select option 5 (ultimate).
Chapter 2: Security and Hardening
This stage prepares the necessary backups and secures the master key.
Backup the Master Key and generate Revocation Certificate
Do this immediately and store the fullback-up file and the revocation certificate file offline.
gpg --export-secret-keys --armor <KEY-ID> > fullbackup.asc
gpg --output revocation.asc --gen-revoke <KEY-ID>
Implement Key Separation
Check the key setup again to identify clearly your 3 Key-IDs. Here we use the long format command.
gpg --list-secret-keys --keyid-format long
sec ed25519/E14085D8197A0018 2025-12-25 \[SC] \[verfällt: 2030-12-24]
C957EA3BD909D1D3BA594D2CE14085D8197A0018
uid [ ultimativ ] Patrick Rottlaender [patrick@rottlaender.eu](mailto:patrick@rottlaender.eu)
ssb cv25519/AF0CB4F423538B80 2025-12-25 [E] [verfällt: 2030-12-24]
ssb ed25519/56025D0BF8BF5B2F 2025-12-25 [S] [verfällt: 2030-12-24]
Master Key-ID (SC): E14085D8197A0018
Subkey 1-Key-ID (E): AF0CB4F423538B80
Subkey 2-Key-ID (S): 56025D0BF8BF5B2F
The goal is: Remove the Master Secret Key (sec) from your local machine using the delete command, turning it into a stub (sec#). This protects the core of your identity from malware. Keep both Subkeys for daily encryption (E) and signing (S).
Before you run the delete command, you must be 100% certain your backup file is valid. If you delete the master key now without a verified backup, you are back to the fatal „lost key“ situation. Run the following 2 checks.
Check 1:
gpg --list-packets /path/to/fullbackup.asc | grep "secret key packet"
:secret key packet:
The output must! show:
:secret key packet:
Check 2:
gpg --list-packets /path/to/fullbackup.asc
off=0 ctb=94 tag=5 hlen=2 plen=134
:secret key packet:
version 4, algo 22, created 1766645842, expires 0
pkey[0]: [80 bits] ed25519 (1.3.6.1.4.1.11591.15.1)
pkey[1]: [263 bits]
iter+salt S2K, algo: 7, SHA1 protection, hash: 2, salt: E5DD0BCA22F746A5
protect count: 65011712 (255)
protect IV: d6 b2 c9 5d e2 3f 05 d3 35 fb cc 7b 87 41 cf f5
skey[2]: [v4 protected]
keyid: E14085D8197A0018
# off=136 ctb=b4 tag=13 hlen=2 plen=44
:user ID packet: "Patrick Rottlaender [patrick@rottlaender.eu](mailto:patrick@rottlaender.eu)"
# off=182 ctb=88 tag=2 hlen=2 plen=153
:signature packet: algo 22, keyid E14085D8197A0018
version 4, created 1766645842, md5len 0, sigclass 0x13
digest algo 10, begin of digest f0 54
hashed subpkt 33 len 21 (issuer fpr v4 C957EA3BD909D1D3BA594D2CE14085D8197A0018)
hashed subpkt 2 len 4 (sig created 2025-12-25)
hashed subpkt 27 len 1 (key flags: 03)
hashed subpkt 9 len 4 (key expires after 5y0d0h0m)
hashed subpkt 11 len 4 (pref-sym-algos: 9 8 7 2)
hashed subpkt 34 len 1 (pref-aead-algos: 2)
hashed subpkt 21 len 5 (pref-hash-algos: 10 9 8 11 2)
hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
hashed subpkt 30 len 1 (features: 07)
hashed subpkt 23 len 1 (keyserver preferences: 80)
subpkt 16 len 8 (issuer key ID E14085D8197A0018)
data: [256 bits]
data: [255 bits]
# off=337 ctb=9c tag=7 hlen=2 plen=139
:secret sub key packet:
version 4, algo 18, created 1766645842, expires 0
pkey[0]: [88 bits] cv25519 (1.3.6.1.4.1.3029.1.5.1)
pkey[1]: [263 bits]
pkey[2]: [32 bits]
iter+salt S2K, algo: 7, SHA1 protection, hash: 2, salt: 2DE27015BEF91567
protect count: 65011712 (255)
protect IV: f8 13 05 2b 8d a0 97 0d 22 99 3b b5 c3 62 43 be
skey[3]: [v4 protected]
keyid: AF0CB4F423538B80
# off=478 ctb=88 tag=2 hlen=2 plen=126
:signature packet: algo 22, keyid E14085D8197A0018
version 4, created 1766645842, md5len 0, sigclass 0x18
digest algo 10, begin of digest fc 2e
hashed subpkt 33 len 21 (issuer fpr v4 C957EA3BD909D1D3BA594D2CE14085D8197A0018)
hashed subpkt 2 len 4 (sig created 2025-12-25)
hashed subpkt 27 len 1 (key flags: 0C)
hashed subpkt 9 len 4 (key expires after 5y0d0h0m)
subpkt 16 len 8 (issuer key ID E14085D8197A0018)
data: [254 bits]
data: [256 bits]
# off=606 ctb=9c tag=7 hlen=2 plen=134
:secret sub key packet:
version 4, algo 22, created 1766645997, expires 0
pkey[0]: [80 bits] ed25519 (1.3.6.1.4.1.11591.15.1)
pkey[1]: [263 bits]
iter+salt S2K, algo: 7, SHA1 protection, hash: 2, salt: 09FD8782B037DC77
protect count: 65011712 (255)
protect IV: e3 fc 51 3f 7d 35 f8 78 a9 43 72 fe 73 f9 82 16
skey[2]: [v4 protected]
keyid: 56025D0BF8BF5B2F
# off=742 ctb=88 tag=2 hlen=2 plen=245
:signature packet: algo 22, keyid E14085D8197A0018
version 4, created 1766645997, md5len 0, sigclass 0x18
digest algo 10, begin of digest fe 58
hashed subpkt 33 len 21 (issuer fpr v4 C957EA3BD909D1D3BA594D2CE14085D8197A0018)
hashed subpkt 2 len 4 (sig created 2025-12-25)
hashed subpkt 27 len 1 (key flags: 02)
hashed subpkt 9 len 4 (key expires after 5y0d0h0m)
subpkt 16 len 8 (issuer key ID E14085D8197A0018)
subpkt 32 len 117 (signature: v4, class 0x19, algo 22, digest algo 10)
data: [256 bits]
data: [256 bits]
This is the expected output: You expect 3 packets most important is the :secret key packet:
Master Key package:
:secret key packet: secret master key packet with KeyID: E14085D8197A0018
:signature packet: This show the signature packet belonging to your secret key packet and issuer key ID E14085D8197A0018
Subkey 1 Key package:
:secret sub key packet: secret subkey packet with KeyID: AF0CB4F423538B80
:signature packet: This show the signature packet belonging to your secret sub key packet and issuer key ID E14085D8197A0018
Subkey 2 Key package:
:secret sub key packet: secret subkey packet with keyid: 56025D0BF8BF5B2F
:signature packet: This show the signature packet belonging to your secret sub key packet and issuer key ID E14085D8197A0018
Only in case :secret key packet: is available proceed!
GnuPG does not have a single command like —delete-only-master key. Instead, the standard „clean“ way to do this is a three-step process.
Step 1: Export ONLY your Secret Subkeys in a temporary subkeys-only file
gpg --export-secret-subkeys --armor E14085D8197A0018 > subkeys-only.asc
Step 2: Delete the current Secret Key (complete wipe) from your MacBook
gpg --delete-secret-keys E14085D8197A0018
Step 3: Import the Secret Subkeys
gpg --import subkeys-only.asc
Step 4: Remove the temporary subkeys-only file
rm subkeys-only.asc
Then check your local setup.
gpg --list-secret-keys
sec# ed25519 2025-12-25 [SC] [verfällt: 2030-12-24]
C957EA3BD909D1D3BA594D2CE14085D8197A0018
uid [ ultimativ ] Patrick Rottlaender <patrick@rottlaender.eu>
ssb cv25519 2025-12-25 [E] [verfällt: 2030-12-24]
ssb ed25519 2025-12-25 [S] [verfällt: 2030-12-24]
Here you see your Master Secret Key (sec) has been removed from your local machine and turning it into a stub (sec#).
Chapter 3: Reset and Restore (Scenario: Start From Scratch)
These steps show how to completely wipe your local key and restore it using the backup.
Delete Complete Key Set (Local Wipe)
Use both commands to ensure both the remaining subkeys and the Public Key are completely removed from your local keyring before restoring.
gpg --delete-secret-keys <KEY-ID> (Deletes subkeys/stubs)
gpg --delete-keys <KEY-ID> (Deletes public key)
Import Complete Key Set (Restore)
Use the verified backup file created in Step 2 to fully restore your Master Key and Subkeys back to the pre-separation state.
First you check the fullback file before you run the import.
#Check the backupfile
gpg --show-keys /path/to/fullbackup.asc
sec ed25519 2025-12-25 [SC] [verfällt: 2030-12-24]
C957EA3BD909D1D3BA594D2CE14085D8197A0018
uid [ ultimativ ] Patrick Rottlaender [patrick@rottlaender.eu](mailto:patrick@rottlaender.eu)
ssb cv25519 2025-12-25 [E] [verfällt: 2030-12-24]
ssb ed25519 2025-12-25 [S] [verfällt: 2030-12-24]
#run the import
gpg --import /path/to/fullbackup.asc
Chapter 4: Useful commands
List public keys
gpg –list-keys
pub ed25519 2025-12-25 [SC] [verfällt: 2030-12-24]
C957EA3BD909D1D3BA594D2CE14085D8197A0018
uid [ ultimativ ] Patrick Rottlaender [patrick@rottlaender.eu](mailto:patrick@rottlaender.eu)
sub cv25519 2025-12-25 [E] [verfällt: 2030-12-24]
sub ed25519 2025-12-25 [S] [verfällt: 2030-12-24]
List secret keys
gpg –list-secret-keys
sec ed25519 2025-12-25 [SC] [verfällt: 2030-12-24]
C957EA3BD909D1D3BA594D2CE14085D8197A0018
uid [ ultimativ ] Patrick Rottlaender [patrick@rottlaender.eu](mailto:patrick@rottlaender.eu)
ssb cv25519 2025-12-25 [E] [verfällt: 2030-12-24]
ssb ed25519 2025-12-25 [S] [verfällt: 2030-12-24]
List public keys showing all KeyIDs
gpg --list-keys --keyid-format long
pub ed25519/E14085D8197A0018 2025-12-25 [SC] [verfällt: 2030-12-24]
C957EA3BD909D1D3BA594D2CE14085D8197A0018
uid [ ultimativ ] Patrick Rottlaender [patrick@rottlaender.eu](mailto:patrick@rottlaender.eu)
sub cv25519/AF0CB4F423538B80 2025-12-25 [E] [verfällt: 2030-12-24]
sub ed25519/56025D0BF8BF5B2F 2025-12-25 [S] [verfällt: 2030-12-24]
List secret keys showing all KeyIDs
gpg --list-secret-keys --keyid-format long
sec ed25519/E14085D8197A0018 2025-12-25 [SC] [verfällt: 2030-12-24]
C957EA3BD909D1D3BA594D2CE14085D8197A0018
uid [ ultimativ ] Patrick Rottlaender [patrick@rottlaender.eu](mailto:patrick@rottlaender.eu)
ssb cv25519/AF0CB4F423538B80 2025-12-25 [E] [verfällt: 2030-12-24]
ssb ed25519/56025D0BF8BF5B2F 2025-12-25 [S] [verfällt: 2030-12-24]
Master Key (SC): E14085D8197A0018
Subkey 1 (E): AF0CB4F423538B80
Subkey 2 (S): 56025D0BF8BF5B2F
Encrypt
gpg -e -r patrick@rottlaender.eu file.txt
Decrypt
gpg -d file.txt.gpg > file.txt
Sign & Encrypt
gpg -se -r recipient@email.com file.txt
Decrypt & Verify
#shows the signature status automatically
gpg -d file.txt.gpg
Chapter 5: General note
ed25519 and cv25519 are algorithms based on Curve25519
ed25519 (Master Key & Signing Subkey)
Feature Description
Full Name: Edwards-curve Digital Signature Algorithm over Curve25519.
Cryptographic Role: Digital Signing and Verification. It is designed to create a mathematical signature that proves the origin (authenticity) and integrity of a message or file.
GnuPG Use: Used for your Master Key ([C]) to certify other keys, and your Signing Subkey ([S]) to sign emails or commits.
Security Property: It is highly resistant to various side-channel attacks and has a very reliable, straightforward implementation.
cv25519 (Encryption Subkey)
Feature Description
Full Name: Curve25519 variant used for Key Exchange.
Cryptographic Role: Key Exchange and Encryption. It is designed for the Diffie-Hellman (DH) key exchange process, which allows two parties to securely establish a shared secret (like a session key) over an insecure channel.
GnuPG Use: Used for your Encryption Subkey ([E]). It enables others to encrypt data to you, and you to decrypt it using the established session key.
Security Property: Highly efficient and designed specifically for confidential (private) communication.
Modern GnuPG key management strictly separates cryptographic roles signing and encryption for security reasons:
• You sign with ed25519: To prove you are the one you are (in my case I am Patrick!).
• You encrypt with cv25519: To ensure privacy.
This separation of duties means if one subkey were ever theoretically broken, it wouldn’t automatically compromise the function of the other key. For example, if your signing key (ed25519) was compromised, your ability to decrypt past files or conversations (protected by cv25519) would remain secure.
