Skip to content

Instantly share code, notes, and snippets.

@dmitrodem
Last active April 8, 2022 15:08
Show Gist options
  • Save dmitrodem/0082b6fa6c6aec47108ff246aa0244d2 to your computer and use it in GitHub Desktop.
Save dmitrodem/0082b6fa6c6aec47108ff246aa0244d2 to your computer and use it in GitHub Desktop.

Import an existing SSH key

To add the key, you need to convert the key format from the Privacy-Enhanced Mail (PEM)-encoded format that SSH uses to an OpenPGP-formatted certificate. The Monkeysphere Project provides a utility, pem2openpgp, that does this for you.

Unfortunately, making this newly added key a subkey is not a one-step process. This longer process is required because there is no clean way to delete the GPG key in the keyring that is just the SSH key. The keys are identified and operated on by keygrip, and the keygrip for a key is the same whether it is a subkey or a standalone key. Thankfully, you only need to work with the private keys, as you can regenerate the public keys at the end.

Also, if you have a newer style OpenSSH key, you'll have a couple of extra steps to convert that into something pem2openpgp can read. Unfortunately, as of version 0.41, Monkeysphere cannot read newer style OpenSSH keys. (Your key is a newer style key if the first line of the private key file is: -----BEGIN OPENSSH PRIVATE KEY-----. If your key starts with: -----BEGIN RSA PRIVATE KEY-----, then you have the PEM-encoded format.)

To import newer keys, you need to convert them into old-style formats. This is done by using ssh-keygen and taking advantage of its ability to write in multiple key formats. You can trigger the conversion by changing the password on the key. You don't have to change the password in this situation, so feel free to reuse your existing one if you prefer.

The workflow below walks us through these steps.

  1. If you have a newer style OpenSSH key, convert it using the ssh-keygen utility. You can use this utility to change the password (if you want) and force the key to be rewritten in the older format. The only difference between a typical use of ssh-keygen and this one is the addition of -m to change the format of the key.
    $ ssh-keygen -p -m PEM -f <private-key-file>
  1. Back up your existing GPG key.
$ gpg2 -a --export-secret-keys 96F33EA7F4E0F7051D75FC208715AF32191DB135 > my_gpg_key.asc
  1. In a new keyring, import your existing GPG key.
    $ mkdir temp_gpg
    $ chmod go-rwx temp_gpg/
    $ gpg2 --homedir temp_gpg --import my_gpg_key.asc
    gpg: key 8715AF32191DB135: public key "Brian Exelbierd" imported
    gpg: key 8715AF32191DB135: secret key imported
  1. Optionally, verify the import
    $ gpg2 -K --homedir temp_gpg/
    /home/bexelbie/temp_gpg/pubring.kbx
    --------------------------------
    sec   rsa2048 2019-03-21 [SC] [expires: 2021-03-20]
          96F33EA7F4E0F7051D75FC208715AF32191DB135
    uid           [ unknown] Brian Exelbierd
    ssb   rsa2048 2019-03-21 [E] [expires: 2021-03-20]
    ssb   rsa2048 2019-03-21 [A]
  1. Import the SSH key as a new standalone GPG key.
    # get the software
    $ dnf install -y monkeysphere

    # temporary_id is a temporary identifier required by GPG
    $ pem2openpgp temporary_id < .ssh/my_fancy_key  | gpg2 --import --homedir temp_gpg/
    Enter PEM pass phrase:
    gpg: key 66091F2C70AF02A9: public key "temporary_id" imported
    gpg: key 66091F2C70AF02A9: secret key imported
    gpg: Total number processed: 1
    gpg:               imported: 1
    gpg:       secret keys read: 1
    gpg:   secret keys imported: 1

    # verify the key loaded and get the keygrip of the new GPG key and the hash of your GPG key
    $ gpg2 -K --with-keygrip  --homedir temp_gpg/
    /home/bexelbie/temp_gpg/pubring.kbx
    --------------------------------
    sec   rsa2048 2019-03-21 [SC] [expires: 2021-03-20]
          96F33EA7F4E0F7051D75FC208715AF32191DB135
          Keygrip = 90E08830BC1AAD225E657AD4FBE638B3D8E50C9E
    uid           [ unknown] Brian Exelbierd
    ssb   rsa2048 2019-03-21 [E] [expires: 2021-03-20]
          Keygrip = 5FA04ABEBFBC5089E50EDEB43198B4895BCA2136
    ssb   rsa2048 2019-03-21 [A]
          Keygrip = 7710BA0643CC022B92544181FF2EAC2A290CDC0E

    sec   rsa2048 2019-03-23 [C]
          D4F6B35B52B96A092FB8F418A41A06197749FBA4
          Keygrip = 1F824257B107D9E3371B9A4957751D78FC8BB190
    uid           [ unknown] temporary_id

    # We can remove monkeysphere unless you need it for other reasons
    $ dnf remove -y monkeysphere
  1. Add the SSH key as a subkey of your GPG key.
    $ gpg2 --homedir temp_gpg  --expert --edit-key 96F33EA7F4E0F7051D75FC208715AF32191DB135
    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? 13
    Enter the keygrip: 1F824257B107D9E3371B9A4957751D78FC8BB190

    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? s
    Your selection? e
    Your selection? a

    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? q
    Please specify how long the key should be valid.
    Key is valid for? (0)
    Key does not expire at all
    Is this correct? (y/N) y
    Really create? (y/N) y

    sec  rsa2048/8715AF32191DB135
         created: 2019-03-21  expires: 2021-03-20  usage: SC  
         trust: unknown       validity: unknown
    ssb  rsa2048/150F16909B9AA603
         created: 2019-03-21  expires: 2021-03-20  usage: E  
    ssb  rsa2048/17E7403F18CB1123
         created: 2019-03-21  expires: never       usage: A  
    ssb  rsa2048/4A9EE7790817C411
         created: 2019-03-23  expires: never       usage: A  
    [ unknown] (1). Brian Exelbierd

    gpg> quit
    Save changes? (y/N) y

Notice there are now two authentication subkeys.

  1. Export your existing GPG key with the new subkey.
    $ gpg2 --homedir temp_gpg -a --export-secret-keys 96F33EA7F4E0F7051D75FC208715AF32191DB135 > my_new_gpg_key.asc
  1. Import your existing GPG key with the new subkey into your customary keyring (only the subkey will import).
    $ gpg2 --import my_new_gpg_key.asc
    gpg: key 8715AF32191DB135: "Brian Exelbierd" 1 new signature
    gpg: key 8715AF32191DB135: "Brian Exelbierd" 1 new subkey
    gpg: key 8715AF32191DB135: secret key imported
    gpg: Total number processed: 1
    gpg:            new subkeys: 1
    gpg:         new signatures: 1
    gpg:       secret keys read: 1
    gpg:   secret keys imported: 1
    gpg:  secret keys unchanged: 1

    # verify the input and get the keygrip (it should be the same)
    $ gpg2 -K --with-keygrip
    /home/bexelbie/.gnupg/pubring.kbx
    ------------------------------
    sec   rsa2048 2019-03-21 [SC] [expires: 2021-03-20]
          96F33EA7F4E0F7051D75FC208715AF32191DB135
          Keygrip = 90E08830BC1AAD225E657AD4FBE638B3D8E50C9E
    uid           [ultimate] Brian Exelbierd
    ssb   rsa2048 2019-03-21 [E] [expires: 2021-03-20]
          Keygrip = 5FA04ABEBFBC5089E50EDEB43198B4895BCA2136
    ssb   rsa2048 2019-03-21 [A]
          Keygrip = 7710BA0643CC022B92544181FF2EAC2A290CDC0E
    ssb   rsa2048 2019-03-23 [A]
          Keygrip = 1F824257B107D9E3371B9A4957751D78FC8BB190

Optionally, you may want to pre-specify that this key is to be used for SSH. This means you will not have to use ssh-add to load the key. To do this, specify the keys in the ~/.gnupg/sshcontrol file. The entries in this file are keygrips.

    ~/.gnupg/sshcontrol file.  The entries in this file are key grips

    # Add the new keygrip to your sshcontrol file
    $ echo 1F824257B107D9E3371B9A4957751D78FC8BB190 >> ~/.gnupg/sshcontrol

Success!

You can now delete the old SSH private key file. When you attempt to SSH into the appropriate servers, you will be prompted to unlock your GPG key (it better have a password!), then gpg-agent will provide the authentication in place of ssh-agent. You have fewer files to keep securely backed up and your key management is a bit easier. If you ever need a new key, you can follow the directions in the previous article to create more authentication subkeys. If the project you're working on ends, you can always delete any extra subkeys you wind up with.

In the third and final article, I will share some tips for managing multiple authentication subkeys/SSH keys. Once you have more than two or three, it gets a bit more complicated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment