← Back to list

Introduction to GnuPG

I rely on Pretty Good Privacy (PGP) and its open implementation, GnuPG (GPG), to keep secure email, software distribution, and signed…

PI in Neural Engineer · 2025-11-07 14:17 · 0 claps · 5.1 min read paywalled
#cryptography #gnupg #software-engineering #software
Open on Medium ↗
Wiki topics: CRY · Crypto & Web3 🔒 · Cybersecurity

Introduction to GnuPG

I rely on Pretty Good Privacy (PGP) and its open implementation, GnuPG (GPG), to keep secure email, software distribution, and signed source code flowing safely. In this guide, I’ll show you exactly how I build trustworthy OpenPGP identities — from generating resilient key pairs to exchanging them over key servers, encrypting data, and signing releases. If you want practical GnuPG best practices for modern engineering workflows, you’re in the right place.

GPG Basics in One Paragraph

GPG implements the OpenPGP standard, so every identity begins as a key pair: a public key that you share freely and a private key that you guard closely. An OpenPGP key stores:

  • Identity data: user IDs with names, email addresses, and trust levels, so collaborators can confirm who you are.
  • Cryptographic core: the large integers, algorithms (RSA, ECC, Ed25519), creation dates, expiration timers, revocation status, and capability flags.

With that metadata, GPG can handle signing, encryption, subkeys, and trust workflows such as the web-of-trust, trust signatures, key servers, and the Web Key Directory (WKD).

Installation and Environment

Quick Setup Checklist

  • Linux: sudo apt install gnupg on Debian/Ubuntu or sudo dnf install gnupg2 on Fedora/RHEL.
  • macOS: brew install gnupg, which bundles gpg-agent and the CLI tools.
  • Windows: Install Gpg4win for Kleopatra, along with the command-line binaries.
  • Verify: gpg --version Shows enabled algorithms and the default keyring path (typically ~/.gnupg).

Generating a Strong Key

Before touching the keyboard, I map the identities I need: a certification-capable primary key and subkeys for signing, encryption, and authentication. Knowing why each subkey exists makes future rotations painless.

Interactive Generation

gpg --full-generate-key

During the prompts, I focus on:

  • Key type: option 1 (RSA and RSA) for compatibility or 9 (ECC and ECC) for Ed25519/X25519 on modern stacks.
  • Key length: RSA 3072-bit minimum; 4096-bit if I can trade a bit of performance for longevity.
  • Expiration: set a renewal cadence so I revisit the key annually or every two years.
  • User IDs: Full Name <email@example.com> plus any alternate addresses I need.
  • Passphrase: long, unique, and stored via a password manager — gpg-agent handles caching.

Once the key is in ~/.gnupg/pubring.kbx and ~/.gnupg/private-keys-v1.d/, I confirm with:

gpg --list-secret-keys

Non-Interactive Generation

For CI pipelines or reproducible containers, I lean on batch parameters:

cat >gpg-batch <<'EOF'
Key-Type: RSA
Key-Length: 3072
Subkey-Type: RSA
Subkey-Length: 3072
Name-Real: Alice Example
Name-Email: alice@example.com
Expire-Date: 2y
Passphrase: correct horse battery staple
%commit
EOF
gpg --batch --generate-key gpg-batch

Batch mode keeps infrastructure bootstrap scripts deterministic and avoids interactive prompts.

Working with Subkeys

A primary key certifies your identity, while subkeys do the day-to-day work. I treat them like specialized tools that can be rotated independently.

Key Subtypes at a Glance

Signing (S)

expect <<'EOF'
spawn gpg --expert --edit-key your@email.com
expect "gpg>"
send "addkey\r"
expect "Your selection?"
send "4\r"              # RSA (sign only)
expect "What keysize do you want?"
send "4096\r"
expect "Key is valid for?"
send "2y\r"
expect "Is this correct?"
send "y\r"
expect "Really create?"
send "y\r"
expect "gpg>"
send "save\r"
expect eof
EOF
  • Purpose: signing code, emails, releases.

Encryption (E)


expect <<'EOF'
spawn gpg --expert --edit-key your@email.com
expect "gpg>"
send "addkey\r"
expect "Your selection?"
send "6\r"              # RSA (encrypt only)
expect "What keysize do you want?"
send "4096\r"
expect "Key is valid for?"
send "2y\r"
expect "Is this correct?"
send "y\r"
expect "Really create?"
send "y\r"
expect "gpg>"
send "save\r"
expect eof
EOF

- Purpose: receiving confidential data.

Authentication

expect <<'EOF'
spawn gpg --expert --edit-key your@email.com
expect "gpg>"
send "addkey\r"
expect "Your selection?"
send "8\r"              # set your own capabilities
expect "Your selection?"
send "S\r"             # toggle sign off
expect "Your selection?"
send "E\r"             # toggle encrypt off
expect "Your selection?"
send "A\r"             # leave authenticate on
expect "Your selection?"
send "Q\r"
expect "What keysize do you want?"
send "4096\r"
expect "Key is valid for?"
send "2y\r"
expect "Is this correct?"
send "y\r"
expect "Really create?"
send "y\r"
expect "gpg>"
send "save\r"
expect eof
EOF
  • Purpose: SSH access and system logins via gpg-agent.

Inspecting and Managing Keys

Reading gpg --list-keys

pub   ed25519 2025-11-05 [SC] [expires: 2028-11-04]
      XXXXxXXXXXXXXXXXXXXXXXXXXXXXXXX
uid           [ultimate] xxxxx <xxxxxx@gmail.com>
sub   cv25519 2025-11-05 [E] [expires: 2028-11-04]
  • pub line: algorithm, creation date, capability flags [S] (sign), [C] (certify), [E] (encrypt), [A] (authenticate), [R] (revocation).
  • Fingerprint: 40 hex characters that must match what the owner publishes elsewhere.
  • uid entries: every declared identity plus trust level.
  • sub blocks: encryption or authentication subkeys with their own expiration timers.

For Git signing I rely on secret key fingerprints:

gpg --list-secret-keys --keyid-format LONG

Need to tweak a key? gpg --edit-key KEYID exposes expiry changes, new user IDs, and cross-signing. To double-check every subkey, I run:

gpg --list-keys --with-subkey-fingerprints your@email.com

Encrypting and Decrypting Data

Encrypting to a Recipient

# Basic encryption
gpg --output message.asc --encrypt --recipient bob@example.com message.txt
# Specify your sender identity
gpg --output message.asc --encrypt \
    --recipient bob@example.com \
    --local-user your@email.com \
    message.txt
  • --armor emits ASCII-armored output for chat, email, or Markdown:
-----BEGIN PGP MESSAGE----- 
Version: GnuPG v2.0.22 (GNU/Linux)  hQEMA12345678901234 

...content... 

-----END PGP MESSAGE-----
  • GPG automatically selects the freshest valid encryption subkey for each recipient. If you only have their primary key, refresh from a key server before sending anything sensitive.
  • Only the holder of the matching private encryption subkey can decrypt your message — the primary key simply vouches for the subkey’s legitimacy.

Signing and Encrypting Together

gpg --output message.txt.gpg --encrypt \
    --sign --local-user a@example.com \
    --recipient bob@example.com message.txt

When I decrypt that file, GPG verifies the embedded signature automatically. There’s no way to verify the signature separately because it sits inside the encrypted payload.

Detached Signatures for Separate Verification

gpg --output message.txt.sig --detach-sign message.txt
gpg --output message.txt.gpg --encrypt --recipient bob@example.com message.txt

Recipients need both files:

gpg --output message.txt --decrypt message.txt.gpg
gpg --verify message.txt.sig message.txt

For transparency I often share gpg --import sender-public-key.asc or even pipe a full -----BEGIN PGP PUBLIC KEY BLOCK----- directly into gpg --import.

Show Encryption Details and Signers

gpg --list-packets message.asc

This reveals the signing key ID, timestamps, and packet structure without needing a passphrase. It’s an easy way to audit who encrypted or signed a blob.

Decrypting

gpg --output message.txt --decrypt message.asc

GPG prompts for the appropriate private subkey passphrase, prints signature status if available, and writes the plaintext. Treat warnings like “untrusted signature” seriously — they signal you haven’t established a trust path to that key yet.

Stay Ready with Revocation Certificates

If I ever lose a private key or forget the passphrase, I want a revocation certificate ready to go:

gpg --output alice-revocation.asc --gen-revoke youremail@example.com

I store it offline (encrypted USB, paper, or a hardware token) so I can upload it to key servers or WKD if compromise strikes.

Exporting Your Public Key

Sharing my key is as simple as:

gpg --armor --export youremail@example.com > alice-public.asc

That ASCII block can live on a personal site, a README, or a CI repository to automate trust bootstrapping.

Integrating with Everyday Tools

  • SSH: enable enable-ssh-support in gpg-agent.conf to let hardware-backed authentication subkeys act like SSH keys.
  • Git: git config --global user.signingkey KEYID plus git config --global commit.gpgsign true ensures every commit carries a signature.
  • Secrets management: tools like pass, gopass, and git-crypt lean on GPG for encryption, so well-managed subkeys simplify app secrets.

Understanding how GPG plugs into these workflows keeps passphrase prompts manageable and makes automation-friendly PGP key management much smoother.

Wrapping Up

GPG remains one of my favorite ways to build trust across open systems. We covered interactive and batch key creation, smart use of subkeys, encryption workflows, packet inspection, revocation readiness, and integrations that power secure email and software releases.

Thanks for reading. If you liked the article, join my newsletter for hands-on cryptography and AI-engineering tactics . Have a question or a favorite GnuPG trick? Drop it in the comments so we can learn from each other.


메타데이터
post_id
9ec27ab2c2eb
slug
introduction-to-gnupg-9ec27ab2c2eb
url
https://blog1.neuralengineer.org/introduction-to-gnupg-9ec27ab2c2eb
canonical_url
https://blog1.neuralengineer.org/introduction-to-gnupg-9ec27ab2c2eb
author_url
https://medium.com/@pi45757
status
ok
fetched_at
2026-07-15 15:09:51