GnuPG Part 4 – Encrypt and Sign Files
GnuPG is typically used by other programs, such as email clients, that automatically use the keys contained in your keyring for encryption and signing. However it can also be used to manually encrypt, decrypt, sign, and verify files using gpg
commands. While you may rarely need to do this in practice in the real world, it is a great exercise for understanding how public key encryption and signing works.
Contents
Create a Test File
We’ll need a file to work with for these examples, so we’ll simply create one named testfile.txt containing the text “This is a test.”
echo "This is a test." > testfile.txt
Encrypt the File
To encrypt a file, you must use the --encrypt
option, the --recipient
option to specify a recipient (i.e. the public key to encrypt with), and the --out
option to specify an output file. The file to be encrypted must be at the end, which can make the full command feel a bit confusing at first.
gpg --out encryptedfile.asc --encrypt --recipient alice@example.com --armor testfile.txt
If you do not specify an output file with --out
, the encrypted file will be automatically saved in the current working directory with .asc
appended to the original file name if the --armor
option was used, or .gpg
if it was not.
If the recipient’s public key has not been signed, as explained in Part 3, you will get a warning prompt asking for confirmation.
Since we used the --armor
option, we can view the contents of the encrypted file and see the ciphertext.
cat encryptedfile.asc
-----BEGIN PGP MESSAGE-----
hQGMA1XbZzXhupAbAQv/RswYvraPE4/JdZrTNQCQ9LNKTDqEGPqozI+jEvndSLJf
Jv6/yjjBUQIEMNV80iyYCGiogJAidelJb5+tqg/sClkxtLehBQl/9wlMIlkOa/h4
PKr6ykkBQxmG5b1wzplxcr3M84tnZ2EcgntgoXaufyKo7OBNrwrJieBqBx1SBKE7
Bg73jq+MMOWAKcWUoCVjbzt/BJawNj09SQnFIO23ybMiDw/fclJloH9AAFUTrVct
IVhBIGqp8CszzSusqXdju5sbvH2aJqU9EcRDVZ1kZi60/bMbkY74guWbuxS6b59E
My0DYN++X/Z0FiDKxW/vvZyawATBhXlpIWpo3IEG/4SfCs13x3GtcSBbvMyZAM9E
aqY7Lt6Cp7ytmH/E5sRl+njbS+5wc01g+3PBwBQ/dARTTHpzQ1aEZaIDhO3ZcjGD
p8Xpqfpe9jM9utf/kfiXeWYZtvTMlmsaROJo01hrrPieue2Rgu+PqlFz4i6aJZ+W
bMJBNoko9pRRjzx0paS60lgBQrdzleVbT1JaL+XrAs/Qx8S50kw3e9i/jCPBeBoF
cMN/uq0nIClFQfV5xLIJ+O/OxCyFLYtJbgMv0XQpALCdJkhQTNzRz6eAEQlW5u/Q
CCT4vbJMhE1V
=Yj49
-----END PGP MESSAGE-----
Decrypt the File
The recipient can decrypt the file with the --decrypt
option (assuming they possess the corresponding private key).
gpg --out decryptedfile.txt --decrypt encryptedfile.asc
Unlike --encrypt
, the decrypted output will simply be displayed if the --out
or redirect options are not used to write it to a file.
Sign the File
Whereas encrypting a file provides confidentiality, signing a file provides integrity by allowing the recipient to verify that the file is truly from the purported sender; and was not modified in transit. In a way it is the functional opposite of encryption, since signing uses the sender’s private key and can be verified by anyone with the public key.
You can sign a file using the --sign
or --clearsign
options. The --clearsign
option is similar to --armor
in that it creates the signature in plain text rather than binary. I will use it in this example for the sake of clarity.
gpg --clearsign testfile.txt
If you do not specify an output file with --out
, the signed file will be automatically saved in the current working directory with .asc
appended to the original file name if the --clearsign
option was used, or .gpg
if the --sign
option was used.
If you view the contents of the signed file, you will see the original content as well as the signature.
cat testfile.txt.asc
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
This is a test.
-----BEGIN PGP SIGNATURE-----
iHUEAREIAB0WIQT+Ql29bFIAmkx/4jr2NmhDPqcKLQUCY5TIOwAKCRD2NmhDPqcK
LcXkAP0ddy6ezclw0OAKErdRKm5pNv37GWtsyNU3E387sm6hqgD/f8yonnMYKpRb
7FfBz7CcbLaINZxyWosm3GYHqUUmqVQ=
=oDZU
-----END PGP SIGNATURE-----
Verify the Signed File
The recipient can verify the signature on the file using the --verify
option. The resulting output will tell you if the signature is good.
gpg --verify testfile.txt.asc
gpg: Signature made Mon 05 Dec 2022 11:13:35 AM MST
gpg: using DSA key 197698E11D9E5B6787C4B55FE1A00903B0E16687
gpg: Good signature from "Bobby " [full]
Encrypt + Sign
Of course you can both encrypt and sign a file before sending it, and both functions can be done in the same command. This provides both confidentiality and integrity, and is the standard practice of most public key encryption systems.
To do this, use the --sign
option after the --encrypt
option.
gpg --encrypt --sign --recipient alice@example.com --armor testfile.txt
Note that when doing this, signing is performed as part of the encryption rather than as a separate function, so there is no option (or point) for using --clearsign
. The signature will be encoded into the encrypted message. You can still use the --armor
option.
The recipient can then use --decrypt
on the file, and the signature will be verified as part of the decryption.
gpg --decrypt testfile.txt.gpg
gpg: encrypted with 3072-bit RSA key, ID B7A021383ADD3D0F, created 2022-12-01
"Alice <alice@example.com>"
This is a test.
gpg: Signature made Sun 11 Dec 2022 03:27:45 PM MST
gpg: using DSA key FE425DBD6C52009A4C7FE23AF63668433EA70A2D
gpg: Good signature from "Bobby <bobby@example.com>" [full]