Tails / GnuPG / OpenPGP

Keys, messages
and signatures.

A step-by-step terminal guide to creating keys, exchanging public keys, and encrypting and decrypting messages on Tails.

Download HTML

Prepared 2026-10-06 · Commands run inside your Tails VM · No installation or administrator access required

What you describe sounds like OpenPGP, using the terminal program gpg. Recent Tails includes GnuPG and its graphical interface, Kleopatra; you don’t need to install anything or use sudo. Tails documentation

The commands below cover the workflow you listed. Replace the example names and fingerprints with the ones from your exercise.

The key relationships are:

Task Key used
Somebody encrypts a message for you Your public key
You decrypt that message Your private key
You encrypt a message for somebody else Their public key
You sign a message Your private key
Somebody verifies your signature Your public key

Your public key can be shared. Keep your private key and its passphrase private.

1Open Terminal and prepare a working folder

Run these commands individually:

gpg --version
umask 077
mkdir -p ~/pgp-exercise
cd ~/pgp-exercise

umask 077 makes newly created files accessible only to your user.

Tails-specific point: saving a file in your home folder does not normally preserve it after shutdown. If your VM supports configured Persistent Storage, the GnuPG feature preserves your keyring; the Persistent Folder feature preserves files saved there. An ordinary ISO-based VM might have neither, so complete the exercise before shutting down. Persistent Storage, Tails in a VM

2Create your public/private key pair

gpg --full-generate-key

Follow the prompts:

  • Use the algorithm and size specified by the exercise. If none is specified, RSA and RSA, 3072 bits, is a broadly compatible choice.
  • Choose an expiration, such as 1y, unless instructed otherwise.
  • Enter the name and email required by the exercise. The comment can be blank.
  • Confirm and set a strong passphrase when prompted.

GPG creates both keys and stores them in its local keyring automatically. You don’t create the public and private keys separately. GnuPG key-generation reference

Display your private keys and their fingerprints:

gpg --list-secret-keys --keyid-format long --with-fingerprint

Find your new key. The long hexadecimal line beneath sec is its primary fingerprint, which identifies it precisely.

Copy that fingerprint, without spaces, into this command:

my_key='PASTE_YOUR_FULL_FINGERPRINT_HERE'

This defines a terminal variable for the following commands. Replace the placeholder first.

3Export both keys as readable text files

gpg --armor --output my-public-key.asc --export "$my_key"
gpg --armor --output my-private-key.asc --export-secret-keys "$my_key"

The second command may ask for your passphrase.

--armor produces ASCII-armored text: a text representation of the key, suitable for copying into a website. It does not reveal the mathematics in a human-readable explanation.

Check your public key:

cat my-public-key.asc

It should look like:

-----BEGIN PGP PUBLIC KEY BLOCK-----
...
-----END PGP PUBLIC KEY BLOCK-----

Your private export begins with -----BEGIN PGP PRIVATE KEY BLOCK-----. Do not submit that file to the website or send it to another person.

Without --armor, GPG exports binary files:

gpg --output my-public-key.gpg --export "$my_key"
gpg --output my-private-key.gpg --export-secret-keys "$my_key"

You only need those binary exports if the exercise requests them. Changing a filename from .gpg to .asc does not convert its contents. GnuPG export reference, ASCII armor reference

4Save and import somebody else’s public key

If the website gives you a text block, run:

cat > recipient-public-key.asc

Then:

  1. Paste the entire public key block, including its BEGIN and END lines.
  2. Press Enter after the final line.
  3. Press Ctrl+D to finish saving.

Here, cat is receiving text directly; your pasted text is not being executed as terminal commands. In Terminal, paste is usually Ctrl+Shift+V.

Inspect the key before importing:

gpg --show-keys --with-fingerprint recipient-public-key.asc

Compare its full fingerprint with the fingerprint supplied by the exercise or another trusted source. A name or email alone doesn’t authenticate a key.

Import it into your keyring:

gpg --import recipient-public-key.asc

List your public keys:

gpg --list-keys --with-fingerprint

Set another variable using the recipient’s primary fingerprint:

recipient_key='PASTE_RECIPIENT_FULL_FINGERPRINT_HERE'

Importing adds the key to your keyring; it doesn’t prove who owns it. GnuPG key-exchange guide

5Encrypt a secret code or a message

A code and a longer message use the same encryption operation. First save the plaintext:

cat > secret-code.txt

Type or paste the code, press Enter, then Ctrl+D. This avoids putting the secret itself in a shell command saved in command history.

Encrypt it to the recipient:

gpg --armor --output secret-code.asc --encrypt --recipient "$recipient_key" secret-code.txt

Display the result:

cat secret-code.asc

Copy the entire block into the website:

-----BEGIN PGP MESSAGE-----
...
-----END PGP MESSAGE-----

For a longer message:

cat > message.txt

Enter the message, then Enter and Ctrl+D.

gpg --armor --output message.asc --encrypt --recipient "$recipient_key" message.txt
cat message.asc

If GPG warns that the key’s ownership is unverified, confirm only after checking its fingerprint. You don’t need to mark someone else’s key “ultimately trusted” to encrypt to it.

Only the recipient can normally decrypt these outputs. To make a message decryptable by both the recipient and yourself, include both keys:

gpg --armor --output message-for-both.asc --encrypt \
  --recipient "$recipient_key" --recipient "$my_key" message.txt

Encrypt locally and paste only the ciphertext into the website when the task calls for confidential communication. Tails specifically advises against composing confidential plaintext in a browser. GnuPG encryption reference, Tails guidance

6Decrypt a message somebody sends you

They must have encrypted it to your public key.

Save their encrypted block:

cat > received-message.asc

Paste everything from -----BEGIN PGP MESSAGE----- through -----END PGP MESSAGE-----, then Enter and Ctrl+D.

Decrypt directly to the terminal:

gpg --decrypt received-message.asc

Or save the plaintext:

gpg --output decrypted-message.txt --decrypt received-message.asc
cat decrypted-message.txt

Enter your private-key passphrase if prompted. GPG automatically selects the appropriate private key.

You don’t need the sender’s public key to decrypt. You need it to verify their signature if they signed the message. Importing their public key cannot fix a No secret key error: that error means your keyring lacks a usable private key for the message’s recipient. GnuPG decryption reference

7If “encrypt with a password” is requested instead

This is a different mode: it uses a shared passphrase instead of the recipient’s public key.

gpg --armor --output password-encrypted.asc --symmetric message.txt

GPG asks you to choose the encryption passphrase. Decrypt with:

gpg --decrypt password-encrypted.asc

The recipient needs that same passphrase. This passphrase is separate from the passphrase protecting your private key. GnuPG symmetric encryption

8If signing is also part of the test

Sign and encrypt a message:

gpg --armor --output signed-encrypted.asc \
  --local-user "$my_key" --sign --encrypt \
  --recipient "$recipient_key" message.txt

For a signature stored separately from the original file:

gpg --armor --output message.sig.asc \
  --local-user "$my_key" --detach-sign message.txt

Verify that detached signature with:

gpg --verify message.sig.asc message.txt

The verifier must have the signer’s public key. “Good signature” confirms that the signature matches the message and key; the checked fingerprint establishes whose key it is. GnuPG signature reference

The three distinctions to remember during the test are: export shares a key; import adds a key; encryption uses the recipient’s public key, while decryption uses your own private key.