GPG Cheat Sheet

Ángel Ortega

This is a very basic guide to use GPG (GNU Privacy Guard), the free software version of the classic PGP (Pretty Good Privacy) tool for signing, encrypting and verifying information. It can be handy if your Email client does not directly support it. This guide explicitly does not cover creating and maintaining keys and keyrings.

For this tutorial we have the following two individuals: Angel, with email address angel@triptico.com and Johannes, with email address johannes@comam.es. They both have GPG installed on their systems and have valid keys. Additionally, each user have another one's public key installed in ther keyrings.

Also, there is a two line message they want to share:

I am the voice of Mother Earth,
from whence all horrors have their birth.

Angel wants to send the creepy message to Johannes. Also, he wants to be sure that Johannes can check that he is who really sent the message. So he runs the following command in its terminal:

gpg -s --clearsign

GPG politely says the following:

You need a passphrase to unlock the secret key for
user: "Angel angel@triptico.com"
1024-bit DSA key, ID 70C9B100, created 2012-11-07

Enter passphrase:

This operation implies the use of Angel's private key, that is password-protected inside his keyring. If the password is correctly entered, GPG waits silently for text from its standard input. Angel pastes the message and GPG dumps the following:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I am the voice of Mother Earth,
from whence all horrors have their birth.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iEYEARECAAYFAlvrxGIACgkQ5CXHVHDJsQBOagCfQAFQoZyFfegGZUa8oWwn/srg
1RwAoMFcDABbLpqaqpwIVqv5U4pYvdVb
=q64b
-----END PGP SIGNATURE-----

This piece of text (including the BEGIN... and END... lines) can be pasted to the email body of a message sent to Johannes. Please note that you can write whatever you want outside the PGP boundaries and the message will still be considered valid when the signature is checked. So this can be the full email body:

Hey, Johannes. This is what was said:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I am the voice of Mother Earth,
from whence all horrors have their birth.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iEYEARECAAYFAlvrxGIACgkQ5CXHVHDJsQBOagCfQAFQoZyFfegGZUa8oWwn/srg
1RwAoMFcDABbLpqaqpwIVqv5U4pYvdVb
=q64b
-----END PGP SIGNATURE-----

Best regards, Angel

Of course, the surrounding text must not be considered signed text. This is a common mistake.

Johannes receives the message in his Inbox. He's absolutely unsure if it's really Angel who quoted the eerie text; so, he just calls GPG with no arguments:

gpg

And gets the following reply:

gpg: Go ahead and type your message ...

Johannes selects and copies the full message body and pastes it into GPG's standard input. Then the program replies:

I am the voice of Mother Earth,
from whence all horrors have their birth.
gpg: Signature made Tue Nov 13 15:02:38 2018 CET using DSA key ID 70C9B100
gpg: Good signature from "Angel angel@triptico.com"

So Johannes can be confident than Angel really sent the two-line message (the rest of the text is considered irrelevant and is ignored). GPG does not need any password to check the signature: all it needs is Angel's public key that it's stored in Johannes' keyring but not protected in any way (Angel's public key can be shown in his web home page or printed and glued on the street lamps of the town if he wants, as it's not sensible information).

Please note that, though GPG apparently mixed the message and its own information, the first one is sent to the standard output stream and the second one to its standard error/status stream; Johannes only sees them together because of the way his terminal shows these channels by default.

Let's suppose some evil being tries to feed its dirty lies to Johannes, trying to take advantage of the confidence between both and impersonating as Angel. So it somehow obtains a copy of the message and does some subtle changes:

Hey, Johannes. This is what was said:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I am the voice of Mother Moon,
from whence all horrors have their doom.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iEYEARECAAYFAlvrxGIACgkQ5CXHVHDJsQBOagCfQAFQoZyFfegGZUa8oWwn/srg
1RwAoMFcDABbLpqaqpwIVqv5U4pYvdVb
=q64b
-----END PGP SIGNATURE-----

Best regards, Angel

Johannes repeats the previous operation but gets the following output

instead:

I am the voice of Mother Moon,
from whence all horrors have their doom.
gpg: Signature made Tue Nov 13 15:02:38 2018 CET using DSA key ID 70C9B100
gpg: BAD signature from "Angel angel@triptico.com"

That BAD signature... thing should trigger all kind of alarms.

The GPG tool also returns different output values for valid and invalid operations that can be useful in scripts and programs. If you are not a programmer nor a sysadmin, you can ignore this.

But Angel may occasionally consider that proving his authorship is not enough; he wants the message to be absolutely hidden to anyone but Johannes. So he opts for PGP/GPG encryption, invoking the command

gpg -e -a -r johannes@comam.es

and pasting the two-lines message into GPG's standard input. GPG barfs the following wall of text:

-----BEGIN PGP MESSAGE-----
Version: GnuPG v1

hQQOA6n6KzujHJfZEBAAkrlIZp/8IpWhw/H4pjCCzl1GgDvpLiqAvw4b1x9SXcPO
bH+yp9M8K34+Slp7QIsBWWp+Z49ZAWeendMSW32iMoxakqt4K2PV27S8qgKAqqPk
bWjCFmJ7ERIy1XSxarSUJaRzvWhwXI/9NVecei6boogSlowxce1GMvranzMJKR3J
RrMR5AsfHWpnjyvcOjNV+o/OGrE6avPitW4ieWX0PzrLdgXS6tkwFUu9pOeB6OF+
YRgVQKwtcEoPk92PHBGlvfahvT3KbWaso6OOa7mQHI+YgjbA3g2pCDobcsm30wED
2Sw2XbU17KQWKU5YUm/RMNhsvYFrYnBA/jiHzqmsw4YeJrImu2MfkjScTgiAdL3S
hIqGz3+AEBH+lTLHKPF3spQV9GDkn2es6DpRmxVF5TOEsb1toUznAqsADwz0Edlb
3FEzeN7Kizui8UJ+HR6al+UiDm0X5v03r1tCMjxmZnq4fkmDG5/tH+j1319s33G7
xDf/upUw1W5XLd+zBgdiTHD1ADxT4fWFiRH6by+CLTdFwt62mREmd1lW6YxwhMEV
RGGZQzyLp3uVOg1z4jT2q7bz4MOBEPxY1L44zOENkH54yIITQ46Ambiwc572iJQQ
/vP23oFRDJQdvHndxjlbFA2hJMSRavzTn3VzUYJzPGbnB2JzULUyqOH/obL4TMYP
/2oxdkJjqQu8Z4xtZOPne5r7q4Ml8mIPtb+h2TbC0hHLi1DDqOQyLJcMmeSKMr3T
XAOphMzbaHJYBODJB5w86Qxw6wAah1/+j6525NeHYYLPGACb9n8ujnXQP3l/Kpf6
9/a2+0g3uRCi8GoriLHQN2slEg0hAgSI8t217HTC0fWeNtkVqInd7qUcE04RNa/e
0nhVXDdbhTRMBkLfSRc/3wELVxrevo0K+bEwPUrJgX/9UROiP0lWJoSE0ezWhdCF
4XK/K6RQr+WZE6GjpfzTuqDZNjQdphcV2xnTKM5DnauQNOX3+p2T+Ri/8JmnF+xx
z3MGIxtNWIq1u71ykZZbaNVMRniGQ3QRwJiP7/DN2N08Sz4QO3cjqseK6TeCz+Av
3vWGP339NUVKS/QHORwmoOQHm9AKwgqQedtgHn/u2hQpLLE35pCZOv5/GgAeJl4d
/w8Qd7xNKDSVZEN82cYb5LJsY/Z0vVaqII66bm+iZQgdaa+uuNGtVITU3lgRMAJP
Z0SBbzmNYE/4iLe/B79JK+057KjGlnpswtaYOwe0jS4RB9XRcgE7KBryo4o6h9E9
udt0WF2h05iHzK7i1ewMJif7WszadnFXG8DifsFiteeEARmetLi89WiSVYdSiFsI
xRhqIzGA0nz3XWuEBNw00UAl0vtkvDlhGEtSAW19MScc0oAB0TFPswUkicX36SN3
8kZHiLCmIbucq33h+3TgEtiFjXj+pWFjlz4mTTRAvnr+nYn7FDTgblFMF/NJOXZq
lSZNeF6PkngjK1+hZTogMBN5OL1iFP1D+IP+7ANydQdQL56V6yaU4YOtJv++l2F4
ghA5wgMRlC9MNWRzptK2qZJmdQ==
=NXsq
-----END PGP MESSAGE-----

Given that GPG has everything it needs to encrypt a message to Johannes (i.e. his public key), no password nor any more information is requested.

Note that, when the message is encrypted, Angel has no way of decrypting it because he does not have Johannes' private key. There is no other way of decrypting this message than using that key.

As with signing, any text can be written surrounding the PGP boundaries. Also, it should not be trusted, as it's not really part of the message.

Johannes receives the block of garbage and proceeds the same as with the signed message:

gpg

But like every time a private key is involved, GPG asks for the password to the Johannes' keyring:

You need a passphrase to unlock the secret key for
user: "Johannes johannes@comam.es"
4096-bit ELG-E key, ID A31C97D9, created 2012-11-07 (main key ID 70C9B100)

Enter passphrase: 

If it's entered correctly, GPG waits for text from its standard input. Johannes copies the full message into it and GPG dumps the omen from Mother Earth with some additional information:

gpg: encrypted with 4096-bit ELG-E key, ID A31C97D9, created 2012-11-07
     "Johannes johannes@comam.es"
I am the voice of Mother Earth,
from whence all horrors have their birth.

If the encrypted message is garbled someway, GPG will complain about the data block integrity:

gpg: CRC error; C73B95 - 357B2A

For complete paranoia, a message can be encrypted AND signed. This is how it's done from Angel's view:

gpg -es -a -r johannes@comam.es

As it needs Angel's private key for signing, the passphrase for his keyring is requested. After pasting the two-line message into GPG's standard input, The response is another scary block of garbage:

-----BEGIN PGP MESSAGE-----
Version: GnuPG v1

hQQOA6n6KzujHJfZEA/8CkbHeZ5Q3VBpsGia90kKJgWcI3/Wbphi5JoSEpm8ezSl
ffUhxoiO4NKM5hcJM+v+dqq7Wo0C4P2YxVnsUPIf9xk/aF6KmZttFU8H3o5/8+48
KYQtp2ZBHlSzuDTIwsQyvXAIgg9CyXUTmdALPGaO6X8Yj+UphHghVu6vF1LwQw0k
G9EfnjRmyEWzb+C4Rzvh6Sf0g+OMvuFtFf9fuSMfzAnwv8+U8diyJYusiuPUrNz7
Q0b7be5MBhVlTyTfqpnD3zOsqt5EP1NewZgFn9HSxjmHMOGeaR3ahKEQVDyRglqK
49SsPz402meJf3WrU3HUVsjen5I1q8CrJ+La+uxjodF4JAKhIX1qYJ6hySJI1P+w
SjGP66VYNFwsYOSkMMlGsehCPNcaNhxZs3UATjd2RsnSNbcs50l+jEQj35EOXApx
fUaCjUisXfTNz4PPl5slkfkQRTJ1nC8IVboOBk1REFmgJ3KhER+MXhsqqH4gMOH8
VuGPh4p8nxX5I1WfFGOCtuXCRLCh2kMLdbVG5oDYEr2vPyfaL5EDDIIgao8v+k8E
mLsWrLOGnSrg14IJ6NZR5zWx9ZC9s9ICPBfIgzKCgqb0wpjLiEP453Ymfl4/MRVr
L5eXdttOfHHcJIultQcmF4FBlC2pHLXUKyJqkPhnHDnqWCtIwOuZHTS9LY6U5TQP
/2Moh6TXe+aJTt0k6k4q9/xhCSIWpeOGq24gLQVS5DPTm+tYLSLm6x8nccPmwB2P
FRXa7BQnDZ4PnOOS1lpo3kapZsmwY5upeZJ6ArI1c8hzHEVrducRPHQC2BrQ9/yj
cKL7vpQNlHAtaSwI1oYhd+HqQLYUfzpDVxYY3ndk1OEWoNfwLFFcCj4jAMJTwD2J
JJFhA7nY4CPggkTAr+8xIhzFbkWRexI+g/hfSH0oMKOidMmqCEsfZZStqwM0pfUW
Ufc28AN+9r6n/6c7qOyZ+HWpbETceLfrUuYwLZ8ExzirJvqILWpMEZduYywDrLko
8wH73JGHue+bdhW62MNoF45hOaSTBwB7ZZ9LmjqaADPeBVipZUUJPUpTuRg5k+o5
JfDD6KbbIVl8cqKnLsBRfW5kDov7qKjxZjrbZ88KIa9qk0jrgXc1d0E74Cv/Lvdv
L7q1Odd1Wsviug0Rdt5YzENXHqZrlCx0BkxBQWdoWhTurdloNITkWir2rxt50tCs
AJlisig+zGQXkfzoiMMagS4MK2K8slyatT7KpbW9Tr0ueMrHN0Rm1kklw+b7/vnp
3x8HHJq2Ia8WU3BoaO5cbD8l2d6st/Nhxgf2e+TxBGN87LSpZPzlSOoUISc1pSPB
RdmACYkrPH+6OaaWjY9uzeSygWbVz3p+lBTL6ZICtQvz0sASAU9lY41R3ZsoTWUv
/E/fTb4U3y4fTsR4G06Y4gyexh4Yyejh/s2mBc3VG4TCkZyubQilXy8mrhM3NJpj
DEG6zZQEMtndp1Wq5z+qcvrJ2AF+j5R4nm7zNdt4XjrXOA+3zfzeD+avnfCjKAhT
Jw0kzUrCzj34xc3iScQmwrdLEETk+66Ypv30ZEcdlzTrQUgcXW1WAqfJfaL8CJf1
69oTyoWRAAXkpyJGZoIafzS+Cvjupneybqab1+sL8qajpptQBglCaatioFJrZWnk
qt4LUBgD
=G+4J
-----END PGP MESSAGE-----

The difference is that, when Johannes tries to check the message as he usually do:

gpg

The following is shown:

You need a passphrase to unlock the secret key for
user: "Johannes johannes@comam.es"
4096-bit ELG-E key, ID A31C97D9, created 2012-11-07 (main key ID 70C9B100)

Enter passphrase: 

This should be expected, as it's a message for Johannes' eyes only. The output is a bit different, though:

gpg: encrypted with 4096-bit ELG-E key, ID A31C97D9, created 2012-11-07
     "Johannes johannes@comam.es"
I am the voice of Mother Earth,
from whence all horrors have their birth.
gpg: Signature made Tue Nov 13 16:03:20 2018 CET using DSA key ID 70C9B100
gpg: Good signature from "Angel <angel@triptico.com>"

GPG dumps information about the key the message was encrypted for, the message itself and the results of the validation test.

Sometimes Angel may want to sign a binary file (a zip package, an image, etc.), for the purpose of helping people know that the file he has and the one they have has the same content. But adding PGP/GPG crap to this kind of files cannot be done because it corrupts them; so, you have to use a detached signature. Suppose you have the file

abraham_lincoln_nude.jpg

Then you can sign it by executing

gpg -ab abraham_lincoln_nude.jpg

A familiar prompt from GPG will be shown:

You need a passphrase to unlock the secret key for
user: "Angel angel@triptico.com"
1024-bit DSA key, ID 70C9B100, created 2012-11-07

Enter passphrase: 

After a successful password GPG creates a file with the same name as the signed one, but with the .asc extension appended, and that looks like:

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iEYEABECAAYFAlvr2GAACgkQ5CXHVHDJsQCeagCfTn72ZUBeVlWwTMvTMcGIbZsL
9q4An0ZDXwAaMb5cyHUsybXoXZ/yjw8U
=R3uI
-----END PGP SIGNATURE-----

Both the file and the signature can now be made available to others.

Johannes can validate that the binary file and Angel's signature on it match by calling

gpg abraham_lincoln_nude.jpg.asc

Note that both the file and the signature must be on the same folder. GPG shall return the following:

gpg: assuming signed data in `abraham_lincoln_nude.jpg'
gpg: Signature made Wed Nov 14 09:10:08 2018 CET using DSA key ID 70C9B100
gpg: Good signature from "Angel angel@triptico.com"

For signing text (will ask for sender's passphrase):

gpg -s --clearsign < msg.txt > msg.signed.txt

For checking a signed text (no passphrase needed):

gpg < msg.signed.txt

For encrypting text (no passphrase needed):

gpg -e -a -r user@destination < msg.txt > msg.encrypted.txt

For decrypting an encrypted text (will ask for receiver's passphrase):

gpg < msg.encrypted.txt

For encrypting and signing text (will ask for sender's passphrase):

gpg -e -a -r user@destination < msg.txt > msg.both.txt

For decrypting and checking text (will ask for receiver's passphrase):

gpg < msg.both.txt

For signing binary files (will ask for sender's passphrase):

gpg -ab binary_file

For checking signed binary files (no passphrase needed):

gpg binary_file.asc

Harry can sleep peacefully because he always encrypts and signs his email messages.

Though the examples here are given using GPG version 1, you should really use version 2 (the executable is called gpg2 in those systems that deploy both versions). I've used the older version because one of the features of version 2 is that it includes an agent that asks for passwords in GUI dialogs (if a GUI is available) and retains them for reasonable periods of time. This is of course convenient, but it may make less clear the cases where a passphrase to the keyring is needed.

If you found this post useful, you may buy Ángel a coffee.