PGP/GPG
PGP (Pretty Good Privacy) and GPG (GnuPG) enable encrypted communication and file signing using public-key cryptography.
Installation
macOS
# Homebrew
brew install gnupg
# Homebrew GUI
brew install gpg-suite
Linux
# Debian/Ubuntu
sudo apt-get install gnupg gnupg2
# RHEL/CentOS/Fedora
sudo dnf install gnupg gnupg2
# Arch
sudo pacman -S gnupg
Windows
# Chocolatey
choco install gnupg
# Scoop
scoop install gpg
# GUI
https://www.gpg4win.org/
Key Generation
Generate New Key Pair
# Interactive key generation
gpg --full-generate-key
# Batch generation
gpg --batch --generate-key << EOF
%pubring keyring.pub
%secring keyring.sec
Key-Type: RSA
Key-Length: 4096
Name-Real: John Doe
Name-Email: john@example.com
Expire-Date: 2y
%commit
EOF
# Quick generation (default settings)
gpg --quick-generate-key "John Doe <john@example.com>" rsa4096 cert 2y
Key Parameters
# Default: RSA 3072-bit
# Recommended: RSA 4096-bit or Ed25519
# Generate with EdDSA (faster, modern)
gpg --quick-generate-key "Name <email>" ed25519 cert 2y
# Generate with specific capabilities
gpg --quick-generate-key "Name <email>" rsa4096 encr,sign 1y
Key Management
List Keys
# List public keys
gpg --list-keys
# List public keys detailed
gpg --list-sigs
# List secret keys
gpg --list-secret-keys
# List specific key
gpg --list-keys FINGERPRINT
# Show fingerprint
gpg --fingerprint EMAIL@example.com
# Export key info
gpg --export-options export-minimal --export EMAIL@example.com
Edit Key
# Interactive key editing
gpg --edit-key FINGERPRINT
# Commands in edit mode:
# addkey - Add subkey
# adduid - Add user ID
# delkey - Delete subkey
# delsig - Delete signature
# trust - Set trust level
# expire - Set key expiration
# sign - Sign another key
# save - Save changes
# Example: Add encryption subkey
gpg --edit-key EMAIL@example.com << EOF
addkey
10 # RSA (sign only)
4096
2y
save
EOF
Change Passphrase
# Change passphrase interactively
gpg --edit-key FINGERPRINT
# Then: passwd
# Non-interactive change (requires expect)
expect -c "
spawn gpg --edit-key FINGERPRINT
expect \"gpg> \"
send \"passwd\n\"
expect \"Enter passphrase:\"
send \"oldpass\n\"
expect \"New passphrase:\"
send \"newpass\n\"
expect \"Repeat passphrase:\"
send \"newpass\n\"
expect \"gpg> \"
send \"quit\n\"
"
Revoke Key
# Generate revocation certificate
gpg --output revoke.asc --gen-revoke FINGERPRINT
# Revoke key using certificate
gpg --import revoke.asc
# Or directly revoke (if you have the key)
gpg --edit-key FINGERPRINT
# Then: revkey, save
Encryption and Decryption
Encrypt File
# Encrypt for single recipient
gpg --encrypt --recipient EMAIL@example.com file.txt
# Creates: file.txt.gpg
# Encrypt for multiple recipients
gpg --encrypt \
--recipient alice@example.com \
--recipient bob@example.com \
file.txt
# Encrypt without compression
gpg --encrypt --no-compress --recipient EMAIL file.txt
# Symmetric encryption (password-only)
gpg --symmetric file.txt
# Enter passphrase (no public key needed)
# ASCII armor output (portable text)
gpg --armor --encrypt --recipient EMAIL file.txt
# Creates: file.txt.asc
Decrypt File
# Decrypt file
gpg --decrypt file.txt.gpg > file.txt
# Decrypt in-place
gpg --output file.txt --decrypt file.txt.gpg
# Decrypt without output (verify only)
gpg --decrypt file.txt.gpg
# Batch decrypt multiple files
for file in *.gpg; do
gpg --output "${file%.gpg}" --decrypt "$file"
done
# Decrypt without passphrase prompt (agent)
# Requires: gpg-agent running with cached passphrase
gpg --batch --quiet --decrypt file.txt.gpg
Signing and Verification
Sign File
# Detached signature (recommended)
gpg --detach-sign file.txt
# Creates: file.txt.sig
# Signature in ASCII armor
gpg --detach-sign --armor file.txt
# Creates: file.txt.asc
# Clearsign (signature inside file)
gpg --clearsign file.txt
# Creates: file.txt.asc (text readable with signature)
# Sign and encrypt
gpg --sign --encrypt --recipient EMAIL file.txt
# Creates: file.txt.gpg (signed and encrypted)
# Batch sign files
for file in *.txt; do
gpg --detach-sign "$file"
done
Verify Signature
# Verify detached signature
gpg --verify file.txt.sig file.txt
# Verify clearsigned file
gpg --verify file.txt.asc
# Batch verify
for file in *.sig; do
gpg --verify "$file" "${file%.sig}"
done
# Get verification details
gpg --verify file.txt.sig file.txt 2>&1 | grep -E "(Good|Bad|signature)"
Keyserver Operations
Search Keyserver
# Search on keys.openpgp.org (modern default)
gpg --search-keys EMAIL@example.com
# Search on specific keyserver
gpg --keyserver keyserver.ubuntu.com --search-keys EMAIL
# Other keyservers:
# keys.openpgp.org (privacy-focused)
# keyserver.ubuntu.com (popular)
# pgp.key-server.io (full sync)
# keys.mailvelope.com (web-friendly)
Import Key from Keyserver
# Import from default keyserver
gpg --auto-key-locate keyserver --locate-keys EMAIL@example.com
# Import from specific keyserver
gpg --keyserver keyserver.ubuntu.com --recv-keys FINGERPRINT
# Import multiple keys
gpg --recv-keys KEY1 KEY2 KEY3
# Refresh keys
gpg --refresh-keys
# Import from file
gpg --import keyfile.asc
Export and Upload Keys
# Export public key to file
gpg --export --armor EMAIL@example.com > public.asc
# Export secret key (CAUTION)
gpg --export-secret-keys --armor EMAIL > secret.asc
# Secure this file!
# Export minimal key
gpg --export-options export-minimal --armor --export EMAIL > minimal.asc
# Upload to keyserver
gpg --send-keys FINGERPRINT
# Upload to specific keyserver
gpg --keyserver keyserver.ubuntu.com --send-keys FINGERPRINT
Trust and Signing
Set Trust Level
# Interactive trust settings
gpg --edit-key EMAIL@example.com
# Then: trust
# Levels:
# 1 = I do not know or I do not want to say how much I trust
# 2 = I do NOT trust
# 3 = I trust marginally
# 4 = I trust fully
# 5 = I trust ultimately
# Set trust in batch mode
echo "EMAIL@example.com:4:" | gpg --import-ownertrust
Sign Other Keys
# Sign another user's key
gpg --sign-key EMAIL@example.com
# Local signature (not exportable)
gpg --lsign-key EMAIL@example.com
# Sign with specific key
gpg --default-key YOUR-KEY --sign-key OTHER-KEY
# Export signed key
gpg --export --armor EMAIL@example.com > signed.asc
Advanced Operations
Export/Import Keys
# Export all public keys
gpg --export --armor > all-public.asc
# Export all secret keys (SECURE THIS!)
gpg --export-secret-keys --armor > all-secret.asc
# Import keys
gpg --import keys.asc
# Backup entire keyring
tar czf keyring-backup.tar.gz ~/.gnupg/
Key Statistics
# Count keys
gpg --list-keys | grep "^pub" | wc -l
# Find expired keys
gpg --list-keys | grep expired
# Find keys without signatures
gpg --list-sigs | grep -v "^sig"
# Show key usage dates
gpg --list-keys --with-subkey-fingerprint EMAIL
Password Manager Integration
# Export key for backup into password manager
gpg --export-secret-keys --armor EMAIL@example.com
# Store in password manager (secure)
# Keep offline backup encrypted with strong password
Scripting Examples
Batch Encryption
#!/bin/bash
# Encrypt multiple files for recipient
RECIPIENT="alice@example.com"
FILES=$(find . -type f -name "*.txt")
for file in $FILES; do
echo "Encrypting $file..."
gpg --encrypt --recipient "$RECIPIENT" --armor "$file"
echo "Created ${file}.asc"
done
Decrypt and Process
#!/bin/bash
# Decrypt and process encrypted config
CONFIG_FILE="config.txt.gpg"
TEMP_FILE=$(mktemp)
# Decrypt to temporary file
gpg --output "$TEMP_FILE" --decrypt "$CONFIG_FILE"
# Source configuration
source "$TEMP_FILE"
# Use configuration
echo "Database: $DB_HOST"
echo "User: $DB_USER"
# Securely delete temporary file
shred -vfz -n 3 "$TEMP_FILE"
Email Integration
#!/bin/bash
# Encrypt and email sensitive file
RECIPIENT="recipient@example.com"
FILE="sensitive.txt"
EMAIL_SUBJECT="Encrypted document"
# Encrypt file
gpg --encrypt --recipient "$RECIPIENT" --armor "$FILE"
# Email encrypted file
echo "See attached encrypted file." | \
mail -s "$EMAIL_SUBJECT" \
-a "${FILE}.asc" \
"$RECIPIENT"
Troubleshooting
Common Issues
Issue: “gpg: decryption failed: No secret key”
# Verify you have the private key
gpg --list-secret-keys
# Import your private key if missing
gpg --import private-key.asc
# Check key permissions
ls -la ~/.gnupg/private-keys-v1.d/
Issue: “sign_and_send_pubkey: signing failed”
# Agent issue; restart agent
gpgconf --kill gpg-agent
gpg-agent --daemon
# Provide passphrase
gpg --clearsign file.txt
# (Requires manual passphrase entry)
Issue: “keyserver connection failed”
# Try different keyserver
gpg --keyserver keys.openpgp.org --search-keys email@example.com
# Check network connectivity
ping keyserver.ubuntu.com
# Proxy configuration
gpg --keyserver-options http-proxy=http://proxy:port --search-keys email
Issue: “untrusted key”
# Trust the key
gpg --edit-key KEY-ID
# Then: trust, 4 (I trust fully), quit
# Or set as ultimately trusted
echo "KEY-ID:6:" | gpg --import-ownertrust
Security Best Practices
- Store private keys securely (encrypted backup)
- Use strong passphrases (15+ characters)
- Keep GPG software updated
- Verify key fingerprints before signing
- Trust keys carefully (don’t trust everyone)
- Use subkeys for daily encryption/signing
- Keep master key offline if possible
- Regularly rotate passphrases
- Backup revocation certificates
- Audit key signatures periodically
Related Tools
- gnupg - Official GPG implementation
- gpg-agent - Passphrase cache
- pinentry - Passphrase entry UI
- gpg4win - Windows GUI
- age - Modern alternative
Last updated: 2026-03-30