Mini GnuPG (gpg) How-to and Cookbook

GnuPG (Gnu Privacy Guard, more commonly referred to as “gpg”) is the modern version of PGP (Pretty Good Privacy). Both GPG and PGP were written by the same person, Phil Zimmerman.  More information (including the latest software for download, and documentation) are available from www.gnupg.org.

You must initialize gpg by creating the directories and files (empty keystores) it uses, before attempting to verify any files.  The first time it is run, gpg will create a ~/.gnupg directory with some files.  Next, obtain the public keys you want.  The easy way is from a keyserver (see my website for a list of keyservers).

Using gpg to verify a signed downloaded file

If some file was digitally signed, you can verify the file’s integrity with:

gpg --verify file.sig

The file and the signature for it (in file.sig) need to be present.  This operation requires the matching public key for that signature is in your gpg keystore (the database of public keys), which is often called a keyring.  If missing, gpg will tell you the KeyID it needs.

You can import someone’s public key with either of the following commands (use the first if you’ve downloaded (or received as email) a key, use the second to search an online directory/keystore):

   gpg --import keyfile
   gpg --keyserver wwwkeys.pgp.net --recv-keys KeyID

Here’s how to get the key for the Linux kernel source (assuming the key is 0x517D0F0E):

   gpg --keyserver wwwkeys.pgp.net --recv-keys 0x517D0F0E

If you don’t know the KeyID number you can search the on-line directories using email addresses or DNS domain names.  (See my home page (scroll down to the "Privacy" section) for a list of such key servers.)

GPG keys IDs are actually the last few bytes in hex of the SHA-1 message digest of the key (also known as the key fingerprint).  You can see this with “gpg -k --with-fingerprint”.

By default, the last four bytes (32 bits) of the fingerprint were used as the key ID, also called the short keyid.  This has become a problem since people have since reversed SHA-1 message digests to generate different GPG keys that have the same short key ID, for any key!  Thus it is easy to get someone to import a fake key.

One solution is to make gpg display a “long” key ID of 8 bytes (the last 64 bits of the fingerprint) instead.  You can also make gpg display the entire fingerprint.  To do this, add the following to your ~/.gnupg/gpg.conf file:

keyid-format long
 	with-fingerprint

(Or you can use “--keyid-format long” command line option.)

For safety, you should only use long format key IDs with GPG.

RPM and YUM can use digital signatures to verify packages before installing, but again you will need to import the public keys for those repositories (and not onto your personal keyring either).

To obtain the signature for the kernel source code, using your web browser to go to: www.kernel.org/signature.html.  Scroll down until you see "The current Linux Kernel Archives OpenPGP key is:".  Copy what follows starting from the "pub 1024D..." line up to and including the line:

    -----END PGP PUBLIC KEY BLOCK-----

into a file, say "~/kernel.pubkey".  Then add this key to your GPG database with:

   gpg --import kernel.pubkey

Now you can verify the signature for any file signed with the matching private key.  Download both the file and the signature file, then verify like this:

   wget ftp://ftp.kernel.org/pub/linux/kernel/v2.4/linux-2.4.19.tar.gz
   wget ftp://ftp.kernel.org/pub/linux/kernel/v2.4/linux-2.4.19.tar.gz.sign
   gpg --verify linux-2.4.19.tar.gz.sign linux-2.4.19.tar.gz

Demo using chkrootkit

Visit www.chkrootkit.org, download tar-ball, .md5, and .sig files using wget. Next verify the tar-ball:

  md5sum --check chkrootkit.md5
  gpg chkrootkit.tar.gz.sig  # Note key name
  gpg --keyserver hkp://pgp.mit.edu --recv-keys A0E92110
  gpg chkrootkit.tar.gz.sig

Now build the script:

  tar -zxvf chkrootkit.tar.gz
  cd chkrootkit-version
  less README
  make sense

And finally run it:  su -c "./chkrootkit"

The Issue of Trust

Receiving a key is dangerous since you don’t really know if that is the key of the person or organization you think it is.  With gpg each person's public keys are digitally signed by others.  If you trust any of the others who signed the key, you can have confidence that the key really belongs to the person who claims it is theirs.

gpg will tell you when you verify a signature that the signature is good (or bad), and who it belongs to, and then it will tell you how much to trust that information.  If the key was signed by someone you trust fully, or signed by three people you trust a little, then you can have high confidence the key belongs to the person who claims it is theirs.  Gpg will require you to decide how much you trust a key you are importing.

Suppose you import key "A" from user "Al", and trust that this is really Al's key.  Furthermore, you know Al personally and know that if Al vouches for someone's key, it is very likely to be that person's key. Then tomorrow you need to verify a file signed by user "Bob" with key "B".  If key "B" was signed with Al's key, you can trust that key "B" really belongs to Bob.

Using GnuPG

Generate a new pair of keys using:

   gpg --full-generate-key
   gpg --gen-key

The second form won't ask you for as much information and will use defaults.  Use the first form to control everything.  (Don't worry, defaults are still suggested.)

Use RSA and RSA (the default) as the encryption type (as of 2020).  Use key size of 1024 or bigger, the default is 2048.  (Bigger than this doesn’t improve security much.)

Always use an expiration date!  For your first key use a short period, a couple of months.  For a “production” key use something like 1–10 years (1-3 years is common).

Next enter your full name, your email address (associated with this key) and a comment (may be blank, or may be a title, a nickname, etc.).  Those with multiple keys generally use the comment to describe the purpose of the key, such as “Package Signer”.

Next you enter a password (since blanks are allowed it is called a passphrase).  The private key is stored in a file on your computer.  If you don’t encrypt this file with a password, then it is easier for someone (or virus) to steal your private key!  Note if you have multiple private keys then each will have it’s own password.

While it is possible to not enter a password (thus making use of the key easier later), this is not recommended.  Instead you should use agent software.

The idea of agent software is that at login time, this loads up with all your private keys and keeps them in memory (and decrypted).  All future uses of encryption will ask the agent, and not interactively ask you, for the private key.  This means you don’t have to enter passwords every time, yet your secret keys are still password protected!  The agent stores keys only in RAM and never on the disk, and you only need to enter the keys' passwords once.

gpg-agent can manage keys for a number of utilities including OpenSSH.  However OpenSSH does come with ssh-agent, which works similarly but for SSH keys only.

The commands for listing and exporting keys are:

   gpg --list-keys
   gpg --list-secret-keys
   gpg --export [KeyID]

Here’s some sample output with different keyID formats:

$ gpg --list-keys # default: no keyid shown
/home/wpollock/.gnupg/pubring.kbx
---------------------------------
pub   dsa1024 2005-06-30 [SC] [expires: 2035-03-18]
      1181217F1F0B196CD8A16F490A8DF400779190A0
uid           [ unknown] Wayne Pollock <pollock@acm.org>
sub   elg2048 2005-06-30 [E] [expires: 2035-03-18]
$ gpg --list-keys --keyid-format short
/home/wpollock/.gnupg/pubring.kbx
---------------------------------
pub  dsa1024/779190A0 2005-06-30 [SC] [expires: 2035-03-18]
      1181217F1F0B196CD8A16F490A8DF400779190A0
uid         [ unknown] Wayne Pollock <pollock@acm.org>
sub   elg2048/40E29FAA 2005-06-30 [E] [expires: 2035-03-18]
$ gpg --list-keys --keyid-format long
/home/wpollock/.gnupg/pubring.kbx
---------------------------------
pub   dsa1024/0A8DF400779190A0 2005-06-30 [SC] [expires: 2035-03-18]
      1181217F1F0B196CD8A16F490A8DF400779190A0
uid             [ unknown] Wayne Pollock <pollock@acm.org>
sub  elg2048/DA6BE7D140E29FAA 2005-06-30 [E] [expires: 2035-03-18]

You can upload your key to a keyserver with:

	gpg --keyserver wwwkeys.pgp.net --send-keys KeyID

You can edit keys, including the level of trust you have that this key really belongs to this user id, and also sign keys (proclaiming to the world that you certify this key as belonging to this user id) with:

   gpg --edit-key KeyID

This brings up an interactive mode, enter “help” to see a list of commands.  For example use the command "trust" to change the level of trust you have in a key. 

To encrypt some file for a user, you need their public key:

gpg -a --encrypt -r KeyID < file > file.gpg

The “-a” says to use ASCII output format. Without the "-r KeyID" argument, you will be asked to select a key to use.

To decrypt something that was sent to you, you need to use your private key:

   gpg --decrypt file  # will ask for your passphrase

To sign a file with your private key, use:

   gpg -a --output file.signed --sign file

This command encrypts file with your private key and saves the result as file.asc by default.  (The "-a" option says to create ASCII output format.)

This isn't very useful, as you must decrypt the file to see the original document.  A more useful way of signing the document is to just sign a message digest, and append that to the file.  This is commonly done for email and similar text files.  To sign the document while keeping the original unencrypted, use:

   gpg -a --output file.signed --clearsign file

For files you plan to make available on the Internet it is usually most convenient to put the signature (the message digest encrypted with your private key) in a separate file, usually with the extension ".sig".  This is done as follows:

   gpg -a --output file.sig --detach-sig file

To verify a signed file use:

   gpg --verify file.signed

To verify a file signed using a detached signature, you need both the file and the signature file:

   gpg --verify file.sig
   echo 'opps' >> file
   gpg --verify file.sig