Displaying GPG public keys in ASCII format

I was debugging a gpg issue earlier this week, and needed to dump the contents of a public key in some type of human readable form. After a bit of googling I came across the crazy awesome pgpdump utility, which provides a command line interface to display the contents of a GPG public key. To use this tool, you can pass the key file as an argument to pgpdump:

$ gpg –export -a > $HOME/pub.asc

$ pgpdump $HOME/pub.asc

Old: Public Key Packet(tag 6)(418 bytes)
	Ver 4 - new
	Public key creation time - Tue Jun 22 10:33:25 EDT 2010
	Pub alg - DSA Digital Signature Algorithm(pub 17)
	DSA p(1024 bits) - ...
	DSA q(160 bits) - ...
	DSA g(1021 bits) - ...
	DSA y(1023 bits) - ...
Old: User ID Packet(tag 13)(31 bytes)
	User ID - Test Key 
Old: Signature Packet(tag 2)(96 bytes)
	Ver 4 - new
	Sig type - Positive certification of a User ID and Public Key packet(0x13).
	Pub alg - DSA Digital Signature Algorithm(pub 17)
	Hash alg - SHA1(hash 2)
	Hashed Sub: signature creation time(sub 2)(4 bytes)
		Time - Tue Jun 22 10:33:25 EDT 2010
	Hashed Sub: key flags(sub 27)(1 bytes)
		Flag - This key may be used to certify other keys
		Flag - This key may be used to sign data
	Hashed Sub: preferred symmetric algorithms(sub 11)(5 bytes)
		Sym alg - AES with 256-bit key(sym 9)
		Sym alg - AES with 192-bit key(sym 8)
		Sym alg - AES with 128-bit key(sym 7)
		Sym alg - CAST5(sym 3)
		Sym alg - Triple-DES(sym 2)
	Hashed Sub: preferred hash algorithms(sub 21)(3 bytes)
		Hash alg - SHA1(hash 2)
		Hash alg - SHA256(hash 8)
		Hash alg - RIPEMD160(hash 3)
	Hashed Sub: preferred compression algorithms(sub 22)(3 bytes)
		Comp alg - ZLIB (comp 2)
		Comp alg - BZip2(comp 3)
		Comp alg - ZIP (comp 1)
	Hashed Sub: features(sub 30)(1 bytes)
		Flag - Modification detection (packets 18 and 19)
	Hashed Sub: key server preferences(sub 23)(1 bytes)
		Flag - No-modify
	Sub: issuer key ID(sub 16)(8 bytes)
		Key ID - 0xA7B71783E5016F25
	Hash left 2 bytes - ad 6b 
	DSA r(157 bits) - ...
	DSA s(159 bits) - ...
		-> hash(DSA q bits)
Old: Public Subkey Packet(tag 14)(525 bytes)
	Ver 4 - new
	Public key creation time - Tue Jun 22 10:33:25 EDT 2010
	Pub alg - ElGamal Encrypt-Only(pub 16)
	ElGamal p(2048 bits) - ...
	ElGamal g(3 bits) - ...
	ElGamal y(2046 bits) - ...
Old: Signature Packet(tag 2)(73 bytes)
	Ver 4 - new
	Sig type - Subkey Binding Signature(0x18).
	Pub alg - DSA Digital Signature Algorithm(pub 17)
	Hash alg - SHA1(hash 2)
	Hashed Sub: signature creation time(sub 2)(4 bytes)
		Time - Tue Jun 22 10:33:25 EDT 2010
	Hashed Sub: key flags(sub 27)(1 bytes)
		Flag - This key may be used to encrypt communications
		Flag - This key may be used to encrypt storage
	Sub: issuer key ID(sub 16)(8 bytes)
		Key ID - 0xA7B71783E5016F25
	Hash left 2 bytes - b1 38 
	DSA r(158 bits) - ...
	DSA s(159 bits) - ...
		-> hash(DSA q bits)

Pgpdump will display the algorithms used to create the key, as well as the key-lengths that were used. This is amazingly helpful when debugging key-related issues (hash algorithm mismatches, key-size discrepancies, etc.), and I will definitely be adding this tool to my SysAdmin toolkit!

Verifying GPG signatures

One of my friends recently asked me how to verify a signature that is distributed with an opensource application. Since I didn’t have a machine handy to show him, I thought I would jot this down for him in my blog. The first step in verifying a signature requires locating the public key of the individual who signed the binary. Once you locate the key and validate it’s authenticity, you can use the gpg “–import” option to import the key. Once the key is imported, you can use the gpg “–verify” option to verify that the signature is legit:

$ gpg –verify postfix-2.3.2.tar.gz.sig postfix-2.3.2.tar.gz

gpg: WARNING: using insecure memory!
gpg: please see http://www.gnupg.org/faq.html for more information
gpg: Signature made Thu Jul 27 12:49:07 2006 EDT using RSA key ID C12BCD99
gpg: Good signature from "Wietse Venema "
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: FF 96 4A 8C 96 88 7C 6E  A4 EF AD BF 48 34 E1 BB

In the above example, I used Wietse Venema’s public key (which I had previously imported) to verify the signature stored in the file postfix-2.3.2.tar.gz.sig against the source code I downloaded. Gpg is a swell piece of software!

Verifying digital signatures

I recently downloaded the samhain file integrity verification suite, and wanted to verify the authenticity of the package. The samhain developers distribute samhain as tar archive, which includes the source code and a detached ASCII signature file:

$ /usr/sfw/bin/gtar tvfz samhain-current.tar.gz

-rw-r--r-- 1000/100    1302539 2005-09-22 16:05:35 samhain-2.0.10a.tar.gz
-rw-r--r-- 1000/100        189 2005-09-22 16:06:29 samhain-2.0.10a.tar.gz.asc

To verify the source code that is contained in the file samhain-2.0.10a.tar.gz using the detached ASCII signature stored in the file samhain-2.0.10a.tar.gz.asc, I downloaded the samhain developers public key, and imported it into my keychain with the gpg “–import” option:

$ gpg –import sh.pub

gpg: key 0F571F6C: public key "Rainer Wichmann " imported
gpg: Total number processed: 1
gpg:               imported: 1

Once the public key was imported, I used gpg’s “–fingerprint” option to extract a digital fingerprint from each public key:

$ gpg –fingerprint

/home/matty/.gnupg/pubring.gpg
------------------------------
pub  1024D/0F571F6C 1999-10-31 Rainer Wichmann 
     Key fingerprint = EF6C EF54 701A 0AFD B86A  F4C3 1AAD 26C8 0F57 1F6C
uid                            Rainer Wichmann 
sub  1024g/9DACAC30 1999-10-31

Once I had the fingerprint and the keyid, I verified both pieces of information with a trusted source. After I verified the authenticity of the key I imported, I used gpg’s “–verify” option along with the signature file (an encrypted hash) to verify the files contents with the key I just imported:

$ gpg –verify samhain-2.0.10a.tar.gz.asc samhain-2.0.10a.tar.gz

gpg: Signature made Thu 22 Sep 2005 04:06:29 PM EDT using DSA key ID 0F571F6C
gpg: Good signature from "Rainer Wichmann "
gpg:                 aka "Rainer Wichmann "
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: EF6C EF54 701A 0AFD B86A  F4C3 1AAD 26C8 0F57 1F6C

Verifying signatures can help ensure that the source code you download hasn’t been replaced with a malicious variant. The gpg(1) manual contains lots of information on signatures, and provides a detailed breakdown of the available gpg options.

Encrypting data with GNU Privacy Guard

The GNU privacy guard provides a command line tool (gpg) to encrypt data and manage digital signatures. GPG supports the OpenPGP standard, and provides easy access to a variety of key distribution servers. To view the full list of options available to gpg, you can run gpg with the “-h” option:

$ gpg -h | head -20

gpg (GnuPG) 1.2.4
Copyright (C) 2003 Free Software Foundation, Inc.
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions. See the file COPYING for details.

Home: ~/.gnupg
Supported algorithms:
Pubkey: RSA, RSA-E, RSA-S, ELG-E, DSA, ELG
Cipher: 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH
Hash: MD5, SHA1, RIPEMD160, SHA256
Compression: Uncompressed, ZIP, ZLIB, BZIP2

Syntax: gpg [options] [files]
sign, check, encrypt or decrypt
default operation depends on the input data

[ ... ]

To use the gpg utility to encrypt a text file, we can invoke gpg with the “-c” option:

$ gpg -c –cipher-algo AES256 services

$ ls -l service*
-rw-r–r– 1 matty matty 572576 11 Feb 12:50 services
-rw-r–r– 1 matty matty 168375 11 Feb 12:50 services.gpg

The “-c” option instructs gpg to encrypt the file with a symmetric key algorithm. The “–cipher-algo” option picks the algorithm to use, and the file to encrypt is passed to gpg as an argument. The full list of algorithms is included in the header of the help screen.

To decrypt a file encrypted with gpg, we can use the “-d” option:

$ gpg –output services -d services.gpg

gpg: AES256 encrypted data
gpg: encrypted with 1 passphrase

The “–output” option is passed to gpg to control where the decrypted file contents are written. By default, gpg will print the decrypted contents to standard out. For sensitive or binary data, this is probably not what you want.