Blog

Using GnuPG (2.1) for SSH authentication

Last year I explained how to use GnuPG for SSH authentication. Since then, GnuPG 2.1 “modern” was released, introducing some important changes. In particular, SSH authentication is now much easier, which prompted me to write this new note.

Using GnuPG Agent as a SSH agent

Enable SSH support in GnuPG Agent by adding the corresponding option in the agent configuration file, ~/.gnupg/gpg-agent.conf:

enable-ssh-support

While GnuPG programs can start the GnuPG Agent on demand, starting explicitly the agent is necessary to ensure that the agent is running when a SSH client needs it. The two lines below, to be inserted into a ~/.xprofile script, are sufficient:1

gpg-connect-agent /bye
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)

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

Using an OpenPGP key as a SSH key

Create an authentication subkey

Let’s assume you already have an OpenPGP key such as the following (note the --expert flag, which will enable advanced key generation options):

$ gpg2 --expert --edit-key alice
Secret key is available.

pub  rsa4096/CB2F38F25B491A54
     created: 2014-12-31  expires: 2017-12-30  usage: SC
     trust: ultimate      validity: ultimate
sub  rsa2048/04BB7F8FDEC5E5D9
     created: 2014-12-31  expires: 2015-12-31  usage: S
sub  rsa2048/BBB6B86627C2D43A
     created: 2014-12-31  expires: 2015-12-31  usage: E
[ultimate] (1). Alice <alice@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
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)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
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 Thu 31 Dec 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  rsa4096/CB2F38F25B491A54
     created: 2014-12-31  expires: 2017-12-30  usage: SC
     trust: ultimate      validity: ultimate
sub  rsa2048/04BB7F8FDEC5E5D9
     created: 2014-12-31  expires: 2015-12-31  usage: S
sub  rsa2048/BBB6B86627C2D43A
     created: 2014-12-31  expires: 2015-12-31  usage: E
sub  rsa2048/7D2233B8833E70AF
     created: 2014-12-31  expires: 2015-12-31  usage: A
[ultimate] (1). Alice <alice@example.org>

gpg> save

Using the authentication subkey

To tell the agent that the authentication subkey can be used with SSH, extract the keygrip of that subkey:

$ gpg2 --with-keygrip -k alice
pub   rsa4096/CB2F38F25B491A54 2014-12-31 [SC] [expires: 2017-12-30]
      Keygrip = D4DF0C35D3E22FA6AC37DA2E54FB03F73616A3CB
uid               [ultimate] Alice <alice@example.org>
sub   rsa2048/04BB7F8FDEC5E5D9 2014-12-31 [S] [expires: 2015-12-31]
      Keygrip = 21B2EDF018D7CAF0B45644FDB753DD42307C4425
sub   rsa2048/BBB6B86627C2D43A 2014-12-31 [E] [expires: 2015-12-31]
      Keygrip = 2E149DA9C5E46E0DECC6A17EFD8B5FB1DF1E1BAB
sub   rsa2048/7D2233B8833E70AF 2014-12-31 [A] [expires: 2015-12-31]
      Keygrip = ECF4591CC28EC303BB12D1E866C8B8AFFB675C7D

and write it into the ~/.gnupg/sshcontrol file:

# List of allowed ssh keys.  Only keys present in this file are used
# in the SSH protocol.  The ssh-add tool may add new entries to this
[…]
ECF4591CC28EC303BB12D1E866C8B8AFFB675C7D

You may then verify that the key is indeed available for SSH by querying the agent for available identities:

$ ssh-add -l
2048 e3:40:d5:eb:ef:b1:3a:37:87:3d:a8:44:1d:81:ed:6a (none) (RSA)

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…]KhJHfdIcCMRF (none)

If you want to authenticate with an OpenPGP smartcard, you may refer to my previous note for GnuPG “stable” 2.0.x. The section about the OpenPGP smartcard is still valid for GnuPG “modern” 2.1.

  1. The --list-dirs agent-ssh-socket option was added to gpgconf in GnuPG 2.1.14, to cope with the fact that, starting from GnuPG 2.1.13, the GnuPG Agent may store its sockets elsewhere than in GnuPG’s home directory.