Migrate to ECC Encryption Keys

With COVID-extra spring cleaning time, a PSA post on updating your security keys. We’re going to move your ssh and gpg keys from RSA algos to the more compact, efficient ECC (Elliptical Curve Cryptography) keys of ED59515. This is how you create them and how to swap them out on services and tools you use.

Most security experts now say to switch from RSA keys to using curves derived from the mathematical properties of elliptical curves, ECC (Elliptical Curve Cryptography). Increasing computing power, has made RSA style keys below 4096 bits vulnerable as well as their now being purpose-made tools around cracking passwords on those secret keys (there are countermeasures).

The software to do the switch is on every osx and linux machine (and even windows if you’ve installed GPG or PGP). It’s not difficult, it substantially increases your security, and it’s good housekeeping hygiene.

The Setup

To make sure you’re not getting yourself into trouble (since there is a slim possibility you can lock yourself out of something permanently, by encrypting something and not being able to decrypt it), please make sure you’re comfortable with public key encryption concepts and:

  1. Have a modern linux-based or OSX system
  2. gpg and ssh are installed
  3. Comfy in terminal and on the command line

We’ll go over the following use cases after replacing your keys:

  1. Changing your github/gitlab ssh keys
  2. Re-encrypting your password store
  3. Updating keybase.io to publicly verify your keys

Checking Your Existing Keys

Let’s take a look at your existing ssh keys. Technically if your RSA keys are long enough you don’t necessarily have to switch them though I’d advise it’s a good idea. Get to the command line and put in the following if you are using zsh or bash:

$ for key in ~/.ssh/id_*; do ssh-keygen -l -f "${key}"; done | uniq

This will yield something along the lines of the following (actual example from when I did this back at start of year):

# good stuff removed
2048 SHA256:VyoWzd53SerDqHKJqFCnAGIKpcn3Vm9ew9SAyS91Nvs no comment (RSA)
2048 SHA256:VyoWzd53SerDqHKJqFCnAGIKpcn3Vm9ew9SAyS91Nvs daryl@atticus.local (RSA)

The first thing you’ll notice here is that the RSA keys here are vulnerable at 2048 (the standard when generated. Swap them out.

$ gpg --list-secret-keys

My gpg keys were in better shape though there were one or two that needed replacing:

# good stuff removed
sec   rsa2048 2015-08-07 [SC] [expires: 2021-03-25]
uid           [ultimate] FirstName LastName <name@example.com>
ssb   rsa2048 2015-08-07 [E] [expires: 2021-03-25]

If you are unfamiliar with the various algorithms that are used, and your key does not read rsaxxxx or RSA in either of the above, you can take a look at the various key types here:

Key type Need to know
DSA Unsafe and no longer supported in OpenSSH. Upgrade.
RSA 4096-bit length is ok. Less than that, upgrade. 1024-bit is unsafe at this point.
ECDSA Dependent on machine random number ability. Upgrade. Also, there is concern on the NIST curves used by ECDSA (due to the US NSA.).

Why upgrade to ED25519?

It offers better security with faster performance compared to DSA or ECDSA. Introduced in OpenSSH 6.5, it implements the Twisted Edwards curve of elliptical curve cryptography. It’s the most widely recommended public key algorithm right now by security experts (but strangely is not a default choice in gpg.).

Not familiar with ECC and how it works? Here’s an explainer, though it’s just a different algorithm for deriving the public and private keys you need. ED25519 keys also by default uses bcrypt/pbkdf2 to hash the private key which makes it much more resilient against brute force cracking attempts against the private key passpharse (admittedly, you can also force ssh and gpg to do thids for you with RSA keys but it requires knowing magic switches.). Another benefit, your public key will be much shorter than if you’re using RSA 4096-bit (which I find, makes it less intimidating to people not used to gpg and encryption in general.).

Generating ED25519 ssh and gpg keys

For ssh, creating keys with ED25519 in ssh is easy and a simple argument parameter. Use the -C flag if you want to have this associated with a particular email address and to be usable for that identity.

 λ ~ ssh-keygen -t ed25519 -C name@example.com
Generating public/private ed25519 key pair.
Enter file in which to save the key (/Users/you/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/you/.ssh/id_ed25519.
Your public key has been saved in /Users/you/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:85peYhJg2rHJoFGDfcDb0jfQOL2VDChGoJdOAIpGu70 daryl@Majid.local
The key's randomart image is:
+--[ED25519 256]--+
|=B=. =.o .       |
|*o*o* o +        |
|=+=*+o o         |
|.*=*o=+          |
|..o=*.=.S        |
|    .  . o       |
|   E  . o o      |
|       +         |
|       .+        |

Make sure you pick a very strong (and memorable to you) passphrase. You’ll notice the bit length at 256 is much less than RSA keys (at 4096 min) which consequently leads to much smaller public key blocks than you’ll be used to. In any case, now you’ve got your default ED25519 key. Pretty painless. NOte that the key is saved in the “new” OpenSSH format and not the traditional PEM format you may have become used to with past keys.

Let’s move onto gpg. GPG doesn’t offer you ED25519 keys as a default option when you use the interface though it’s a simple switch to let yourself have access to that functionality. Don’t let the --expert flag on the command intimidate you.

λ ~ gpg --expert --full-gen-key
gpg (GnuPG) 2.2.20; Copyright (C) 2020 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
   (9) ECC and ECC
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (13) Existing key
  (14) Existing key from card
Your selection? 9
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 1

You want option 9 here, the poorly named ECC and ECC here. Select 9 first, then 1 for Curve 25519 (aka ED25519) from the list.

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)

After that you’ll be asked to set an expiry for your key. I personally pick about 3 or 5 years for my keys but you can always alter the expiry of the key later (or even revoke it if need be) so this is a matter of taste. I do recommend making it longer than a year so people are not constantly forced to look up and validate your new public key if they want to communicate with you.

GnuPG needs to construct a user ID to identify your key.

Real name: Ice Bear
Email address: ice_bear@cave.com
You selected this USER-ID:
    "Ice Bear <ice_bear@cave.com>"

It will then ask you to secure the secret key with a strong passphrase (and do pick a strong, memorable one. Think phrase, not password) and then it will generate the key after collecting random “noise” from your computer to make the key as random as possible.

Under .gnupg in your home directory it will add the secret key to the directory private-keys-v1.d, add a revocation certificate to the directory openpgp-revocs.d and add your public key to the gpg public keyring, pubring.gpg.

Congratulations, you’ve now generated elliptical curve keys for both ssh and gpg. Now let’s see how to start getting your systems to use them with some use cases.

Changing your gitlab/github ssh key

Swapping out your key on github is not that hard though there are a few gotchas. For one, it appears that git, unless specifically configured, only looks for keys of the form id_* in your .ssh directory. For compatability, you will probably want your key named id_ed25519.pub else you will need to set up your /.ssh/config file to look something like this using git ssh identities if you want separate keys (which would look something like this):

  Host github.com
  	HostName github.com
  	User git
  	IdentityFile ~/.ssh/id_github_ed25519
  Host gitlab.com
  	Hostname gitlab.com
  	User git
  	IdentityFile ~/.ssh/id_gitlab_ed25519

Gitlab and Github both have excellent documentation for you to follow on adding the ssh keys, but basically it comes down to this:

  1. Copy id_ed25519.pub to the clipboard
  2. Go to your account settings and paste the new key in
  3. Test and log in
  4. Delete the old key(s) (Optional: once you’re sure everything works)

Do make sure your log in works and is working with your keys before deleting anything, otherwise you might need to start this enture process again (though github and gitlab both have ways for you to test if your ssh keys are working.).

Re-encrypting your password store

If you followed my Password management with GoPass post and are enjoying using gpg as driving your cli, web, and mobile password needs, you’ll also need to re-encrypt your password store to the new gpg ed25519 key.

First off, make a backup in case you do something wrong here. Good safety measure.

Strangely, this is one of the places gopass has seemed to break compatibility with the original pass password manager (most likely due to team features) and the pass init with the new key does not re-encrypt to the new key as in pass classic.

For gopass, you need to do the following:

gopass recipients add <keyid eg. id_ed25519>
gopass recipients remove <keyid eg. id_rsa>

Done. One issue: the git history which gopass integrates with if you followed my howto will still contain your passwords encrypted with the old key. The easiest way to handle this if you don’t care about the git history is to do the following: delete the .git folder in the password store and recreate it again:

cd .password-store
rm -rf .git
git init
git add .public-keys .gitattributes .gpg-id *
git commit -m"Initial commit after changing GPG key"

Note: You do not have to do this if your old key was still secure but it’s something you need to be aware of if your password store’s stored in the open somewhere (say github repos) and you have a reason to suspect motivated attackers.

Issue a gopass sync to make sure your new store pushes up to your git cloud repo (github, gitlab, bitbucket etc) and check to make sure you can decrypt an entry and that it asks you with your new ed25519 key and you should be done. Your password store is re-encrypted.

The gopass bridge should have your web browser’s passwords working already as it’s on your machine. To get GoPass for iOS (or the Android version) working you will need to do two things:

  1. Sync the new password to GoPass
  2. Copy your new public and secret key to GoPass for iOS

So, first off, grab your iPhone and go to GoPass. Pull down to sync the password store and your new re-encrypted info should git sync to the iPhone. So, now you have the newly re-encrypted password store.

Go back to your laptop and export the ascii-armoured public and secret key for id_ed25519 (assuming that’s the key you created and re-encrypted to). Copy them to clipboard or otherwise get them into a place you can enter them into the GoPass for iOS’s public and private key setup screen (obviously, replacing the previous keys you had in there for the old RSA key.).

You’re now done. Test you can now decrypt a password that’s encrypted to the new key, and create a new one, sync it and make sure you can decrypt it on your desktop to make sure everything works. If that all works, you’re done! You’ve now migrated to using ed25519 on your password store across all devices.

Updating keybase.io

Originally, the idea behind PGP and gpg public key verification was with a web of trust model. An attempt at decentralized trust that predates blockchain. Enough people verify and sign your key, people could be sure the public key represented your identity. While those public pgp servers still exist to drive that, it did not truly catch on except in (very) techie organizations.

Keybase.io started some time ago and has become a place where people can verify their keys and identities on the internet and then have a centralized place to refer to which also provides a more visible web of trust (in essence). I’m surprised, since I think it’s original mandate was different, but it’s slowly becoming a centralized collector of verified cryptographic identities for people. For example, if you look at my kaybase profile, it has verified my github and twitter accounts and provides the two keys (old RSA and new ed25519) that I want people to use if they encrypt to me. You can also very nicely import public keys directly from keybase into gpg to make your cryptographic life easier

In fact, on the About page of this blog, I point people at:

For secure communications, please use my main gpg public key, id 3F20 A015 3E1D 7043. Import directly into gpg with curl https://keybase.io/wakatara/pgp_keys.asc | gpg --import.

YMMV. I find it super handy. Accounts are currently free and it does have some nice features so you should check it out if that’s a use case for you. If you’ve already verified a key with keybase, you’ll also need to update if this is the main one you want to use for your identity (or your old key was weak as above.).

Tbh, I preferred when keybase had just a CLI interface available to people (which they did during the early betas) but now you need to install their application perform CLI functions like adding keys or removing keys. So, if you haven’t in a while, update keybase and make sure it’s on your system and you’ve logged in.

As long as your old public key is still valid and non-expired in keybase you can update (or add) a new public key. My old key is still in there and not expired.

Get to your terminal and issue this on the command line:

$ keybase pgp select --multi

The app will prompt you for the key you want to upload and then ask you to sign it with your corresponding secret key to prove your identity.

That’s it. All done. If you check keybase.io you should now have a second key in your profile. People can painlessly import your key into their gpg public keyring with the following:

curl https://keybase.io/<keybase username>/pgp_keys.asc | gpg --import

Note: Keybase currently doesn’t have a way for you to download only the one key so all gpg public keys available for the identity get imported for the person.

You can also provide a handy link from your personal blog or other pages with a link to:

https://keybase.io/<kaybase username/pgp_keys.asc?fingerprint=<full hex fingerprint of key>


And that’s about it. gpg ends up being an underlying infrastructure for security for me across a wide range of things where encryption and identity are important. Secure keys are important and changing them, requires some underlying knowledge even though it is not difficult when you know how. One of the wonders of gpg I find is that as long as you can move files around you can generally figure out a way to make things work.

I hope this helped you out and interested to hear back from you on ways it could be better or stuff you wold have also liked to have seen. Hit me up on twitter @awws via an @mention. And if you are learning about encryption and cryptography and needed someone to try out public key encryption with, you can always send encrypted email to me for practice using my main gpg public key, id 3F20 A015 3E1D 7043. Import directly into your gpg with curl https://keybase.io/wakatara/pgp_keys.asc | gpg --import on the command line.