GnuPG, or gpg, is the free implementation of the well known Open PGP project. It allows you to encrypt or decrypt files based on keys. gpg uses what is commonly known as the public key cryptography, using a private and public key to allow safe encryption or decryption of files.
How gpg works
The private and public keys are required to offer security of files when transferring over unsecured networks. The private key is owned by the generator of the keys (which the owner should only have access to), and the other key is a public key (which can be distributed to anyone). The distribution list depends on what application you are using gpg for, and of course, the distribution list of users must have gpg installed as well.
The private key is for owners only and is further secured by a passphrase by the owner. The public key can be freely distributed or exchanged with other gpg users. Once you have been sent a public key from another user (or you may have downloaded it from a web site), you need to add it to your public keyring. This file holds all your public keys. You need this to encrypt files (assuming you are sending files to other users) using the intended recipients public key. They can then decrypt your encrypted file using their own private key.
In this article, I will demonstrate how to generate a pair of keys, as well as encrypting and decrypting files. Decrypting and encrypting can be used purely for ones own security, you do not have to share your public key if you are not exchanging files with other trusted users. I will also demonstrate how to sign a file and how to check the integrity of the contents. I will also demonstrate how to use gpg within a batch environment.
The current version of gpg is 2.0.16 and can be built from source. I have only been successful building it from source using a commercial C compiler. Since this is not an option for most administrators, I am using a pre-compiled binary gpg version 1.4.7 for this demonstration. Details of downloads can be found in the Related topics section.
$ gpg gpg: Go ahead and type your message ... ^C $
You may get a warning about insecure memory similar to the following:
$ gpg gpg: WARNING: using insecure memory! gpg: please see http://www.gnupg.org/faq.html for more information gpg: Go ahead and type your message ...
To get rid of this warning, make the gpg binary set uid:
chmod 4755 gpg
Generating your key pair
Before you can begin to encrypt or decrypt files, your first task is to generate your public and private key using the gen-key option of gpg. Listing 1 is a truncated output of the command. You will be asked questions about the type of key, size, and how long should the key life should be. For this demonstration, I have answered those questions provided below:
Key: DSA and Elgamal Key size: 2048 Never expire the key Name: David Tansley Email: email@example.com Comment: aix admin Passphrase: watchmaker
For clarity I have used my full name in the key generation during this demonstration, but the name can be any alias that identifies you. I could have used dxtans, for example.
Note: Keep your passphrase secure, do not forget it, as you will be prompted for it when using gpg operations on files.
Listing 1. generate keys
$gpg --gen-key gpg (GnuPG) 1.4.7; Copyright (C) 2006 Free Software Foundation, Inc. gpg: please see http://www.gnupg.org/faq.html for more information Please select what kind of key you want: (1) DSA and Elgamal (default) (2) DSA (sign only) (5) RSA (sign only) Your selection? 1
DSA keypair will have 1024 bits. ELG-E keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) Requested keysize is 2048 bits Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) Key does not expire at all Is this correct? (y/N) y Real name: david tansley Email address: firstname.lastname@example.org Comment: aix admin You selected this USER-ID: "david tansley (aix admin) <email@example.com>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O You need a Passphrase to protect your secret key:watchmaker gpg: /home/dxtans/.gnupg/trustdb.gpg: trustdb created gpg: key DD096620 marked as ultimately trusted public and secret key created and signed. uid david tansley (aix admin) <firstname.lastname@example.org> sub 2048g/25B15F46 2010-08-10
Once the keys have been created, a subdirectory will be present in your HOME directory called .gnupg . This directory will be the holding place for your public and private keys, as well as your public keyring. You will need public keys from users who send you their encrypted files, so you can decrypt them.
Now the keys have been generated, lets encrypt a file, then decrypt it.
Encrypting and decrypting a file for personal usage
The format to use gpg to encrypt files for personal usage is:
gpg <options> <filename>
Practically all options given to gpg are prefixed by two dashes, like so: – –
Encrypting a file for personal usage does not require the encrypt option. To encrypt a text file, specify the armour that creates a shield around the text. By default, gpg will assume it is a binary file you wish to encrypt. The symmetric option informs gpg to use a passphrase. Lastly, the name of the input file is parsed. In this case, it is the file-name myfile. Once the command is issued, you will be prompted to enter your passphrase. This phrase is the same one entered when the keys were generated. Notice we do not have to specify the type of cipher; by default gpg will use CAST5.
$ cat my_file Meet me at the same place tonight, come alone $ gpg --armour --symmetric my_file enter passphrase:
gpg will generate a new file with an extension of .asc, containing the encrypted information:
$ ls -l my_file* -rw-r--r-- 1 dxtans staff 46 Aug 12 19:37 my_file -rw-r--r-- 1 dxtans staff 211 Aug 12 19:37 my_file.asc
Looking at the now encrypted file, it is now unreadable:
$ cat my_file.asc -----BEGIN PGP MESSAGE----- Version: GnuPG v1.4.7 (AIX) jA0EAwMC/W81Yzg46lNgyUeKDVxXVGUNSVNv8x2HdzaDMLP4DRJlyjtxX5UXlhvH nM+/nftRgcbgJo/qmzKSa+XjoVqZALrVeFsdRm7yYGxLYRR1s5QhCg== =k+s4 -----END PGP MESSAGE-----
You can also specify the name of the encrypted file to be produced using the output option. In the following example, the encrypted file will be called myoutfile:
gpg --armour --output myoutfile --symmetric my_file
To decrypt the file just created, use the decrypt option specifying the name of the encrypted file. The format to use gpg to decrypt files is:
gpg <options> --decrypt <file-name>
The file will be displayed to standard output:
$ gpg --decrypt my_file.asc gpg: CAST5 encrypted data gpg: encrypted with 1 passphrase Meet me at the same place tonight, come alone gpg: WARNING: message was not integrity protected
To specify the output of the decrypted file, use the output option. In the following example the decrypted file will be called my_decrypt_file:
gpg --output my_decrypt_file --decrypt outfile
The following will achieve the same as the above example but this time using file redirection:
gpg --decrypt my_file.asc >my_decrypt_file
To disable gpg informational messages, use the quiet option when decrypting:
$ gpg --decrypt --quiet my_file.asc Meet me at the same place tonight, come alone gpg: WARNING: message was not integrity protected
Even after using the quiet option you may still get a warning about not being integrity checked. The warning is caused if the original file was not encrypted with modification detection checking enabled. This warning can be suppressed by issuing the no-mdc-warning when decrypting a file:
gpg --decrypt --no-mdc-warning --quiet my_file.asc
As a general rule, it is best not to have the warning at all rather then suppressing it. To encrypt a file forcing an mdc, use the option force-mdc:
gpg --force-mdc --armour --output outfile --symmetric myfile
Exporting and importing keys
When files are to be exchanged, the file is first encrypted using the intended recipients public key. Once the recipient gets the encrypted file, the recipient uses his own private key to decrypt the file. Typically, this public key can be uploaded onto a trusted site where uses can then download it and put it into their keyring. However, when using gpg within an enterprise business environment, and you are exchanging sensitive files, the users you give your public key to will be very selective. Accordingly, to receive encrypted files from other users, you will need their public key to unlock their file for you to read it; their public key will go into your keying.
Once your public key is exported, you can then transfer the key to its destination either by email, scp or ftp. The format to use gpg to export the public key is:
gpg --armour --output < file-name> --export <key-name>
Where key-name is the real name you entered when generating your keys. Notice I am exporting with the armour option, as the key will be exported in ASCII mode.
To view your keys, you can list your current key keyring using the list-keys option:
$ gpg --list-keys /home/dxtans/.gnupg/pubring.gpg ------------------------------- pub 1024D/DD096620 2010-08-10 uid david tansley (aix admin) <email@example.com> sub 2048g/25B15F46 2010-08-10
In the above example for the UID, I could use either david tansley or firstname.lastname@example.org, as both names identify me. In this scenario, I will use:
You can also list your private key with:
$ gpg --list-secret-keys /home/dxtans/.gnupg/secring.gpg ------------------------------- sec 1024D/DD096620 2010-08-10 uid david tansley (aix admin) <email@example.com> ssb 2048g/25B15F46 2010-08-10
To export my public key in ASCII mode to the file dxtans_pubkey:
$ gpg --armor --output dxtans_pubkey --export david tansley $ ls -l dxtans_pubkey -rw-r--r-- 1 dxtans staff 1180 Aug 14 08:34 dxtans_pubkey
Alternatively, I could use redirection to produce the output file, like so:
gpg --armor --export david tansley > dxtans_pubkey
Listing 2 . public key. Shows a truncated output of my public key
$ cat dxtans_pubkey -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.7 (AIX) mQGiBExhkgIRBACPxUNlJP9xTGUwbgs/6T9rG1p2CzODHszEyisjLAiKJ6sgTvdl /0Xr+ioEkknCq37XVotvu5+0plF3Say3BOtTL7qw1unL5kCWulYzvsc/BTrMiKYD Hmg5fjpR/pCXIYIsyJ0g+J0EHAEmMpH7fTOAhNgevK4d8J3GDz2liUmVXwCgzbKP MD5GS7y8AJ962Kj7LZx/jruTCYsD/GH6PgbzNw== =wLpz -----END PGP PUBLIC KEY BLOCK-----
The next task is to send my public key to user(s) that I want to send encrypted files to, so that they can decrypt the files using their own private key. In this demonstration, I am going to send my public key via email to the company security officer (busintel). That person’s fictitious email address is firstname.lastname@example.org.
The key can now be transferred via ftp, scp, or just pipe the export command into an email. In the following example, my public key is exported, and the contents are piped into the email content with the subject line of pubkey:
$ gpg --armour --export email@example.com | mail -s pubkey firstname.lastname@example.org
Alternatively, I could send it as an attachment file called dxtans_pubkey.txt in a email:
#!/bin/sh email@example.com mail -s " intel.. Here is my public key" $list <<mayday Thanks dxtans ~<!uuencode dxtans_pubkey dxtans_pubkey.txt mayday
Now the key has been sent, user busintel can now download the file to import it into his keyring. The format of the command to import a key is:
gpg --import <filename>
User busintel would now perform the following to import my public key, assume he saves my public key as dxtans_pubkey:
$ gpg --import dxtans_pubkey gpg: key DD096620: public key "david tansley (aix admin) <firstname.lastname@example.org>" imported gpg: Total number processed: 1 gpg: imported: 1
To confirm the public key is now in busintel’s key ring, user busintel could list his keys, like so:
$ whoami busintel $ gpg --list-keys /home/busintel/.gnupg/pubring.gpg ------------------------------ pub 1024D/2326BEEA 2010-08-11 uid busintel (company intel) <email@example.com> sub 2048g/8DCD62BC 2010-08-11 pub 1024D/DD096620 2010-08-10 uid david tansley (aix admin) <firstname.lastname@example.org> sub 2048g/25B15F46 2010-08-10
When decrypting files, gpg will ask if this person is who he says he is. You can inform gpg of your trust level in the person’s public key you hold by informing gpg of your trust level. The format of the command is:
gpg --edit-key <UID>
Listing 3 demonstrates how you can inform gpg of the trust for each public key you have in your keyring. When presented with the prompt, enter the keyword trust. Next, select from the menu your level of trust. In the following example, email@example.com is having his trust raised by user busintel to the level of ultimate trust.
Listing 3. Giving trust
$ gpg --edit-key firstname.lastname@example.org gpg (GnuPG) 1.4.7; Copyright (C) 2006 Free Software Foundation, Inc. pub 1024D/2326BEEA created: 2010-08-11 expires: never usage: SC trust: unknown validity: unknown sub 2048g/8DCD62BC created: 2010-08-11 expires: never usage: E [ unknown] (1). busintel (company intel) <email@example.com> import key: Command> trust pub 1024D/2326BEEA created: 2010-08-11 expires: never usage: SC trust: unknown validity: unknown sub 2048g/8DCD62BC created: 2010-08-11 expires: never usage: E [ unknown] (1). busintel (company intel) <firstname.lastname@example.org> Please decide how far you trust this user to correctly verify other users' keys (by looking at passports, checking fingerprints from different sources, etc.) 1 = I don't know or won't say 2 = I do NOT trust 3 = I trust marginally 4 = I trust fully 5 = I trust ultimately m = back to the main menu Your decision? 5 Do you really want to set this key to ultimate trust? (y/N) y pub 1024D/2326BEEA created: 2010-08-11 expires: never usage: SC trust: ultimate validity: unknown sub 2048g/8DCD62BC created: 2010-08-11 expires: never usage: E Command> quit
The trust setting has now been changed to ultimate trust for david tansley’s public key.
I would now perform the same process to import busintel’s public key into my keyring. Let’s now assume that has been completed. We are now ready to exchange encrypted files.
Encrypting and decrypting files using public keys
Let’s assume I have just completed some MIS statistics contained in a spreadsheet. I now need to send user busintel this sensitive file. The command format to encrypt a file with a public key is:
gpg <options> --encrypt --recipient(s) <uid of person(s) sending to> <filename>
The file name to encrypt is
monthly_mis.xls. The file name will be output as
2010_08_mis.xls. The recipient’s name is
As this file is not ASCII, I will not use the armor option. The following command will encrypt the file, using the information provided above, using busintel’s public key:
$ gpg --output 2010_08_mis.xls --encrypt --recipient 'busintel' monthly_mis.xls $ ls 2010* 2010_08_mis.xls $ cat 2010_08_mis.xls -----BEGIN PGP MESSAGE----- Version: GnuPG v1.4.7 (AIX) hQIOA/j/okH5aj/XEAgAhRaxI2fZnBoShlFOuaZ8/yDRRNsNXduIFAAyUOTKdKU+ d7asHYcKZFkVx8D2iQxORmvRtuYFg2lGG1i3YFLNrMggCJcf7HzQBO1G5DPoQjUU .... .....
The file 2010_mix.xls is now sent via email to busintel for that user to decrypt.
The command format to decrypt a file with a public key is:
gpg <options> --decrypt <filename >
The user busintel has now received the file and will now decrypt it; this is carried out using his own private key. The user busintel has decided to call the decrypted file aug_mix. He will be prompted for his own passphrase (in this example, it is called papercutter) to complete the decryption process.
User busintel would run the following command to decrypt which is in the previous encrypt example. I had encrypted the file using busintel’s public key; he can now decrypt using his own private key:
$ gpg --output aug_mis --decrypt 2010_08_mis.xls You need a passphrase to unlock the secret key for user: "busintel (business intel) <email@example.com>" 2048-bit ELG-E key, ID F96A3FD7, created 2010-08-14 (main key ID 86C597BF) Enter passphrase:papercutter gpg: encrypted with 2048-bit ELG-E key, ID F96A3FD7, created 2010-08-14 "busintel (business intel) <firstname.lastname@example.org>
The file has now been decrypted and is called aug_mix for user busintel to review.
Over a period of time your keyring will become quite populated with keys, some keys will no doubt belong to users whom are no longer present within your key exchange. To delete these keys, use the delete-key option. The command format to delete a key is:
gpg --delete-key <UID>
Before running the above command, be sure to use the list-keys option to identify correctly the key before deletion. In the following example, the public key of bravo is deleted. Notice that I first list the keys to be sure of the correct UID I am using:
$ gpg --list-keys /home/dxtans/.gnupg/pubring.gpg ------------------------------- pub 1024D/DD096620 2010-08-10 uid david tansley (aix admin) <email@example.com> sub 2048g/25B15F46 2010-08-10 pub 1024D/28B78F84 2010-08-14 uid bravo (aix user) <firstname.lastname@example.org> sub 2048g/860FAE6D 2010-08-14 .... .... $ gpg --delete-key bravo gpg (GnuPG) 1.4.7; Copyright (C) 2006 Free Software Foundation, Inc. pub 1024D/28B78F84 2010-08-14 bravo (aix user) <email@example.com> Delete this key from the keyring? (y/N) y $
Dealing with encryption or decryption within a batch environment means one thing: automation. The only human interaction that is required to encrypt or decrypt files depending on the process is entering of the passphrase. gpg offers the batch option, where the passphrase can be parsed or read into the passphrase prompt. There are a few ways this can be done. One could echo a string and pipe it through to gpg or redirect from a file or read from a file into gpg.
The command format to run in batch mode is:
gpg < options> -- batch --passphraseX <filename>
Where passphaseX is
passphrase-fd n (file descriptor and number) and
Using the batch option along with passphrase-fd. The passphrase will be read in via the local file descriptor. The following command encrypts the text file myfile and outputs it to tord3.gpg. Notice the use of the batch option along with the passphrase-fd 3. Here we open file descriptor 3 and then read into that the file descriptor the file called .passf. The contents of .passf is the single passphrase contained on one line, with no line feeds and only readable by the owner.
$ cat .passf watchmaker $ gpg --armor --output tord3.gpg --batch --symmetric --passphrase-fd 3 3<.passf myfile
Still using the passphrase-fd example, we could also echo in a string containing the passphrase into the input stream fd 0, like so:
echo watchmaker | gpg --output tord3.gpg --batch --symmetric --passphrase-fd 0 myfile
Another example that is very similar to the above uses the batch option along with the passphrase-file. Here the file .passf containing the passphrase is read in by gpg.
gpg --armor --batch --symmetric --passphrase-file .passf --output tord3.gpg myfile
As in both examples, there is no user input required which makes it ideal for batch processing large volumes of files. The passphrase file containing the passphrase to use should only contain one passphrase and should not contain a line feed at the end of the line.
Listing 4 contains a script that will check the directory /opt/hfc/holding/ for files matching the pattern ‘mis*’ to encrypt. If found, it will encrypt these using the batch passphrase-file option. The file containing the passphrase is ./home/dxtans/.gnupg/.passf. The files are encrypted with user busintel’s public key in readiness for that user to decrypt them (whom also has my public key). The files, once encrypted are created in the /opt/hfc/encrypt directory.
Listing 4. encrypt_files
#!/bin/sh # encrypt_files passf=/home/dxtans/.gnupg/.passf input_dir=/opt/hfc/holding output_dir=/opt/hfc/encrypt filelist=$(ls $input_dir/mis* 2>&1) if [ $? != 0 ] then echo "no files to process...exiting" exit 0 fi for txtfile in $filelist do filename=$(basename $txtfile) echo "attempting to encrypt..$txtfile" gpg --batch --force-mdc --output $output_dir/$filename.gpg --armor --passphrase-file $passf --symmetric --encrypt --recipient 'busintel' $txtfile if [ $? != 0 ] then echo "Failed on $txtfile to encrypt to $output_dir/$filename.gpg" else echo "OK $txtfile encrypted, new location $output_dir/$filename.gpg" # rm $txtfile fi done
When the script is run, the output is similar to the following:
$ /home/dxtans/.gnupg/encrypt_files attempting to encrypt../opt/hfc/holding/mis_341 OK /opt/hfc/holding/mis_341 encrypted, new location /opt/hfc/encrypt/mis_341.gpg attempting to encrypt../opt/hfc/holding/mis_342 OK /opt/hfc/holding/mis_342 encrypted, new location /opt/hfc/encrypt/342.gpg
Once the files have been processed, it is just a matter of decrypting them using the batch option again with the passphrase-file. For example, user busintel could decrypt the file mis_341.gpg as he has the public key of the sender. The file will be decrypted to: /opt/hfc/encrypt/mis_341
$ gpg --batch --quiet --output /opt/hfc/encrypt/mis_341 --decrypt --passphrase-file /home/bisintel/.gnupg/.passf /opt/hfc/encrypt/mis_341.gpg
There are cases where you will send text files to users, or perhaps a file you are uploading to a public area, where the file itself needs not be encrypted. But, the users need to be sure that the file has come from the actual person it says it has. One method to achieve this is to clearsign your file using your own private key. This does not encrypt your file , but rather creates another copy of the file, with the file extension of .asc. This new file contains your signature as well as the contents of the original file. You will be prompted for your passphrase when you sign the file.
To clear sign a file, the command format is:
gpg --clearsign < filename>
For example, to sign the file my popfile, I could use:
$ gpg --clearsign popfile You need a passphrase to unlock the secret key for user: "david tansley (aix admin) <firstname.lastname@example.org>" 1024-bit DSA key, ID DD096620, created 2010-08-10
The above command will produce another file called popfile.asc. The signature can be verified by other users using the verify option:
$ gpg --verify popfile.asc gpg: Signature made Sat Aug 14 16:59:03 BST 2010 using DSA key ID DD096620 gpg: Good signature from "david tansley (aix admin) <email@example.com>"
If the file has been tampered with, you will get a bad signature message, like so:
$ gpg --verify popfile.asc gpg: Signature made Sat Aug 14 16:59:03 BST 2010 using DSA key ID DD096620 gpg: BAD signature from "david tansley (aix admin) <firstname.lastname@example.org
To sign binary files, use the command:
gpg --sign <filename>
GnuPG provides a secure method of encrypting your own personal files or files you exchange between users. In this article, I have demonstrated how gpg can be used to encrypt and decrypt files, also how gpg can be used within a batch environment.