GPG and File Encryption
GPG (GNU Privacy Guard) is the open-source implementation of the OpenPGP standard (RFC 4880). It provides encryption, decryption, digital signing, and key management using asymmetric cryptography. Unlike PKI/TLS which relies on Certificate Authorities, GPG uses a web of trust model where individuals vouch for each other’s keys.
GPG vs PKI - Mental Model
Section titled “GPG vs PKI - Mental Model”PKI (TLS/HTTPS): GPG (OpenPGP): Trust anchor = Certificate Trust anchor = Key signatures Authority (CA) from people you already trust
CA signs your cert You sign someone's key (after → everyone trusts you verifying their identity in person) because they trust the CA → people who trust you now have a reason to trust their key too
Centralised trust hierarchy Decentralised web of trust
Best for: Best for: - HTTPS/TLS for websites - Email encryption (S/MIME alternative) - Machine-to-machine auth - File encryption and signing - Short-lived certs (ACME) - Code signing (Git commits, packages) - Sensitive document exchangeKey Generation
Section titled “Key Generation”# Install GPGapt install gnupg # Debian/Ubuntubrew install gnupg # macOS
# Generate a new key pair (interactive)gpg --gen-key# Choose: RSA and RSA (sign + encrypt), 4096 bits, 2 years expiry
# Generate with full customisation (expert mode)gpg --full-generate-key# Options: RSA/DSA/Ed25519+CV25519, key size, expiry date, UID
# Modern: use ed25519 + cv25519 (fast, compact, strong)gpg --expert --full-generate-key# Choose: (9) ECC and ECC → (1) Curve 25519 for signing# Then add encryption subkey (10) ECC → (12) Curve 25519
# List your keysgpg --list-keys # public keysgpg --list-secret-keys # private keysgpg --list-keys --keyid-format long # show full key IDgpg --list-keys --fingerprint # show fingerprint (use to verify identity)Key Components
Section titled “Key Components”GPG key structure: Primary key (master key) → Used for: certifying other keys (signing), identity → Should have long expiry or no expiry → Keep offline / on a hardware key for safety
Subkeys → Signing subkey: used for signing messages/commits → Encryption subkey: used for encrypting messages to you → Authentication subkey: used for SSH authentication → Subkeys can have short expiry (1 year); rotate independently → If a subkey is compromised, revoke and replace without losing your identityKey Management
Section titled “Key Management”# Export your public key (share this with others)# --armor = ASCII text output (base64-encoded; safe to paste anywhere)
# Export private key (keep this secure - encrypted with your passphrase)
# Import someone else's public keygpg --import bob-public.asc
# Import from a key servergpg --keyserver keyserver.ubuntu.com --recv-keys 0xABCD1234DEADBEEF
# Upload your public key to a key server
# Generate a revocation certificate (do this immediately after key creation)# Store this securely - if your private key is compromised, publish this revocation
# Revoke a key (when compromised or abandoned)gpg --import alice-revocation.ascKey Signing (Web of Trust)
Section titled “Key Signing (Web of Trust)”# Verify someone's fingerprint (in person, over phone, etc.)# Fingerprint: A1B2 C3D4 E5F6 ...# → Bob reads this to you verbally; if it matches, you know the key is his
# Sign their key (adds your certification)
# Set trust level (controls automatic trust decisions)gpg> trust# 5 = ultimate (your own keys only)# 4 = full (you've verified thoroughly)# 3 = marginal (somewhat verified)# 2 = don't trustgpg> save
# View the web of trust for a keyEncrypting and Decrypting Files
Section titled “Encrypting and Decrypting Files”Encrypt to a Recipient
Section titled “Encrypt to a Recipient”# Encrypt a file for a recipient (only they can decrypt with their private key)# Creates: secret.txt.asc
# Encrypt for multiple recipients (any of them can decrypt)gpg --armor --encrypt \ secret.txt
# Encrypt with a passphrase (symmetric - no key needed to decrypt, just the password)gpg --armor --symmetric secret.txt# Uses AES-256 by default; prompts for passphrase
# Encrypt to yourself (useful for personal encrypted storage)
# Encrypt and sign in one step (recipient gets encrypted + signed content)Decrypt
Section titled “Decrypt”# Decrypt a file (prompts for your private key passphrase)gpg --decrypt secret.txt.ascgpg --output secret.txt --decrypt secret.txt.asc # write to file
# Decrypt and verify signature simultaneouslygpg --decrypt --output document.txt signed-encrypted.txt.ascSigning Files and Verifying Signatures
Section titled “Signing Files and Verifying Signatures”Signing
Section titled “Signing”# Sign a file (creates a detached .sig file alongside original)gpg --armor --detach-sign file.tar.gz# Creates: file.tar.gz.asc (the signature)# Distribute: file.tar.gz + file.tar.gz.asc together
# Inline signature (signature embedded in the file - ASCII)gpg --armor --sign message.txt# Creates: message.txt.asc (contains original content + signature)
# Clearsign (human-readable content + signature - for emails/text)gpg --clearsign announcement.txt# Creates: announcement.txt.asc (readable content headers + sig block at bottom)Verifying
Section titled “Verifying”# Verify a detached signaturegpg --verify file.tar.gz.asc file.tar.gz# Good signature: "Good signature from 'Alice <[email protected]>'"# Bad signature: "BAD signature" - file was modified after signing
# Verify and extract an inline-signed filegpg --output original.txt --decrypt signed.txt.asc
# Verify a clearsigned filegpg --verify announcement.txt.asc
# What GPG checks when verifying:# 1. Signature is mathematically valid (not tampered)# 2. Signing key is known (in your keyring)# 3. Signing key hasn't been revoked# 4. Signing key hasn't expired# Warning if signer's key is not trusted via web of trustReal-World: Verifying Software Downloads
Section titled “Real-World: Verifying Software Downloads”# Example: verifying a Debian ISO# 1. Import the Debian project keygpg --keyserver keyring.debian.org --recv-keys DF9B9C49EAA9298432589D76DA87E80D6294BE9B
# 2. Verify the checksums file is signed by Debiangpg --verify SHA512SUMS.sign SHA512SUMS
# 3. Verify the ISO matches the checksumsha512sum -c SHA512SUMS 2>/dev/null | grep debian-12.isoGit Commit Signing
Section titled “Git Commit Signing”# Configure GPG key for Git signinggpg --list-secret-keys --keyid-format long# Copy the key ID: e.g., 3AA5C34371567BD2
git config --global user.signingkey 3AA5C34371567BD2git config --global commit.gpgsign true # sign all commits by defaultgit config --global tag.gpgsign true # sign all tags
# Sign a specific commit (if not configured globally)git commit -S -m "feat: add login endpoint"
# Sign a taggit tag -s v1.0.0 -m "Release 1.0.0"
# Verify a commit signaturegit log --show-signature -1git verify-commit HEAD
# Verify a taggit verify-tag v1.0.0
# GitHub: add your GPG public key to your account# Settings → SSH and GPG keys → New GPG key → paste output of:GPG with SSH Authentication
Section titled “GPG with SSH Authentication”# Use your GPG authentication subkey as an SSH key# Enable gpg-agent SSH support in ~/.gnupg/gpg-agent.conf:echo "enable-ssh-support" >> ~/.gnupg/gpg-agent.confecho "default-cache-ttl-ssh 3600" >> ~/.gnupg/gpg-agent.conf
# Set SSH_AUTH_SOCK to use gpg-agent instead of ssh-agentexport SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)gpgconf --launch gpg-agent
# List the SSH public key derived from your GPG auth subkeygpg-connect-agent 'keyinfo --ssh-list --ssh-fpr' /byessh-add -L # shows the GPG auth key as an SSH public key
# Add it to a server's authorized_keys:ssh-add -L >> ~/.ssh/authorized_keys # (on the target server)
# Or use yubikey with GPG for hardware-backed SSH# (same workflow - gpg-agent handles the hardware key interaction)Hardware Keys (YubiKey / SmartCard)
Section titled “Hardware Keys (YubiKey / SmartCard)”# Move primary key off computer to a hardware key (YubiKey)# First, generate keys on the computer, then transfer:gpg> keytocard # moves primary key to cardgpg> key 1 # select subkey 1gpg> keytocard # moves signing subkey to card# Repeat for encryption and auth subkeys
# After transfer, private key stubs remain on computer# Actual private key operations happen on the hardware key# YubiKey requires PIN entry per session (can't be extracted)
# Check card statusgpg --card-status
# Set PIN (default: 123456 for user PIN, 12345678 for admin PIN)gpg --card-editgpg/card> passwd # change PINEncryption in Practice - Quick Reference
Section titled “Encryption in Practice - Quick Reference”# Scenario 1: Send an encrypted + signed file to Bob# → sends report.pdf.asc to Bob
# Scenario 2: Encrypt an archive for backup (symmetric, passphrase)tar czf - /home/alice/documents | gpg --symmetric --armor > documents-backup.tar.gz.asc# Decrypt:gpg --decrypt documents-backup.tar.gz.asc | tar xzf -
# Scenario 3: Verify a downloaded package's signature (RPM)rpm --import https://repo.example.com/RPM-GPG-KEY-examplerpm --checksig package.rpm # should say "signatures OK"
# Scenario 4: Sign a release tarball (for a software project)gpg --armor --detach-sign myproject-1.0.0.tar.gzsha256sum myproject-1.0.0.tar.gz > myproject-1.0.0.tar.gz.sha256# Publish: myproject-1.0.0.tar.gz + .asc + .sha256
# Scenario 5: Encrypt multiple files into a single archivetar czf - secret1.txt secret2.txt | gpg --symmetric --armor > secrets.tar.gz.asc