Manage GnuPG securely

Manage GnuPG securely

27. Dezember 2025 0 Von admin

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.