GPG
await dv.view("00Meta/Views/NoteBanner");
Note — +
> ABOUT_THIS_NOTEAdvanced, copy-ready GnuPG reference for local key management, signing, encryption, verification, and automation. Examples favour full fingerprints, explicit signing identities, and deliberate recipient lists. Commands were checked against the installed GnuPG 2.5.21 client.
Note — +
> SAFETY_BOUNDARYris:ShieldCheck
- A fingerprint identifies a key; it is safe to share after independent verification. A private key, passphrase, decrypted data, and private-key backup are not.
- Never delete a secret key before an encrypted offline backup and revocation certificate exist.
- Keyservers are effectively append-only. Revoking a compromised published key is possible; reliably removing it from all keyservers is not.
// ADVANCED_OPERATOR_QUICKSTART fas:ClipboardList
1. Use full fingerprints and explicit identities
# Replace every placeholder with a full 40-hex-character OpenPGP fingerprint.
export YOUR_FPR='0123456789ABCDEF0123456789ABCDEF01234567'
export RECIPIENT_FPR='89ABCDEF0123456789ABCDEF0123456789ABCDEF'
# Show the secret keys that can sign and public keys that can encrypt.
gpg --list-secret-keys --keyid-format LONG --with-fingerprint
gpg --list-keys --keyid-format LONG --with-fingerprint
Note — + Why fingerprints matter
fas:Lightbulbris:LockPasswordA short key ID is not a unique trust anchor. Verify a full fingerprint through an independent channel, then use that fingerprint with--local-user(-u) and--recipient(-r).
2. Sign with a non-default private key
# Detached, ASCII-armored signature: creates file.pdf.asc
gpg --local-user "$YOUR_FPR" --detach-sign --armor file.pdf
# Detached binary signature: creates file.pdf.sig
gpg --local-user "$YOUR_FPR" --detach-sign file.pdf
# Embedded binary signature: creates file.pdf.gpg
gpg --local-user "$YOUR_FPR" --sign file.pdf
# Human-readable cleartext signature: creates message.txt.asc
gpg --local-user "$YOUR_FPR" --clearsign message.txt
Note — + Signing selection
ris:FileListris:Command
--local-user/-uchooses the signing identity and overridesdefault-key.--detach-signkeeps the original file unchanged and is the normal choice for software artifacts.--armorproduces portable text output; omit it for compact binary output.
3. Encrypt to explicit public keys
# Binary encrypted output: creates file.pdf.gpg
gpg --recipient "$RECIPIENT_FPR" --encrypt file.pdf
# ASCII-armored encrypted output: creates file.pdf.asc
gpg --recipient "$RECIPIENT_FPR" --armor --encrypt file.pdf
# Encrypt to several people; each listed recipient can decrypt.
gpg --recipient "$RECIPIENT_FPR" \
--recipient "$YOUR_FPR" \
--armor --encrypt file.pdf
Note — + Include yourself deliberately
fas:TriangleExclamationEncryption only includes the recipients you specify, plus any separately configuredencrypt-torecipient. If you encrypt only to someone else, you may be unable to decrypt your own output later. Add your verified encryption-capable key as another--recipientwhen you need future access.
4. Encrypt and sign with different keys
# Sign as YOUR_FPR; encrypt only for the recipient.
gpg --local-user "$YOUR_FPR" \
--recipient "$RECIPIENT_FPR" \
--sign --encrypt file.pdf
# Sign as YOUR_FPR; encrypt for the recipient and yourself.
gpg --local-user "$YOUR_FPR" \
--recipient "$RECIPIENT_FPR" \
--recipient "$YOUR_FPR" \
--armor --sign --encrypt file.pdf
5. Verify and decrypt safely
# Verify a detached signature against its original file.
gpg --verify file.pdf.asc file.pdf
# Verify an embedded signature.
gpg --verify signed-file.gpg
# Decrypt to a deliberate output path.
gpg --output decrypted-file.pdf --decrypt file.pdf.gpg
Note — + What a successful verification proves
ris:CheckboxCircleA good signature proves that a matching private key signed the bytes you verified. It does not establish a real-world identity until you have independently verified the signing key’s fingerprint and trust context.
// DEFAULT_KEY_&_RECIPIENT_CONTROL ris:LockPassword
1. Understand the four settings
| Setting | Effect | Prefer for intentional workflows |
|---|---|---|
default-key <FPR> | Default signing identity when --local-user is omitted | Explicit --local-user "$YOUR_FPR" |
default-recipient <FPR> | Encrypts to this key when --recipient is omitted | Explicit --recipient "$RECIPIENT_FPR" |
default-recipient-self | Uses the default signing key as encryption recipient when recipients are omitted | Add your own --recipient "$YOUR_FPR" explicitly |
encrypt-to <FPR> | Always adds this recipient to encryption, even when --recipient is supplied | Explicit recipient list when you need predictable output |
2. Remove a configured default key without deleting the key
# Locate the active GnuPG home and open the primary configuration file.
gpgconf --list-dirs homedir
"${EDITOR:-vi}" "$(gpgconf --list-dirs homedir)/gpg.conf"
Remove or comment out each directive you do not want, for example:
# default-key 0123456789ABCDEF0123456789ABCDEF01234567
# default-recipient 0123456789ABCDEF0123456789ABCDEF01234567
# default-recipient-self
# encrypt-to 0123456789ABCDEF0123456789ABCDEF01234567
# Inspect the defaults reported by the current configuration.
gpgconf --list-options gpg | grep -E '^(default-key|default-recipient|encrypt-to):'
# One-command override: disable recipient defaults for this invocation only.
gpg --no-default-recipient --recipient "$RECIPIENT_FPR" --encrypt file.pdf
Note — + Removing a default is not deleting a key
fas:TriangleExclamation
- Removing
default-keyonly clears the configured signing preference. If you omit--local-user, GnuPG can still fall back to the first usable secret key.--no-default-recipientresetsdefault-recipientanddefault-recipient-selffor one command; do not put it ingpg.conf.- For repeatable work, always specify both the signer and every intended recipient on the command line.
3. Delete a key from the local keyring — separate, destructive action
# First: create an encrypted secret-key backup and an offline revocation certificate.
gpg --armor --output "${YOUR_FPR}.secret.asc" --export-secret-keys "$YOUR_FPR"
gpg --output "${YOUR_FPR}.revocation.asc" --generate-revocation "$YOUR_FPR"
# Review the exact fingerprint, then remove the local secret and public key.
gpg --fingerprint "$YOUR_FPR"
gpg --delete-secret-and-public-key "$YOUR_FPR"
Note — + Deletion checklist
fas:Skull
- Store the exported private key and revocation certificate offline, encrypted, and separately from the passphrase.
- Deletion removes the key from this local keyring; it does not retract a public key already uploaded to a keyserver.
- If the key is compromised rather than simply unused, publish the revocation certificate after validating its contents.
// SCRIPTING_&_ISOLATED_KEYRINGS fas:Terminal
1. Machine-readable listings and status output
# Stable machine-readable key listing; do not parse the human-facing --list-keys output.
gpg --batch --with-colons --with-fingerprint --list-keys "$RECIPIENT_FPR"
# Capture structured status lines while verifying a detached signature.
gpg --batch --status-fd 1 --verify file.pdf.asc file.pdf 2>/dev/null
2. Test an import in a disposable GnuPG home
export TEST_GNUPGHOME="$(mktemp -d)"
chmod 700 "$TEST_GNUPGHOME"
gpg --homedir "$TEST_GNUPGHOME" --import candidate-key.asc
gpg --homedir "$TEST_GNUPGHOME" --with-fingerprint --list-keys
# Remove this temporary directory only after reviewing the imported key.
if [ -n "$TEST_GNUPGHOME" ] && [ -d "$TEST_GNUPGHOME" ]; then
rm -rf -- "$TEST_GNUPGHOME"
fi
unset TEST_GNUPGHOME
Note — + Automation rules
ris:RadarUse--batch,--status-fd, and--with-colonsfor scripts. Do not feed passphrases on the command line; use a controlled pinentry, agent, or a carefully designed file descriptor workflow instead.
Quick Reference Command Matrix
This table summarizes ALL GPG operations covered in this cheatsheet.
Note — - 📋 Quick Reference Cheat Sheet
# Category Command Purpose Key Flags 1 Key Generation gpg --gen-keyGenerate new key pair (simplified) Interactive prompts 2 Key Generation gpg --full-generate-keyGenerate key with full options Choose algorithm, size, expiry 3 Key Generation gpg --quick-generate-key "Name <email>" ed25519 sign 1yGenerate Ed25519 key programmatically Modern algorithm 4 Key Listing gpg --list-keysList all public keys Alias: gpg -k5 Key Listing gpg --list-secret-keysList all private keys Alias: gpg -K6 Key Listing gpg --list-keys --keyid-format longList keys with long IDs Shows full key IDs 7 Key Export gpg --export -a <key-id>Export public key (ASCII) -a= armor (text format)8 Key Export gpg --export-secret-keys -a <key-id>Export private key (ASCII) Keep secure! 9 Key Import gpg --import <file>Import key from file Public or private 10 Key Import gpg --recv-keys <key-id>Download key from keyserver Requires keyserver config 11 Key Upload gpg --send-keys <key-id>Upload key to keyserver Makes key discoverable 12 Key Search gpg --search-keys "email@example.com"Search keyserver for key Requires keyserver 13 Key Deletion gpg --delete-key <key-id>Delete public key Cannot have secret key 14 Key Deletion gpg --delete-secret-key <key-id>Delete private key Must be done first 15 Key Editing gpg --edit-key <key-id>Interactive key editor Commands: trust, expire, passwd 16 Key Info gpg --fingerprint <key-id>Show key fingerprint For verification 17 Encryption (Asymmetric) gpg -e -r <recipient> <file>Encrypt file for recipient Creates .gpgfile18 Encryption (Asymmetric) gpg -e -a -r <recipient> <file>Encrypt with ASCII armor Creates .ascfile19 Encryption (Symmetric) gpg -c <file>Encrypt with passphrase No keys needed 20 Encryption (Symmetric) gpg -c --armor <file>Symmetric encryption (ASCII) Password-based 21 Decryption gpg -d <file>Decrypt file to stdout Displays decrypted content 22 Decryption gpg -o <output> -d <file>Decrypt to specific file -o= output path23 Signing (Binary) gpg -s <file>Sign file (binary format) Creates .gpg24 Signing (Clear) gpg --clearsign <file>Sign with readable message Creates .asc25 Signing (Detached) gpg -b <file>Create detached signature Creates .sig26 Signing (Detached ASCII) gpg -b -a <file>Detached signature (ASCII) Creates .asc27 Sign + Encrypt gpg -se -r <recipient> <file>Sign then encrypt Combined operation 28 Verification gpg --verify <file>Verify embedded signature Checks authenticity 29 Verification gpg --verify <sig> <file>Verify detached signature Two separate files 30 Revocation gpg --gen-revoke --output revoke.asc <key-id>Generate revocation certificate Create immediately 31 Trust Management gpg --update-trustdbRebuild trust database After key changes 32 Agent Control gpgconf --kill gpg-agentRestart GPG agent Fix cache issues 33 Configuration gpg --list-configShow configured options Debugging 34 Diagnostics gpg --check-trustdbCheck trust database integrity Troubleshooting
Key Terminology:
- ASCII Armor: Text-based encoding for binary GPG data (flag:
-aor--armor) - Key ID: Unique identifier for a GPG key (short: 8 hex chars, long: 16 hex chars, fingerprint: 40 hex chars)
- Keyring: Database storing all your GPG keys (
~/.gnupg/) - Passphrase: Password protecting your private key
- Recipient: Person you’re encrypting a message for (flag:
-r) - Web of Trust: Decentralized trust model based on key signing
- Subkey: Secondary key for specific operations (can be rotated without changing master key)
- Revocation Certificate: Document that invalidates a key if compromised
Understanding GnuPG and Public Key Cryptography
- GnuPG (GNU Privacy Guard) is a complete and free implementation of the OpenPGP standard as defined by RFC 4880.
- It provides hybrid encryption combining the convenience of public-key cryptography with the speed of symmetric encryption.
- Public-key cryptography uses two mathematically related keys: 4. Public key: Shared openly, used by others to encrypt messages to you or verify your signatures 5. Private key: Kept secret, used to decrypt messages sent to you or create digital signatures
- The Web of Trust model allows users to certify each other’s keys through signatures, building a decentralized trust network without central authorities.
- Use cases include: 8. Encrypting sensitive emails and documents 9. Digitally signing code releases and Git commits 10. Authenticating software downloads via detached signatures 11. Securing SSH authentication using GPG keys 12. Encrypting password manager databases
- GPG operates on the principle of confidentiality (encryption prevents unauthorized reading), authenticity (signatures prove sender identity), and integrity (tampering detection).
Security Model and Cryptographic Algorithms
- GPG supports multiple public-key algorithms: 2. RSA: Traditional algorithm, minimum 2048-bit (4096-bit recommended) 3. Ed25519: Modern elliptic curve algorithm, faster and more secure with smaller keys 4. DSA/ElGamal: Legacy algorithms, no longer recommended
- Symmetric encryption algorithms (for actual data encryption): 6. AES256: Industry standard, recommended 7. AES192/AES128: Also secure but less common 8. 3DES: Deprecated, should be disabled
- Hash algorithms for integrity verification: 10. SHA512/SHA384/SHA256: Modern, secure 11. SHA1: Deprecated due to collision vulnerabilities 12. MD5: Completely broken, never use
- The encryption process works as follows:
- GPG generates a random session key (symmetric)
- The message is encrypted with the session key using symmetric encryption (fast)
- The session key is encrypted with the recipient’s public key (slow but small)
- Both the encrypted message and encrypted session key are bundled together
- The decryption process reverses this:
- Your private key decrypts the session key
- The session key decrypts the actual message
- Digital signatures provide authenticity:
- GPG creates a hash of the message
- The hash is encrypted with your private key (this is the signature)
- Recipients decrypt the signature with your public key and compare hashes
Key Management Best Practices
Key generation recommendations:
- Use Ed25519 for new keys (modern, fast, secure)
- If compatibility required, use RSA 4096-bit
- Always set an expiration date (1-2 years), extend as needed
- Use a strong passphrase (minimum 20 characters, store in password manager)
Master key and subkey architecture:
- Keep your master key offline (air-gapped computer or hardware token)
- Use subkeys for daily operations (signing, encryption, authentication)
- If a subkey is compromised, revoke only the subkey, not the master key
- Subkeys can be rotated without affecting your key identity
Backup strategy:
- Export your private key to encrypted USB drive
- Store revocation certificate in a separate secure location
- Consider paper backups using paperkey
- Test restoration process regularly
Trust and verification:
- Always verify fingerprints through a separate channel (phone call, in person, video chat)
- Sign keys only after identity verification
- Set appropriate trust levels: unknown, never, marginal, full, ultimate
- Attend key signing parties to expand Web of Trust
Key distribution:
- Upload public keys to keyservers: keys.openpgp.org, keyserver.ubuntu.com
- Publish on personal website or GitHub
- Include in email signatures or social media profiles
- Use Keybase for cryptographic identity verification
Revocation planning:
- Generate revocation certificate immediately after key creation
- Store offline in secure location with instructions
- Distribute revocation certificate to keyservers if key compromised
- Create reason-specific revocations (compromised vs. superseded)
Key Generation and Initial Setup
Simplified Key Generation (Recommended for Beginners):
gpg --gen-key
gpg (GnuPG) 2.4.0; Copyright (C) 2021 Free Software Foundation, Inc.
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
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) 2y
Real name: John Doe
Email address: john.doe@example.com
Comment: Work key
You selected this USER-ID:
"John Doe (Work key) <john.doe@example.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
[Enter passphrase when prompted]
gpg: key 0x1234567890ABCDEF marked as ultimately trusted
public and secret key created and signed.
Process Overview:
- Algorithm selection: Default RSA and RSA creates both signing and encryption subkeys
- Key size: 4096 bits provides strong security (2048 minimum, 3072 default)
- Expiration: Setting expiry forces periodic review and prevents orphaned keys
- User ID: Combines name, email, and optional comment (email most important for searches)
- Passphrase: Encrypts your private key on disk using symmetric encryption
What happens during generation:
- GPG collects entropy from system randomness (
/dev/random) - Generates prime numbers for RSA keys
- Creates master key and subkeys
- Generates revocation certificate automatically (stored in
~/.gnupg/openpgp-revocs.d/) - Updates local trustdb
Alternative approaches:
gpg --full-generate-key— Provides more algorithm optionsgpg --quick-generate-key— Non-interactive, scriptablegpg --expert --full-generate-key— Advanced options including curve selection
Advanced Key Generation with Modern Algorithms
Generate Ed25519 Key (Recommended for 2024+):
gpg --quick-generate-key "John Doe <john.doe@example.com>" ed25519 sign 1y
gpg: key 0xABCDEF1234567890 marked as ultimately trusted
gpg: revocation certificate stored as '/home/user/.gnupg/openpgp-revocs.d/ABCDEF1234567890.rev'
public and secret key created and signed.
pub ed25519 2025-12-30 [SC] [expires: 2026-12-30]
ABCDEF1234567890ABCDEF1234567890ABCDEF12
uid John Doe <john.doe@example.com>
Add Encryption Subkey:
gpg --quick-add-key ABCDEF1234567890 cv25519 encr 1y
pub ed25519 2025-12-30 [SC] [expires: 2026-12-30]
ABCDEF1234567890ABCDEF1234567890ABCDEF12
uid [ultimate] John Doe <john.doe@example.com>
sub cv25519 2025-12-30 [E] [expires: 2026-12-30]
Syntax: gpg --quick-generate-key "<name> <email>" <algorithm> <usage> <expiry>
| Parameter | Purpose |
|---|---|
--quick-generate-key | Non-interactive key generation |
"Name <email>" | User ID string (quoted if contains spaces) |
ed25519 | Modern elliptic curve signing algorithm |
sign | Key usage (sign, cert, auth, encr) |
1y | Expires in 1 year (also: 2m=2 months, 3w=3 weeks, 0=never) |
Why Ed25519 is superior:
- Smaller keys: 256-bit Ed25519 ≈ 3072-bit RSA security
- Faster operations: 10-100x faster than RSA
- Modern cryptography: Based on Curve25519, designed by Daniel J. Bernstein
- Resistance to side-channel attacks: Constant-time implementations
Key usage flags explained:
- [C]: Certify (sign other keys, master key capability)
- [S]: Sign (create digital signatures on data)
- [E]: Encrypt (receive encrypted messages)
- [A]: Authenticate (use for SSH authentication)
Adding subkeys:
- Use
--quick-add-keywith master key ID - Specify algorithm (cv25519 for encryption, ed25519 for signing)
- Different expiry dates for different subkeys is common practice
- Authentication subkey:
gpg --quick-add-key <keyid> ed25519 auth 1y
Listing and Inspecting Keys
List all public keys:
gpg --list-keys --keyid-format long
/home/user/.gnupg/pubring.kbx
--------------------------------
pub rsa4096/0x1234567890ABCDEF 2025-12-30 [SC] [expires: 2027-12-30]
ABCDEF1234567890ABCDEF1234567890ABCDEF12
uid [ultimate] John Doe (Work key) <john.doe@example.com>
sub rsa4096/0x9876543210FEDCBA 2025-12-30 [E] [expires: 2027-12-30]
pub ed25519/0xDEADBEEFCAFEBABE 2025-12-28 [SC] [expires: 2026-12-28]
DEADBEEFCAFEBABEDEADBEEFCAFEBABEDEADBEEF
uid [ unknown] Alice Smith <alice@example.com>
sub cv25519/0xBABECAFEDEADBEEF 2025-12-28 [E] [expires: 2026-12-28]
List private (secret) keys:
gpg --list-secret-keys --keyid-format long
/home/user/.gnupg/pubring.kbx
--------------------------------
sec rsa4096/0x1234567890ABCDEF 2025-12-30 [SC] [expires: 2027-12-30]
ABCDEF1234567890ABCDEF1234567890ABCDEF12
uid [ultimate] John Doe (Work key) <john.doe@example.com>
ssb rsa4096/0x9876543210FEDCBA 2025-12-30 [E] [expires: 2027-12-30]
Show key fingerprint:
gpg --fingerprint john.doe@example.com
pub rsa4096 2025-12-30 [SC] [expires: 2027-12-30]
ABCD EF12 3456 7890 ABCD EF12 3456 7890 ABCD EF12
uid [ultimate] John Doe (Work key) <john.doe@example.com>
sub rsa4096 2025-12-30 [E] [expires: 2027-12-30]
Understanding the output:
| Field | Meaning |
|---|---|
pub | Public key |
sec | Secret (private) key |
sub | Public subkey |
ssb | Secret subkey |
rsa4096 | Algorithm and key size |
0x1234...CDEF | Long key ID (16 hex characters) |
2025-12-30 | Creation date |
[SC] | Key capabilities: Sign, Certify |
[E] | Key capability: Encrypt |
[expires: 2027-12-30] | Expiration date |
[ultimate] | Trust level (your own keys) |
[unknown] | Trust level (unverified keys) |
Trust levels explained:
- unknown: No trust decision made
- never: Explicitly distrusted
- marginal: Some confidence in key ownership
- full: High confidence in key ownership
- ultimate: Your own keys (absolute trust)
Key ID formats:
- Short (8 hex chars):
0xABCDEF12— Vulnerable to collisions, deprecated - Long (16 hex chars):
0x1234567890ABCDEF— Recommended minimum - Fingerprint (40 hex chars): Full SHA-1 hash of public key — Most secure, use for verification
Useful listing variations:
gpg -k— Shorthand for--list-keysgpg -K— Shorthand for--list-secret-keysgpg --list-keys --with-fingerprint— Always show fingerprintsgpg --list-keys --with-keygrip— Show internal key identifiers
Exporting Keys for Backup and Sharing
Export public key (ASCII armor for sharing):
gpg --armor --export john.doe@example.com > john-doe-public.asc
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGV2+8kBEADMq7YzL3p8vKYj9xJHR8nzJ+W3qTd5gFHJ2kL9xYp3qRV8sW7M
[... key material ...]
-----END PGP PUBLIC KEY BLOCK-----
Export private key (keep secure!):
gpg --armor --export-secret-keys john.doe@example.com > john-doe-private.asc
-----BEGIN PGP PRIVATE KEY BLOCK-----
lQdGBGV2+8kBEADMq7YzL3p8vKYj9xJHR8nzJ+W3qTd5gFHJ2kL9xYp3qRV8sW7M
[... encrypted private key material ...]
-----END PGP PRIVATE KEY BLOCK-----
Export all keys (backup entire keyring):
gpg --armor --export > all-public-keys.asc
gpg --armor --export-secret-keys > all-private-keys.asc
Export to clipboard (macOS):
gpg --armor --export john.doe@example.com | pbcopy
Export binary format (smaller file size):
gpg --export john.doe@example.com > john-doe-public.gpg
Syntax: gpg [--armor] --export [--output file] <key-id>
| Flag | Purpose |
|---|---|
--armor / -a | ASCII-armored output (text instead of binary) |
--export | Export public keys |
--export-secret-keys | Export private keys |
--export-secret-subkeys | Export only subkeys (keep master offline) |
--output / -o | Specify output file |
<key-id> | Email, key ID, or fingerprint (omit for all keys) |
ASCII armor vs. binary:
- ASCII armor (
.asc): Text format, email-safe, larger size (~33% overhead) - Binary (
.gpg): Smaller, more efficient, not text-safe
Security considerations:
- Private key exports are encrypted with your passphrase
- Store private key exports on encrypted USB drives or offline media
- Never email or upload private keys to cloud services
- Use
shredor secure deletion when removing private key backups
Advanced export scenarios:
- Export master key only:
gpg --export-secret-keys --armor <keyid>! - Export specific subkey:
gpg --export-secret-subkeys --armor <subkeyid>! - Export with trust database: Also backup
~/.gnupg/trustdb.gpg - Paper backup: Use
paperkeytool to create printable backup
Importing Keys from Others
Import from file:
gpg --import alice-public.asc
gpg: key 0xDEADBEEFCAFEBABE: public key "Alice Smith <alice@example.com>" imported
gpg: Total number processed: 1
gpg: imported: 1
Import from keyserver:
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0xDEADBEEFCAFEBABE
gpg: key 0xDEADBEEFCAFEBABE: public key "Alice Smith <alice@example.com>" imported
gpg: Total number processed: 1
gpg: imported: 1
gpg: marginal needed: 3 complete needed: 1 trust model: pgp
Search keyserver for a key:
gpg --keyserver hkps://keys.openpgp.org --search-keys alice@example.com
(1) Alice Smith <alice@example.com>
4096 bit RSA key 0xDEADBEEFCAFEBABE, created: 2025-12-28
Keys 1-1 of 1 for "alice@example.com". Enter number(s), N)ext, or Q)uit > 1
Import from URL:
curl https://example.com/alice-key.asc | gpg --import
Import and verify fingerprint:
gpg --import alice-public.asc
gpg --fingerprint alice@example.com
pub rsa4096 2025-12-28 [SC] [expires: 2026-12-28]
DEAD BEEF CAFE BABE DEAD BEEF CAFE BABE DEAD BEEF
uid [ unknown] Alice Smith <alice@example.com>
Syntax: gpg --import <file> or gpg --recv-keys <key-id>
| Flag | Purpose |
|---|---|
--import | Import keys from file or stdin |
--recv-keys | Download and import from keyserver |
--search-keys | Search keyserver interactively |
--keyserver <url> | Specify keyserver to use |
--fingerprint | Display key fingerprint after import |
Post-import verification workflow:
- Import the key
- Check fingerprint:
gpg --fingerprint <key-id> - Verify fingerprint out-of-band (phone call, in person, verified website)
- Sign the key if verified:
gpg --sign-key <key-id> - Set trust level:
gpg --edit-key <key-id>→trustcommand
Popular keyservers:
- keys.openpgp.org: Modern, privacy-focused, verifies email
- keyserver.ubuntu.com: Pool of synchronized servers
- keys.gnupg.net: Legacy, often used for software verification
Keyserver operations:
- Upload:
gpg --send-keys <key-id> - Refresh all keys:
gpg --refresh-keys(updates signatures and expiry) - Auto-retrieve: Set
auto-key-retrieveingpg.conf
Deleting Keys (Use with Caution)
Delete public key:
gpg --delete-key alice@example.com
gpg (GnuPG) 2.4.0; Copyright (C) 2021 Free Software Foundation, Inc.
pub rsa4096/0xDEADBEEFCAFEBABE 2025-12-28 Alice Smith <alice@example.com>
Delete this key from the keyring? (y/N) y
Delete private key (must be done before deleting public key):
gpg --delete-secret-key john.doe@example.com
sec rsa4096/0x1234567890ABCDEF 2025-12-30 John Doe (Work key) <john.doe@example.com>
Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y
Delete both secret and public key (shortcut):
gpg --delete-secret-and-public-key john.doe@example.com
Important Notes on Key Deletion:
- Deleting a private key is permanent — cannot decrypt past messages without backup
- Deleting public key doesn’t remove it from keyservers — must publish revocation certificate
- Order matters: Must delete private key before public key
- Subkeys are deleted with master key — cannot selectively delete subkeys via command line
- Before deletion: 6. Ensure you have backed up the private key 7. Generate and publish revocation certificate if key is public 8. Consider just revoking instead of deleting
- Use key editing for selective removal:
gpg --edit-key <keyid>→key N→delkey
Interactive Key Editor
Enter key editing mode:
gpg --edit-key john.doe@example.com
gpg (GnuPG) 2.4.0; Copyright (C) 2021 Free Software Foundation, Inc.
Secret key is available.
sec rsa4096/0x1234567890ABCDEF
created: 2025-12-30 expires: 2027-12-30 usage: SC
trust: ultimate validity: ultimate
ssb rsa4096/0x9876543210FEDCBA
created: 2025-12-30 expires: 2027-12-30 usage: E
[ultimate] (1). John Doe (Work key) <john.doe@example.com>
gpg> help
quit quit this menu
save save and quit
help show this help
fpr show key fingerprint
grip show the keygrip
list list key and user IDs
uid select user ID N
key select subkey N
check check signatures
sign sign selected user IDs
adduid add a user ID
deluid delete selected user IDs
addkey add a subkey
delkey delete selected subkeys
expire change the expiration date for the key or selected subkeys
passwd change the passphrase
trust change the ownertrust
revkey revoke key or selected subkeys
gpg>
Common Key Editing Tasks:
Change expiration date:
- Enter edit mode:
gpg --edit-key <key-id> - Command:
expire - Follow prompts to set new expiration
- For subkeys:
key 1to select, thenexpire - Save:
save
Change passphrase:
- Enter edit mode:
gpg --edit-key <key-id> - Command:
passwd - Enter old passphrase, then new passphrase twice
- Save:
save
Set trust level:
- Enter edit mode:
gpg --edit-key <key-id> - Command:
trust - Select trust level (1-5): 4. 1 = I don’t know or won’t say 5. 2 = I do NOT trust 6. 3 = I trust marginally 7. 4 = I trust fully 8. 5 = I trust ultimately (own keys only)
- Confirm and save
Add new user ID (email):
- Enter edit mode:
gpg --edit-key <key-id> - Command:
adduid - Enter new name, email, comment
- Command:
uid 1to select new UID - Command:
primaryto make it primary - Save:
save
Revoke a key:
- Enter edit mode:
gpg --edit-key <key-id> - Command:
revkey - Select reason: 0=No reason, 1=Key compromised, 2=Key superseded, 3=Key no longer used
- Confirm revocation
- Save:
save - Upload to keyserver:
gpg --send-keys <key-id>
Asymmetric Encryption (Public Key)
Encrypt file for single recipient:
gpg --encrypt --recipient alice@example.com secret-document.txt
[No output - creates secret-document.txt.gpg]
Encrypt with ASCII armor (text-safe):
gpg --encrypt --armor --recipient alice@example.com secret-document.txt
[Creates secret-document.txt.asc]
Encrypt for multiple recipients:
gpg -e -a -r alice@example.com -r bob@example.com -r john.doe@example.com confidential.txt
[Creates confidential.txt.asc - all three recipients can decrypt]
Encrypt and specify output filename:
gpg --output encrypted-report.gpg --encrypt --recipient alice@example.com quarterly-report.pdf
Encrypt stdin (terminal input):
echo "Meeting at 3pm tomorrow" | gpg -e -a -r alice@example.com > message.asc
Encrypt multiline message:
cat <<EOF | gpg -e -a -r alice@example.com > secret-message.asc
Project Nightfall is a go.
Launch coordinates: 51.5074° N, 0.1278° W
Extraction team on standby.
EOF
Syntax: gpg --encrypt --recipient <email> [--armor] [--output <file>] <input-file>
| Flag | Purpose |
|---|---|
--encrypt / -e | Encrypt the file |
--recipient / -r | Specify recipient by email or key ID (repeatable) |
--armor / -a | Output ASCII-armored text instead of binary |
--output / -o | Specify output filename |
--hidden-recipient / -R | Hide recipient identity in encrypted file |
How it works:
- GPG looks up recipient’s public key in your keyring
- Generates random session key (symmetric)
- Encrypts file with session key using AES-256
- Encrypts session key with recipient’s public key
- Bundles both in output file
Multiple recipients:
- Each
-rflag adds another recipient - Session key is encrypted separately for each recipient’s public key
- Any recipient can decrypt using their private key
- File size increases slightly with each recipient
Pro tips:
- Always encrypt to yourself too: Add
-r your@email.comso you can decrypt later - Use
--encrypt-toin config: Automatically includes your key - Hidden recipients: Use
-Rinstead of-rto prevent key ID leakage - Trust warnings: GPG warns if recipient key isn’t trusted (use
--trust-model alwaysto bypass)
Symmetric Encryption (Password-Based)
Encrypt with passphrase (no keys needed):
gpg --symmetric confidential-notes.txt
[Prompts for passphrase twice]
[Creates confidential-notes.txt.gpg]
Symmetric encryption with ASCII armor:
gpg --symmetric --armor backup-codes.txt
[Creates backup-codes.txt.asc]
Specify cipher algorithm:
gpg --symmetric --cipher-algo AES256 --armor passwords.txt
Encrypt from stdin:
echo "Quick secret note" | gpg -c --armor > note.asc
Encrypt multiline content:
cat <<EOF | gpg -c --armor > database-credentials.asc
Database: production-db-01
Username: admin
Password: Tr0ub4dor&3
Host: db.internal.company.com:5432
EOF
Syntax: gpg --symmetric [--cipher-algo <algorithm>] [--armor] <file>
| Flag | Purpose |
|---|---|
--symmetric / -c | Symmetric encryption (password-based) |
--cipher-algo | Specify encryption algorithm (default: AES-128) |
--armor / -a | ASCII-armored output |
--output / -o | Specify output file |
Supported cipher algorithms:
- AES256 — Recommended (strongest)
- AES192 — Strong
- AES128 — Default (still secure)
- CAMELLIA256 — Alternative to AES
- TWOFISH — Legacy
When to use symmetric encryption:
- Personal backups: No need for key exchange
- Quick encryption: Faster than asymmetric
- File archives: Password-protect sensitive files
- Pre-shared secrets: When secure channel for passphrase exists
Security considerations:
- Passphrase strength is critical (minimum 20 characters recommended)
- Use password manager to generate and store passphrases
- No forward secrecy (compromised passphrase exposes all files encrypted with it)
- Consider diceware for memorable but strong passphrases
Decryption is identical to asymmetric: gpg -d file.gpg (prompts for passphrase instead of using private key)
Decrypting Files
Decrypt to stdout (display):
gpg --decrypt secret-document.txt.gpg
gpg: encrypted with rsa4096 key, ID 0x9876543210FEDCBA, created 2025-12-30
"John Doe (Work key) <john.doe@example.com>"
This is the secret document content.
Multiple lines preserved.
Decrypt to specific file:
gpg --output decrypted.txt --decrypt secret-document.txt.gpg
gpg: encrypted with rsa4096 key, ID 0x9876543210FEDCBA, created 2025-12-30
"John Doe (Work key) <john.doe@example.com>"
Decrypt ASCII armored file:
gpg --decrypt message.asc
Decrypt and pipe to another command:
gpg -d encrypted-logs.txt.gpg | grep "ERROR" | less
Decrypt from stdin (paste encrypted content):
gpg --decrypt <<EOF
-----BEGIN PGP MESSAGE-----
hQIMA5h2VDIgzey6AQ/+K8Z3Jx4vN2M1pR7qL9...
-----END PGP MESSAGE-----
EOF
Decrypt clipboard content (macOS):
pbpaste | gpg -d
Decrypt and copy result to clipboard (macOS):
gpg -d secret.asc | pbcopy
Syntax: gpg --decrypt [--output <file>] <encrypted-file>
| Flag | Purpose |
|---|---|
--decrypt / -d | Decrypt the file |
--output / -o | Write decrypted content to file instead of stdout |
--batch | Non-interactive mode (no prompts) |
--passphrase <pass> | Supply passphrase via command line (insecure) |
--passphrase-file <file> | Read passphrase from file |
What happens during decryption:
- GPG reads the encrypted file header
- Identifies which key(s) can decrypt it
- Prompts for passphrase to unlock your private key
- Decrypts the session key using your private key
- Decrypts the actual content using the session key
- Outputs plaintext to stdout or file
Output interpretation:
encrypted with rsa4096 key— Shows encryption algorithm and key typeID 0x...— Key ID that encrypted the file- Name and email — Key owner (the recipient)
Troubleshooting:
- “decryption failed: No secret key” — You don’t have the private key
- “decryption failed: Bad passphrase” — Wrong passphrase for private key
- “WARNING: encrypted message has been manipulated” — File integrity compromised (possible attack)
- “gpg: public key decryption failed: Canceled” — User cancelled passphrase entry
Digital Signatures (Binary Format)
Sign a file (creates compressed binary signature):
gpg --sign important-document.txt
[Creates important-document.txt.gpg]
Sign with ASCII armor:
gpg --sign --armor report.pdf
[Creates report.pdf.asc]
Sign with specific key:
gpg --sign --local-user john.doe@example.com contract.txt
Extract content from signed file:
gpg --decrypt signed-document.gpg
gpg: Signature made Mon 30 Dec 2025 14:32:15 GMT
gpg: using RSA key 0x1234567890ABCDEF
gpg: Good signature from "John Doe (Work key) <john.doe@example.com>" [ultimate]
[Original file content displayed]
Syntax: gpg --sign [--local-user <key-id>] [--armor] <file>
| Flag | Purpose |
|---|---|
--sign / -s | Create binary signature |
--local-user / -u | Specify which key to sign with |
--armor / -a | ASCII-armored output |
--output / -o | Specify output filename |
What binary signing does:
- Compresses the original file
- Creates hash of the compressed data
- Encrypts hash with your private key (this is the signature)
- Bundles original + signature in
.gpgfile
Characteristics:
- Original file is embedded in the signature file
- Smaller than clear-signing (compression applied)
- Not human-readable (binary format)
- To view content, must decrypt:
gpg -d file.gpg
Use cases:
- Software releases (Linux packages)
- Binary files (executables, archives)
- When file content doesn’t need to be readable without verification
Clear-Text Signatures (Human-Readable)
Sign with readable message:
gpg --clearsign announcement.txt
[Creates announcement.txt.asc]
Content of clear-signed file:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
This is the original message content.
It remains completely readable.
Anyone can see this text without GPG.
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCgAdFiEErN3xKzP4yKWaLZvzEjRWeJCrze8FAmV3FNMACgkQEjRWeJCr
ze/xKRAAiJ4K3mN9pQZ7vR2XjL...
-----END PGP SIGNATURE-----
Sign from terminal input:
cat <<EOF | gpg --clearsign
Official company announcement:
Our Q4 earnings exceeded expectations.
Revenue: £12.5M (up 23% YoY)
Signed by CEO
EOF
Sign and save to file:
cat <<EOF | gpg --clearsign > announcement.asc
Security Advisory: Patch immediately
CVE-2025-12345 affects versions 1.0-2.3
Update to version 2.4 or later
EOF
Sign with specific key:
gpg --clearsign --local-user john.doe@example.com statement.txt
Syntax: gpg --clearsign [--local-user <key-id>] <file>
| Flag | Purpose |
|---|---|
--clearsign | Create clear-text signature |
--local-user / -u | Specify signing key |
--output / -o | Specify output file |
--digest-algo | Choose hash algorithm (default: SHA256) |
Structure of clear-signed message:
- Header:
-----BEGIN PGP SIGNED MESSAGE-----and hash algorithm - Blank line
- Original message: Unmodified, human-readable
- Signature block:
-----BEGIN PGP SIGNATURE-----…-----END PGP SIGNATURE-----
Advantages:
- Message readable without GPG tools
- Perfect for email, forum posts, announcements
- Content and signature in single file
- Easy to copy-paste
Limitations:
- Only works with text files (not binary)
- Line endings must be preserved
- Slight size increase compared to detached signatures
Use cases:
- Email announcements and statements
- Git commit messages (when not using detached signatures)
- Forum posts and public declarations
- Security advisories
- Release notes
Detached Signatures (Separate Signature File)
Create detached binary signature:
gpg --detach-sign software-package-1.2.3.tar.gz
[Creates software-package-1.2.3.tar.gz.sig]
Create detached ASCII signature:
gpg --detach-sign --armor software-package-1.2.3.tar.gz
[Creates software-package-1.2.3.tar.gz.asc]
Detached signature content (ASCII):
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEErN3xKzP4yKWaLZvzEjRWeJCrze8FAmV3GDUAC gkQEjRWeJCr
ze8h9g/9FjK4pL3mN8vQ2Z...
-----END PGP SIGNATURE-----
Sign with specific key:
gpg --detach-sign --armor --local-user release@company.com product.zip
Verify detached signature:
gpg --verify software-package-1.2.3.tar.gz.asc software-package-1.2.3.tar.gz
gpg: Signature made Mon 30 Dec 2025 15:45:22 GMT
gpg: using RSA key 0x1234567890ABCDEF
gpg: Good signature from "John Doe (Work key) <john.doe@example.com>" [ultimate]
Syntax: gpg --detach-sign [--armor] [--local-user <key-id>] <file>
| Flag | Purpose |
|---|---|
--detach-sign / -b | Create detached signature |
--armor / -a | ASCII-armored signature |
--local-user / -u | Specify signing key |
--output / -o | Specify signature filename |
How detached signatures work:
- GPG creates hash of the entire file
- Encrypts hash with your private key
- Saves signature in separate file
- Original file remains unmodified
Verification process:
- User downloads both original file and
.sigfile - GPG hashes the original file
- Decrypts signature with signer’s public key
- Compares hashes — match = authentic
Advantages:
- Original file completely unchanged
- Works with any file type (binary, text, compressed)
- Small signature file (few KB regardless of original size)
- Standard for software distribution
Use cases:
- Software releases: Linux packages, tarballs, ISOs
- Git tags:
git tag -s v1.0.0creates detached signature - Large files: Signature stays small even for GB files
- Multiple signatures: Different people can sign same file
Naming conventions:
- Binary:
file.sig - ASCII:
file.ascorfile.sig.asc - Some projects:
file.gpgorfile.pgp
Combined Sign and Encrypt
Sign then encrypt for recipient:
gpg --sign --encrypt --recipient alice@example.com confidential-contract.pdf
[Creates confidential-contract.pdf.gpg]
Sign and encrypt with ASCII armor:
gpg -se -a -r alice@example.com sensitive-data.txt
[Creates sensitive-data.txt.asc]
Sign and encrypt for multiple recipients:
gpg -se -a -r alice@example.com -r bob@example.com -r john.doe@example.com report.txt
Specify signing key explicitly:
gpg -s -e -a -u john.doe@example.com -r alice@example.com message.txt
Decrypt and verify in one step:
gpg --decrypt signed-encrypted.asc
gpg: encrypted with rsa4096 key, ID 0x9876543210FEDCBA, created 2025-12-30
"John Doe (Work key) <john.doe@example.com>"
gpg: Signature made Mon 30 Dec 2025 16:10:45 GMT
gpg: using RSA key 0x1234567890ABCDEF
gpg: Good signature from "Alice Smith <alice@example.com>" [full]
[Decrypted message content]
Syntax: gpg --sign --encrypt --recipient <email> [--local-user <key>] <file>
| Flag | Purpose |
|---|---|
--sign --encrypt / -se | Sign then encrypt (combined) |
--recipient / -r | Specify recipients (repeatable) |
--local-user / -u | Specify signing key |
--armor / -a | ASCII-armored output |
Order of operations:
- File is signed first (creates signature with your private key)
- Signed data is then encrypted (using recipient’s public key)
- Recipient must decrypt first, then verify signature
Security benefits:
- Confidentiality: Only recipient can read (encryption)
- Authenticity: Proves you sent it (signature)
- Integrity: Detects tampering (signature verification)
- Non-repudiation: You cannot deny sending (your signature)
Why this is the gold standard:
- Signing alone doesn’t hide content
- Encrypting alone doesn’t prove sender
- Combining both provides complete security
Use cases:
- Confidential business communications
- Legal documents requiring proof of authenticity
- Sensitive personal correspondence
- Financial information exchange
Verification by recipient:
- Decrypt with their private key (proves they’re intended recipient)
- Verify signature with your public key (proves you sent it)
- Both operations happen automatically with
gpg -d
Verifying Signatures
Verify clear-signed message:
gpg --verify announcement.asc
gpg: Signature made Mon 30 Dec 2025 16:30:12 GMT
gpg: using RSA key 0x1234567890ABCDEF
gpg: Good signature from "John Doe (Work key) <john.doe@example.com>" [ultimate]
Verify detached signature:
gpg --verify software-1.2.3.tar.gz.asc software-1.2.3.tar.gz
gpg: Signature made Mon 30 Dec 2025 16:45:00 GMT
gpg: using RSA key 0x1234567890ABCDEF
gpg: Good signature from "Release Team <release@company.com>" [full]
Verify binary signed file:
gpg --verify document.gpg
Verify with verbose output:
gpg --verify --verbose software.tar.gz.sig software.tar.gz
Verify and extract content:
gpg --decrypt signed-message.gpg
gpg: Signature made Mon 30 Dec 2025 17:00:00 GMT
gpg: using RSA key 0x1234567890ABCDEF
gpg: Good signature from "Alice Smith <alice@example.com>" [full]
[Message content displayed]
Test signature creation and verification (one-liner):
echo "Test message" | gpg --clearsign | gpg --verify
gpg: Signature made Mon 30 Dec 2025 17:05:30 GMT
gpg: using RSA key 0x1234567890ABCDEF
gpg: Good signature from "John Doe (Work key) <john.doe@example.com>" [ultimate]
Syntax:
- Embedded:
gpg --verify <signed-file> - Detached:
gpg --verify <signature-file> <original-file>
| Flag | Purpose |
|---|---|
--verify | Verify signature |
--verbose | Show detailed information |
--status-fd N | Machine-readable status output |
Signature verification outcomes:
| Message | Meaning |
|---|---|
Good signature | ✅ Signature is valid and intact |
BAD signature | ❌ File has been tampered with or signature corrupt |
Can't check signature: No public key | ⚠️ You don’t have signer’s public key |
Signature expired | ⚠️ Signature was created with expired key |
WARNING: This key is not certified | ⚠️ You haven’t verified/signed this public key |
Trust indicators:
- [ultimate]: Your own key
- [full]: You’ve signed this key (verified identity)
- [marginal]: Signed by someone you trust
- [unknown]: No trust relationship established
- [expired]: Key has passed expiration date
- [revoked]: Key has been revoked by owner
What GPG checks:
- Signature cryptographically matches file (integrity)
- Signature was created with private key corresponding to claimed public key (authenticity)
- Key hasn’t been revoked
- Key hasn’t expired (warning if expired)
- Signature timestamp (when it was created)
Troubleshooting:
- Missing public key: Import with
gpg --recv-keys <keyid>orgpg --import - Untrusted key: Verify fingerprint out-of-band, then sign:
gpg --sign-key <keyid> - BAD signature: File corrupted or tampered — do NOT trust
Shell Aliases for Enhanced Productivity
Add these to ~/.bashrc, ~/.zshrc, or equivalent:
# Key Management
alias gpg-list='gpg --list-keys --keyid-format long'
alias gpg-list-secret='gpg --list-secret-keys --keyid-format long'
alias gpg-fingerprint='gpg --fingerprint'
alias gpg-refresh='gpg --refresh-keys'
# Encryption shortcuts
alias gpg-encrypt='gpg -e -a -r'
alias gpg-encrypt-self='gpg -e -a -r $(gpg --list-keys --keyid-format long | grep -m1 "^pub" | awk "{print \$2}" | cut -d"/" -f2)'
alias gpg-symmetric='gpg -c --armor --cipher-algo AES256'
# Decryption
alias gpg-decrypt='gpg -d'
alias gpg-decrypt-file='gpg -o'
# Signing
alias gpg-sign='gpg --clearsign'
alias gpg-sign-detach='gpg -b -a'
alias gpg-sign-encrypt='gpg -se -a -r'
# Verification
alias gpg-verify='gpg --verify'
# Export
alias gpg-export-pub='gpg --armor --export'
alias gpg-export-priv='gpg --armor --export-secret-keys'
# Clipboard operations (macOS)
alias gpg-encrypt-clip='pbpaste | gpg -e -a -r'
alias gpg-decrypt-clip='pbpaste | gpg -d'
alias gpg-sign-clip='pbpaste | gpg --clearsign | pbcopy'
alias gpg-export-clip='gpg --armor --export $1 | pbcopy'
# Linux alternatives (using xclip)
# alias gpg-encrypt-clip='xclip -o | gpg -e -a -r'
# alias gpg-decrypt-clip='xclip -o | gpg -d'
# alias gpg-sign-clip='xclip -o | gpg --clearsign | xclip -selection clipboard'
# Advanced operations
alias gpg-revoke='gpg --gen-revoke --armor --output=revocation.asc'
alias gpg-edit='gpg --edit-key'
alias gpg-import='gpg --import'
alias gpg-send='gpg --send-keys'
alias gpg-recv='gpg --recv-keys'
alias gpg-search='gpg --search-keys'
# Agent management
alias gpg-restart='gpgconf --kill gpg-agent && gpg-agent --daemon'
alias gpg-agent-status='gpg-connect-agent "getinfo version" /bye'
# Quick test
alias gpg-test='echo "Test message" | gpg --clearsign | gpg --verify'
Usage examples:
# Encrypt for Alice
gpg-encrypt alice@example.com confidential.txt
# Sign and copy to clipboard
echo "Important announcement" | gpg-sign-clip
# Decrypt clipboard content
gpg-decrypt-clip
# Export public key to clipboard
gpg-export-clip john.doe@example.com
# Quick signature test
gpg-test
GPG Configuration Files
Configuration file locations:
~/.gnupg/gpg.conf— Main GPG configuration~/.gnupg/gpg-agent.conf— GPG Agent (passphrase caching, pinentry)~/.gnupg/dirmngr.conf— Directory manager (keyserver operations)~/.gnupg/trustdb.gpg— Trust database (binary, auto-managed)~/.gnupg/pubring.kbx— Public keyring (binary)~/.gnupg/secring.gpg— Secret keyring (legacy, GPG 2.1+ uses private-keys-v1.d/)
Directory permissions (critical for security):
chmod 700 ~/.gnupg
chmod 600 ~/.gnupg/*
Recommended ~/.gnupg/gpg.conf Configuration
Production-ready configuration with security best practices:
#-----------------------------
# Explicit Key Selection (recommended)
#-----------------------------
# Prefer --local-user <FULL_FINGERPRINT> and explicit --recipient values
# per command. Do not enable defaults unless their behaviour is intentional.
#
# Optional signing default (use a full fingerprint, never a short key ID):
# default-key 0123456789ABCDEF0123456789ABCDEF01234567
#
# Optional automatic self-encryption. This is convenient but less explicit:
# default-recipient-self
#
# Optional always-add recipient. This changes every encryption operation:
# encrypt-to 0123456789ABCDEF0123456789ABCDEF01234567
#-----------------------------
# Display and Output Behavior
#-----------------------------
# Disable copyright notice
no-greeting
# Use long key IDs (16 hex characters)
keyid-format 0xlong
# Display key fingerprints
with-fingerprint
# Show UID validity when listing keys
list-options show-uid-validity
verify-options show-uid-validity
# Show key usage capabilities
list-options show-usage
# ASCII-armored output by default (text-safe)
armor
# Remove version string from output (privacy)
no-emit-version
# Remove comments from output (privacy)
no-comments
#-----------------------------
# Cryptographic Preferences
#-----------------------------
# Preferred symmetric ciphers (strongest first)
personal-cipher-preferences AES256 AES192 AES
# Preferred digest algorithms
personal-digest-preferences SHA512 SHA384 SHA256
# Preferred compression algorithms
personal-compress-preferences ZLIB BZIP2 ZIP Uncompressed
# Default cipher for symmetric encryption
cipher-algo AES256
# Default digest for signatures
digest-algo SHA512
# Default compression
compress-algo ZLIB
# Compression level (0=none, 1=fast, 9=best)
compress-level 6
#-----------------------------
# Security Hardening
#-----------------------------
# Disable weak algorithms
disable-cipher-algo 3DES
disable-cipher-algo IDEA
disable-cipher-algo CAST5
# Mark SHA-1 as weak
weak-digest SHA1
# Require cross-certification on subkeys
require-cross-certification
# Don't merge user IDs on import
import-options import-clean
# Remove unusable signatures when cleaning keys
import-options import-minimal
#-----------------------------
# Keyserver Configuration
#-----------------------------
# Default keyserver (modern, privacy-focused)
keyserver hkps://keys.openpgp.org
# Alternative keyservers (uncomment if needed):
# keyserver hkps://keyserver.ubuntu.com
# keyserver hkps://keys.gnupg.net
# Automatically retrieve keys when verifying
auto-key-retrieve
# Include revoked keys in searches
keyserver-options include-revoked
# Don't leak key search info to keyserver
keyserver-options no-honor-keyserver-url
#-----------------------------
# User Interface
#-----------------------------
# Use UTF-8 for display
utf8-strings
# Fixed list mode (parseable output)
fixed-list-mode
# Show full timestamps
list-options show-sig-expire
#-----------------------------
# Trust and Validation
#-----------------------------
# Set trust model (pgp = Web of Trust, tofu = Trust On First Use)
trust-model pgp
# Require valid certification path (stricter)
# trust-model tofu+pgp
# Use agent for passphrases
use-agent
# Throw keyids option (privacy - hides recipients)
# throw-keyids
Configuration Options Explained:
Key security options:
default-recipient-self: Ensures you can decrypt messages you sendrequire-cross-certification: Prevents fake binding signatures on subkeysweak-digest SHA1: Warns when SHA-1 is used (deprecated due to collisions)disable-cipher-algo 3DES: Prevents use of weak encryption algorithms
Privacy options:
no-emit-version: Doesn’t reveal your GPG version (reduces fingerprinting)no-comments: Removes comment field from outputthrow-keyids: Hides recipient key IDs (prevents traffic analysis)keyserver-options no-honor-keyserver-url: Ignores keyserver URLs in keys (prevents tracking)
Output formatting:
armor: Default to ASCII output (.ascfiles)keyid-format 0xlong: Shows 16-character key IDs (short IDs are insecure)with-fingerprint: Always displays full 40-character fingerprint
Algorithm preferences:
- Listed in order of preference (strongest first)
- GPG negotiates with recipient’s preferences
- Falls back to next algorithm if first isn’t supported
Recommended ~/.gnupg/gpg-agent.conf Configuration
#-----------------------------
# Passphrase Caching
#-----------------------------
# Cache passphrase for 1 hour (3600 seconds)
default-cache-ttl 3600
# Maximum cache time: 8 hours (28800 seconds)
max-cache-ttl 28800
# Time to cache SSH keys (if using GPG for SSH)
default-cache-ttl-ssh 3600
max-cache-ttl-ssh 28800
#-----------------------------
# Pinentry (Password Prompt)
#-----------------------------
# Graphical pinentry (choose based on your desktop environment)
# For macOS:
pinentry-program /usr/local/bin/pinentry-mac
# For GNOME/GTK:
# pinentry-program /usr/bin/pinentry-gtk-2
# For KDE/Qt:
# pinentry-program /usr/bin/pinentry-qt
# For terminal/console:
# pinentry-program /usr/bin/pinentry-curses
# For TTY (servers):
# pinentry-program /usr/bin/pinentry-tty
#-----------------------------
# SSH Support
#-----------------------------
# Enable GPG key usage for SSH authentication
enable-ssh-support
#-----------------------------
# Security
#-----------------------------
# Allow passphrase entry via loopback (for scripts)
allow-loopback-pinentry
# Enforce passphrase constraints
# min-passphrase-len 20
# min-passphrase-nonalpha 2
#-----------------------------
# Logging (Debugging)
#-----------------------------
# Uncomment for troubleshooting
# log-file /tmp/gpg-agent.log
# debug-level basic
# verbose
Apply changes:
# Restart GPG agent to load new config
gpgconf --kill gpg-agent
gpg-agent --daemon
Recommended ~/.gnupg/dirmngr.conf Configuration
#-----------------------------
# Keyserver Configuration
#-----------------------------
# Primary keyserver
keyserver hkps://keys.openpgp.org
# Fallback keyservers (tried if primary fails)
# keyserver hkps://keyserver.ubuntu.com
# keyserver hkps://pgp.mit.edu
#-----------------------------
# Network and Proxy
#-----------------------------
# Honor HTTP proxy environment variables
honor-http-proxy
# Use Tor for keyserver access (requires Tor running)
# use-tor
# HTTP proxy (if not using environment variables)
# http-proxy http://proxy.example.com:8080
#-----------------------------
# Certificate Validation (for HKPS)
#-----------------------------
# Path to CA certificates (for HTTPS keyservers)
# hkp-cacert /usr/share/ca-certificates/mozilla/root.crt
# Disable certificate checks (not recommended)
# disable-http
#-----------------------------
# Logging (Debugging)
#-----------------------------
# Uncomment for troubleshooting
# log-file /tmp/dirmngr.log
# debug-level basic
# verbose
Apply changes:
# Restart dirmngr
gpgconf --kill dirmngr
dirmngr --daemon
Common Troubleshooting Issues
Problem: “gpg: decryption failed: No secret key”
- Cause: You don’t have the private key needed to decrypt
- Solution:
3. Check which key encrypted the file:
gpg --list-packets file.gpg | grep keyid4. Verify you have that key:gpg --list-secret-keys <keyid>5. If missing, import backup:gpg --import private-key-backup.asc
Problem: “gpg: WARNING: This key is not certified with a trusted signature”
- Cause: You haven’t verified and signed the public key
- Solution:
3. Verify fingerprint out-of-band (phone, in person)
4. Sign the key:
gpg --sign-key <keyid>5. Or adjust trust:gpg --edit-key <keyid>→trust→ select level
Problem: “gpg: can’t connect to the agent: IPC connect call failed”
- Cause: GPG agent not running or socket issue
- Solution:
# Kill existing agent gpgconf --kill gpg-agent # Start new agent gpg-agent --daemon # Verify it's running gpg-connect-agent 'getinfo version' /bye
Problem: “gpg: public key decryption failed: Inappropriate ioctl for device”
- Cause: Terminal not properly configured for passphrase entry
- Solution:
export GPG_TTY=$(tty) echo "export GPG_TTY=\$(tty)" >> ~/.bashrc
Problem: “gpg: keyserver receive failed: No keyserver available”
- Cause: Keyserver configuration issue or network problem
- Solution:
# Test keyserver connectivity gpg --keyserver hkps://keys.openpgp.org --recv-keys <keyid> # Try alternative keyserver gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys <keyid> # Check dirmngr status gpgconf --check-programs # Restart dirmngr gpgconf --kill dirmngr
Problem: “gpg: signing failed: Unusable secret key”
- Cause: Key expired or passphrase wrong
- Solution:
# Check key expiration gpg --list-keys <keyid> # Extend expiration gpg --edit-key <keyid> # In editor: expire → set new date → save # Upload updated key gpg --send-keys <keyid>
Problem: Permission errors on ~/.gnupg
- Cause: Incorrect file permissions (GPG requires strict permissions)
- Solution:
chmod 700 ~/.gnupg chmod 600 ~/.gnupg/* chmod 700 ~/.gnupg/private-keys-v1.d
Problem: “gpg: Fatal: can’t create directory”
- Cause: GPG directory doesn’t exist or ownership wrong
- Solution:
mkdir -p ~/.gnupg chmod 700 ~/.gnupg chown -R $USER:$USER ~/.gnupg
Diagnostic Commands
Check GPG version and capabilities:
gpg --version
gpg (GnuPG) 2.4.0
libgcrypt 1.10.1
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2
List loaded configuration options:
gpg --list-config
Check agent status:
gpg-connect-agent 'getinfo version' /bye
D 2.4.0
OK
Test key with verbose output:
gpg -vvv --list-keys john.doe@example.com
Update trust database:
gpg --update-trustdb
Check trust database integrity:
gpg --check-trustdb
List all GPG-related processes:
ps aux | grep gpg
Force passphrase re-entry (clear cache):
echo RELOADAGENT | gpg-connect-agent
Restart all GPG components:
gpgconf --kill all
gpg-agent --daemon
Hardware Token Integration (YubiKey, Nitrokey)
Why use hardware tokens:
- Private keys never leave the device — cannot be copied or exfiltrated
- Physical presence required — protection against remote attacks
- PIN protection — additional authentication layer
- Tamper-resistant — specialized security chips
- Portable — use your keys on multiple computers without copying them
Supported operations:
- Store GPG signing subkey
- Store GPG encryption subkey
- Store GPG authentication subkey (for SSH)
- Store master key (advanced: offline master key setup)
Check if token is detected:
gpg --card-status
Reader: Yubico YubiKey OTP+FIDO+CCID
Application ID: D2760001240100000006123456780000
Version: 3.4
Manufacturer: Yubico
Serial number: 12345678
Name of cardholder: John Doe
Language prefs: en
Sex: male
URL of public key: https://example.com/john-doe.asc
Login data: john.doe@example.com
Signature PIN: not forced
Key attributes: rsa4096 rsa4096 rsa4096
Max. PIN lengths: 127 127 127
PIN retry counter: 3 0 3
Signature counter: 42
Signature key: ABCD EF12 3456 7890
created: 2025-12-30
Encryption key: 1234 5678 90AB CDEF
created: 2025-12-30
Authentication key: 9876 5432 10FE DCBA
created: 2025-12-30
Move existing subkey to token:
gpg --edit-key john.doe@example.com
# In editor:
key 1 # Select signing subkey
keytocard # Move to card
# Choose slot (1=signature, 2=encryption, 3=authentication)
save
Generate key directly on token (cannot be backed up):
gpg --card-edit
# In editor:
admin
generate
# Follow prompts
Hardware Token Backup Strategy:
- Keys moved to hardware tokens cannot be extracted — this is by design
- Always keep encrypted backup of private keys before moving to hardware
- Consider having two tokens with identical keys for redundancy
- Store revocation certificate offline in case token is lost
- Document your PINs securely (default Admin PIN: 12345678, User PIN: 123456)
- Backup strategy:
7. Export subkeys before moving:
gpg --armor --export-secret-subkeys <keyid>8. Store on encrypted USB drive in safe location 9. Test restoration process periodically
Using GPG for SSH Authentication
Why use GPG for SSH:
- Single key for both GPG and SSH operations
- Hardware token support (YubiKey, Nitrokey)
- Centralized key management
- Subkey rotation without changing SSH configuration
Setup process:
- Enable SSH support in
gpg-agent.conf:
echo "enable-ssh-support" >> ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent
- Configure shell environment:
# Add to ~/.bashrc or ~/.zshrc
export GPG_TTY=$(tty)
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
gpgconf --launch gpg-agent
- Create authentication subkey (if you don’t have one):
gpg --expert --edit-key john.doe@example.com
# In editor:
addkey
# Choose: (8) RSA (set your own capabilities)
# Toggle: S, E (to disable), toggle A (to enable authentication)
# Choose key size: 4096
# Choose expiration: 1y
save
- Add authentication subkey to SSH:
# Get authentication subkey keygrip
gpg --list-keys --with-keygrip john.doe@example.com
# Add keygrip to sshcontrol
echo "YOUR_KEYGRIP_HERE" >> ~/.gnupg/sshcontrol
- Export SSH public key:
gpg --export-ssh-key john.doe@example.com
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC... openpgp:0xABCDEF12
- Add to remote server:
gpg --export-ssh-key john.doe@example.com >> ~/.ssh/authorized_keys
# Or copy-paste to remote server's ~/.ssh/authorized_keys
- Test SSH connection:
ssh user@remote-server.com
# Should prompt for GPG passphrase (or PIN if using hardware token)
Advanced Key Management: Master Key Offline Strategy
Concept:
- Keep master key on air-gapped machine or hardware token
- Use subkeys for daily operations
- If subkey compromised, revoke only subkey, not entire identity
Implementation:
- Generate master key on air-gapped machine:
gpg --expert --full-generate-key
# Choose: (1) RSA and RSA
# Size: 4096
# Capabilities: Certify only (disable Sign and Encrypt)
# Expiry: 0 (does not expire)
- Add subkeys for daily use:
gpg --expert --edit-key <master-key-id>
# Add signing subkey:
addkey → (4) RSA (sign only) → 4096 → 1y → save
# Add encryption subkey:
addkey → (6) RSA (encrypt only) → 4096 → 1y → save
# Add authentication subkey:
addkey → (8) RSA (set capabilities) → toggle all except A → 4096 → 1y → save
- Backup master key:
gpg --armor --export-secret-keys <master-key-id> > master-key-backup.asc
gpg --armor --export-secret-subkeys <master-key-id> > subkeys-backup.asc
gpg --gen-revoke --output revocation.asc <master-key-id>
# Store on encrypted USB drives (multiple copies)
# Consider paper backup with paperkey
- Export subkeys for daily machine:
gpg --armor --export-secret-subkeys <master-key-id> > daily-subkeys.asc
- On daily machine, delete master key (keep subkeys):
# Import subkeys
gpg --import daily-subkeys.asc
# Verify you have subkeys
gpg --list-secret-keys
# You should see "sec#" (hash indicates master key stub only)
- Annual subkey rotation (requires master key):
# On air-gapped machine with master key:
gpg --edit-key <master-key-id>
key 1 # Select old subkey
expire # Extend or revoke
addkey # Create new subkey
save
# Export updated subkeys to daily machine
References and Further Reading
Official Documentation:
- GnuPG Official Website — Primary resource for GPG
- GnuPG Manual — Comprehensive reference guide
- RFC 4880 - OpenPGP Message Format — Protocol specification
- GnuPG FAQ — Common questions and answers
Security and Best Practices:
- OpenPGP Best Practices — Riseup security collective recommendations
- Debian Wiki: Using OpenPGP subkeys — Advanced key management
- Creating the Perfect GPG Keypair — Detailed walkthrough
- The GNU Privacy Handbook — Beginner-friendly guide
Hardware Token Resources:
- YubiKey GPG Guide — Official YubiKey documentation
- Nitrokey Documentation — Nitrokey Pro and Storage setup
- drduh’s YubiKey Guide — Comprehensive hardware token tutorial
Cryptographic Background:
- Public-Key Cryptography — Wikipedia overview
- Digital Signature — Cryptographic signature concepts
- Web of Trust — Trust model explanation
- Curve25519 — Modern elliptic curve cryptography
Practical Guides:
- Using GPG for Email — FSF Email Self-Defense guide
- Git Commit Signing — Signing commits and tags
- Pass: The Standard Unix Password Manager — GPG-based password manager
Keyserver Information:
- keys.openpgp.org — Modern, privacy-focused keyserver
- Ubuntu Keyserver — Popular keyserver pool
- SKS Keyserver Status — Legacy SKS network (deprecated)
Community and Support:
- GnuPG Mailing Lists — Official support channels
- r/GnuPG — Reddit community
- Stack Exchange: Cryptography — Q&A for cryptographic topics
#Cryptography #GnuPG #GPG #Encryption #Digital-Signatures #OpenPGP #Key-Management #Public-Key-Cryptography #Privacy #Security #PGP #Asymmetric-Encryption #Symmetric-Encryption #Web-of-Trust #Command-Line #Linux #macOS #BSD #PKI #Ed25519 #RSA #AES #SHA512 #Keyserver #YubiKey #Hardware-Token #SSH-Authentication #Email-Encryption #Code-Signing #File-Security