Why bother?

The traditional method of verifying the identity of a host with ssh is to use an ssh host key. In theory, you can get a copy of the host key from your system administrator via some secure method, such as in-person communications or perhaps via cryptographically signed email, before the first time you log into a host. In practice, it is often tempting to log into a host before the system administrator gets around to providing you a copy of the host key via a secure means.

I've found that it's extremely rare for sysadmins to bother to provide host keys; for example, I've mentioned on one group's mailing list that mailing out ssh style host keys or fingerprints in GPG signed email would be a good idea, yet I've only ever seen the fingerprint for one of the hosts mailed out in that way.

I've also seen system administrators be fairly casual about changing host keys; this can lead to users developing an instinct that the right thing to do when they see ssh's man in the middle attack warning is to delete the relevant line of their ~/.ssh/known_hosts file, and try again, which sort of defeats the point of the known_hosts mechanism.

Kerberos provides another option for verifying host keys, and it seems to work reasonably well. However, among other issues, many sites do not have Kerberos infrastructure deployed. For some, X.509 may also offer a convenient method to verify host keys. It's possible that X.509 certificate support for openssh may exist someday. However, many people find the cost and hassle of getting an X.509 certificate signed by a known certifying authority to be prohibitive, and having each organization or individual run their own CA seems to have issues with distributing the root certificates which are very similar to the issues with distributing ssh style host keys.

The theory here is that lots of people are using the OpenPGP standard to encrypt their email, and that it will be natural for them to also use it for managing host keys. Also, making the exchange of fingerprints useful for verifying ssh host keys might cause some to start encrypting their email.

Changes from 0.8.1 to 0.9

Changes from 0.8 to 0.8.1

Changes from 0.7 to 0.8

Downloading and Compilation

If you want to use sxw's gssapi patches, get a virgin openssh tree, apply sxw's patches, and then use openssh-gpg-0.9-3.6.1p2-gssapi.patch after verifying the detatched signature openssh-gpg-0.9-3.6.1p2-gssapi.patch.asc

Otherwise, use openssh-gpg-0.9-3.6.1p2.patch after verifying the detached signature openssh-gpg-0.9-3.6.1p2.patch.asc

(There are also old versions that you don't want to use.)

After you apply the patch, you will need to run autoconf of a version sufficiently close to the version used by the openssh developers. If you're using the GSSAPI version, you'll also need to get regenerated.

Because this version invokes gpg directly and doesn't depend on any libraries to be able to use gpg, you can compile openssh with gpg support without having to install any special software first, other than this patch. Indeed, gpg itself does not need to be installed at the time you compile openssh.

There is a --with-gpg option to the configure script, but it is enabled by default, so you normally won't need to do anything special there.

Server configuration

On the server side, you need to generate and sign a host key. gpg --gen-key should work; if the server's name is, and if that machine is also known as, you will want to give it an email address of, and then add another uid with the email address (You need to make a uid for each fully qualified hostname that ssh client users want to be able to use.) You'll need to supply a full name value of some sort, since otherwise gpg will refuse to generate the key, but it matters little what you put in that full name field, as the current version of the openssh client software ignores it. You need to generate this key without a passphrase, so that the sshd will be able to use it to sign things.

After you generate the key, you will probably want to sign it with at least one real person's primary signing key; make sure you sign all the uids. You should make sure that the copy of the keyring that the sshd will be using has all the sigs on it, since the sshd exports the key and sends it along to the client as part of the ssh protocol.

You'll need to put lines like the following in the config file for sshd, to specify which key to use, where to find the GPG binary, and what value of the HOME environment variable should be passed to GPG:

GPGAbsoluteFilename /usr/local/bin/gpg
GPGHomedir /root

You should either use DSAPGPKeyName or RSAPGPKeyName, depending on which key type you told GnuPG you wanted when you generated the key. This implementation will issue a fatal error if the ssh layer has been incorrectly told about which encryption algorithm your key uses, since allowing that to work would appear to be a violation of the relevant RFCs.

Client configuration

The client will only use gpg if you explicitly tell it where to find gpg. You want to put a line like this in its config file (for which the per user config file is normally ~/.ssh/config, but you may want to put this in the systemwide config file instead):

gpgabsolutefilename = /usr/local/bin/gpg

Once you do that, the client will use OpenPGP host keys in preference to traditional ssh host keys where the server offers an OpenPGP host key.

It is possible to specify what home directory to use with the gpghomedir option, as in the following example; if you omit this, then the value of the HOME environment variable is used.

gpghomedir = /home/nemo

It is also possible to use a GPG key to authenticate yourself to the server. To do this, you need to use an RSAPGPKeyName or DSAPGPKeyName option in your client config file, like this:

DSAPGPKeyName 87C36E60187451050A4F26B134824FC95C781A18

Then, in the authorized_keys file on the server, use something like this:

pgp-sign-dss 87C36E60187451050A4F26B134824FC95C781A18 foo

Where 87C36E60187451050A4F26B134824FC95C781A18 is the key fingerprint, and foo is an optional comment. As the comment can be omitted, you could also write:

pgp-sign-dss 87C36E60187451050A4F26B134824FC95C781A18

Minor issues

While this version will make sure that the signature is made by the same key that it gets in the import step, and fail otherwise, it does potentially add keys to your keyring every time you run the ssh client. You should be aware that should you hit a man in the middle, arbitrary keys can get added to your keyring. It's not clear, though, that this is actually a problem.

It's not clear that it's desirable to require the user to explicitly specify the path to gpg.

If the host you are connecting to is in the same domain as the machine you are connecting from, the tcp layer can cope with an unqualified hostname. However, the current version of the uid checking code doesn't know how to determine which domain you're using, so it will fail to allow any connections to unqualified hostnames. The search directive allowed in resolv.conf makes it unclear that there is a good, secure solution to this problem.

Status of this code

While I'm not aware of security bugs in this code, having a couple of other knowledgeable people look this over for security bugs would be very helpful.

Also, the implementation claims that it supports PGP user keys. Testing should be done to verify that this code interoperates with the implementation.