GPG’s primary function isn’t just encryption; it’s about establishing trust and verifying identity in a world where messages can be intercepted.

Let’s say you want to encrypt a sensitive configuration file, secrets.conf, for your colleague Alice.

# First, ensure you have Alice's public key imported
gpg --list-keys alice@example.com

# If not, import it (assuming you have her public key file, alice.pub)
gpg --import alice.pub

# Now, encrypt the file for Alice
gpg --encrypt --recipient alice@example.com secrets.conf

# This will create secrets.conf.gpg

When Alice receives secrets.conf.gpg, she’ll use her private key (which only she has) to decrypt it.

# Alice decrypts the file
gpg --decrypt secrets.conf.gpg > secrets.conf

# Or, more commonly, she'll just run:
gpg secrets.conf.gpg
# GPG will automatically decrypt it and prompt for her passphrase

The magic here is asymmetric cryptography. Your public key is known to everyone, allowing them to encrypt messages for you. Your private key, however, is a closely guarded secret, and it’s the only thing that can decrypt messages encrypted with your public key. GPG uses this principle to ensure that only the intended recipient can read the message.

Internally, GPG uses a hybrid encryption scheme. For efficiency, it generates a random, one-time symmetric encryption key. It then uses this symmetric key to encrypt the actual file content. The symmetric key itself is then encrypted using the recipient’s public key (asymmetric encryption). This encrypted symmetric key, along with the symmetrically encrypted file content, forms the final .gpg file. When decrypting, the recipient uses their private key to decrypt the one-time symmetric key, and then uses that symmetric key to decrypt the file content.

The most surprising part is that GPG’s default encryption mode (--symmetric) uses the same passphrase to encrypt and decrypt. This is convenient but less secure if the passphrase is weak or compromised, as it doesn’t leverage public-key cryptography. For true secure communication between individuals, you must use --recipient with imported public keys.

If you want to sign a file to prove its authenticity, you use your private key.

# Sign secrets.conf with your private key
gpg --sign secrets.conf

# This creates secrets.conf.sig (detached signature) or secrets.conf.gpg (signed and encrypted)
# If you just want a detached signature:
gpg --detach-sign secrets.conf

When someone receives secrets.conf and secrets.conf.sig, they can verify it using your public key.

# Verify the signature
gpg --verify secrets.conf.sig secrets.conf

If you encrypt and sign a file for Alice:

# Encrypt and sign for Alice
gpg --encrypt --sign --recipient alice@example.com secrets.conf

Alice will be prompted for her passphrase to decrypt the file, and then GPG will automatically verify the signature using your public key. If the signature is valid, it means the file hasn’t been tampered with since you signed it and it indeed came from you.

The real power comes when you understand key management: generating keys, exporting public keys, importing other people’s public keys, and crucially, verifying the authenticity of those public keys before trusting them. This verification step is often done out-of-band, like in person or over a trusted channel, to prevent man-in-the-middle attacks where an attacker might substitute their own public key for yours.

Understanding how to manage trust in GPG keys, beyond just importing them, is the next hurdle.

Want structured learning?

Take the full Cryptography course →