“Using GnuPG for SSH authentication” may refer to two distinct things:
In this note, I will explain how to do both.
2015/01/10 update: This page concerns GnuPG 2.0.x (“stable”). A new note is available with updated instructions for GnuPG 2.1 (“modern”).
You need to make sure that gpg-agent(1) is started with support for SSH, that it is started only once, and that any program needing the agent knows how to contact it.
To do all that, I inserted the following code in my
~/.xprofile
script, which is run at the beginning of any X
session:
if test -f $XDG_RUNTIME_DIR/gpg-agent-info && kill -0 $(head -n 1 $XDG_RUNTIME_DIR/gpg-agent-info | cut -d: -f2) 2>/dev/null ; then eval $(< $XDG_RUNTIME_DIR/gpg-agent-info) else eval $(gpg-agent --daemon --enable-ssh-support --write-env-file $XDG_RUNTIME_DIR/gpg-agent-info) fi export GPG_AGENT_INFO export SSH_AUTH_SOCK
The script first checks for a gpg-agent-info
file
revealing the presence of a running gpg-agent. If that file
exists and refers to an existing process, its contents are evaluated to
define the GPG_AGENT_INFO and SSH_AUTH_SOCK
variables; otherwise, a new instance of gpg-agent(1) is
started, and the output of the starting command is also evaluated. In
both cases, the newly defined variables are finally exported into the
environment so that client programs will be aware of the running
agent.
Of course, if you used ssh-agent(1) agent before, you must also make sure it is not started anymore, since its role will now be fullfiled by gpg-agent(1).
With the GPG agent running, you can start using it with your existing
SSH keys, exactly like you would use ssh-agent. For example, to
load your default ~/.ssh/id_rsa
key into the agent, just
run as usual:
$ ssh-add
Let’s assume you already have an OpenPGP key such as the following:
$ gpg2 --expert --edit-key 996BF6BB Secret key is available. pub 4096R/996BF6BB created: 2014-04-15 expires: 2017-04-14 usage: SC trust: ultimate validity: ultimate sub 2048R/8F603B09 created: 2014-04-15 expires: 2015-04-15 usage: E sub 2048R/B0A4401F created: 2014-04-15 expires: 2015-04-15 usage: S [ultimate] (1). Bob <bob@example.org>
This is a 4096-bit master key with a 2048-bit subkey for encryption and a 2048-bit subkey for signing. We will add a new 2048-bit subkey for authentication purposes:
gpg> addkey Key is protected. You need a passphrase to unlock the secret key for user: "Bob <bob@example.org>" 4096-bit RSA key, ID 996BF6BB, created 2014-04-15 Please select what kind of key you want: (3) DSA (sign only) (4) RSA (sign only) (5) Elgamal (encrypt only) (6) RSA (encrypt only) (7) DSA (set your own capabilities) (8) RSA (set your own capabilities) Your selection?
Select (8) RSA (set your own capabilities):
Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Sign Encrypt (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection?
Select successively (S), (E), and (A) to remove the signing and encryption capabilities and enable the authentication capability.
Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Authenticate (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection?
Once the only allowed action is Authenticate, select (Q) Finished to exit this sub-menu. The remaining of the procedure is like any other key generation:
RSA 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) 1y Key expires at Wed 15 Apr 2015 02:02:56 PM CEST Is this correct? (y/N) y Really create? (y/N) y We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. pub 4096R/996BF6BB created: 2014-04-15 expires: 2017-04-14 usage: SC trust: ultimate validity: ultimate sub 2048R/8F603B09 created: 2014-04-15 expires: 2015-04-15 usage: E sub 2048R/B0A4401F created: 2014-04-15 expires: 2015-04-15 usage: S sub 2048R/0A072B72 created: 2014-04-15 expires: 2015-04-15 usage: A [ultimate] (1). Bob <bob@example.org> gpg> save
If you plan to use an OpenPGP smartcard, you can skip this section and read the next one. Loading the authentication subkey into the GnuPG agent is done automatically when the subkey is in such a smartcard.
Install the monkeysphere package, part of the Monkeysphere project.1 This package provides the openpgp2ssh(1) tool, which will allow to convert an OpenPGP private key block into a format suitable for use with SSH.
Export the authentication private subkey and pass it through that tool:
$ gpg2 --export-secret-subkeys \ --export-options export-reset-subkey-passwd 0A072B72! | \ openpgp2ssh 0A072B72 > gpg-auth-keyfile
The exclamation mark after the key ID is to convince GnuPG to export only the specified subkey—otherwise, it will export all subkeys associated with the same master key.
Restrict the permissions on the exported key file, as ssh-add(1) will refuse to load a private key contained in a world-readable file, and import the key into the agent:
$ chmod 0600 gpg-auth-keyfile $ ssh-add gpg-auth-key-file
Verify that the key is indeed loaded:
$ ssh-add -l 2048 1c:6a:86:3e:c4:f7:7d:3d:8f:21:e0:c3:fd:89:22:99 gpg-auth-keyfile (RSA)
The gpg-auth-keyfile
is no longer needed and may be
deleted.2
Contrary to ssh-agent, gpg-agent will remember the
loaded keys between sessions, so you will not have to load your key
again, even after restarting your computer.3
Finally, extract the public key from the agent in a form suitable for
inclusion into a ~/.ssh/authorized_keys
file:
$ ssh-add -L ssh-rsa AAAAB3NzaC1yc2EAA[…truncated output…]RnxTx4Mh gpg-auth-keyfile
This last step may also be done using the (unfortunately undocumented) gpgkey2ssh tool provided by GnuPG2. It takes a single parameter which is the ID of a key in your private keyring:
$ gpgkey2ssh 0A072B72 ssh-rsa AAAAB3NzaC1yc2EAA[…truncated output…]RnxTx4Mh COMMENT
If you have an OpenPGP smartcard, you can transfer your private authentication subkey to it.
$ gpg2 --edit-key 996BF6BB Secret key is available. pub 4096R/996BF6BB created: 2014-04-15 expires: 2017-04-14 usage: SC trust: ultimate validity: ultimate sub 2048R/8F603B09 created: 2014-04-15 expires: 2015-04-15 usage: E sub 2048R/B0A4401F created: 2014-04-15 expires: 2015-04-15 usage: S sub 2048R/0A072B72 created: 2014-04-15 expires: 2015-04-15 usage: A [ultimate] (1). Bob <bob@example.org>
Switch to the list of private (sub)keys:
gpg> toggle sec 4096R/996BF6BB created: 2014-04-15 expires: 2017-04-14 ssb 2048R/8F603B09 created: 2014-04-15 expires: never ssb 2048R/B0A4401F created: 2014-04-15 expires: never ssb 2048R/0A072B72 created: 2014-04-15 expires: never (1) Bob <bob@example.org>
Select the authentication subkey…
gpg> key 3 sec 4096R/996BF6BB created: 2014-04-15 expires: 2017-04-14 ssb 2048R/8F603B09 created: 2014-04-15 expires: never ssb 2048R/B0A4401F created: 2014-04-15 expires: never ssb* 2048R/0A072B72 created: 2014-04-15 expires: never (1) Bob <bob@example.org>
and move it to the smartcard:
gpg> keytocard Signature key ....: [none] Encryption key....: [none] Authentication key: [none] Please select where to store the key: (1) Signature key (3) Authentication key Your selection? 3 You need a passphrase to unlock the secret key for user: "Bob <bob@example.org>" 2048-bit RSA key, ID 8F603B09, created 2014-04-15
Unlock your secret key and enter your smartcard Admin PIN when requested.
sec 4096R/996BF6BB created: 2014-04-15 expires: 2017-04-14 ssb 2048R/8F603B09 created: 2014-04-15 expires: never ssb 2048R/B0A4401F created: 2014-04-15 expires: never ssb* 2048R/0A072B72 created: 2014-04-15 expires: never card no: 0001 00000229 (1) Bob <bob@example.org> gpg> save
That’s it. Now the authentication subkey will automatically be loaded
into the GnuPG Agent the first time the card is read (you can verify
that by running ssh-add -l
), and when attempting to connect
to a SSH server, you will be prompted for your card PIN.
~/.gnupg/private-keys-v1.d
.