Whether you're a software developer or a sysadmin, I bet you're using SSH keys. Pushing your commits to Github or managing your Unix systems, it's best practice to do this over SSH with public key authentication rather than passwords. However, as time flies, many of you are using older keys and not aware of the need to generate fresh ones to protect your privates much better. In this post I'll demonstrate how to transition to an Ed25519 key smoothly, why you would want this and show some tips and tricks on the way there.

Tl;dr: Generate your new key with ssh-keygen -o -a 100 -t ed25519 , specify a strong passphrase and read further if you need a smooth transition.

I'm planning to publish some more posts on SSH tips & tricks, so keep an eye on my blog for more. This post will focus on about SSH keys as user public key authentication.

DSA and RSA 1024 bit are deprecated now

If you've created your key more than about four years ago with the default options it's probably insecure (RSA < 2048 bits). Even worse, I've seen tweeps, colleagues and friends still using DSA keys ( ssh-dss in OpenSSH format) recently. That's a key type similar to RSA, but limited to 1024 bits size and therefore recommended against for a long time. It's plainly insecure and refused for valid reasons in recent OpenSSH versions (see also the changelog for 7.0).

The sad thing about it is that I see posts on how to re-enable DSA key support rather than moving to a more secure type of key. Really, it's unwise to follow instructions to change the configuration for PubkeyAcceptedKeyTypes or HostKeyAlgorithms (host keys are for a later post). Instead, upgrade your keys!

Compare DSA with the technology of locks using keys like this one. You wouldn't want this type of key to unlock your front door, right?

Determine your current situation

List all your keys:

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

DSA or RSA 1024 bits: red flag. Unsafe.

RSA 2048: yellow recommended to change

RSA 3072/4096: great, but Ed25519 has some benefits!

ECDSA: depends. Recommended to change

Ed25519: wow cool, but are you brute-force safe?

A smooth transition, I promise.

You're probably thinking… "I'm using my key for a long time, I don't want to change them everywhere now." Valid point, but you don't have to! It's good to know you can have multiple keys on your system and your SSH client will pick the right one for the right system automatically.

It's part of the SSH protocol that it can offer multiple keys and the server picks the one your client will have to prove it has possession of the private key by a challenge. See it in action adding some verbosity to the SSH connect command ( -vvv ). Also if you're using an SSH agent you can load multiple keys and it will discover them all. Easy as that.

You'll like the Twisted Edwards curve

Most common is the RSA type of key, also known as ssh-rsa with SSH. It's very compatible, but also slow and potentially insecure if created with a small amount of bits (< 2048). We just learned that your SSH client can handle multiple keys, so enable yourself with the newest faster elliptic curve cryptography and enjoy the very compact key format it provides!

Ed25519 keys are short. Very short. If you're used to copy multiple lines of characters from system to system you'll be happily surprised with the size. The public key is just about 68 characters. It's also much faster in authentication compared to secure RSA (3072+ bits).

Generating an Ed25519 key is done using the -t ed25519 option to the ssh-keygen command.

Ed25519 is a reference implementation for EdDSA using Twisted Edward curves (Wikipedia link).

Increase resistance to brute-force password cracking

When generating the keypair, you're asked for a passphrase to encrypt the private key with. If you will ever lose your private key it should protect others from impersonating you because it will be encrypted with the passphrase. To actually prevent this, one should make sure to prevent easy brute-forcing of the passphrase.

OpenSSH key generator offers two options to resistance to brute-force password cracking: using the new OpenSSH key format and increasing the amount of key derivation function rounds. It slows down the process of unlocking the key, but this is what prevents efficient brute-forcing by a malicious user too. I'd say experiment with the amount of rounds on your system. Start at about 100 rounds. On my system it takes about one second to decrypt and load the key once per day using an agent. Very much acceptable, imo.

With ssh-keygen use the -o option for the new RFC4716 key format and the use of a modern key derivation function powered by bcrypt. Use the -a <num> option for <num> amount of rounds.

Actually, it appears that when creating a Ed25519 key the -o option is implied.

The OpenSSH manpages are not really explanatory about the 'new' format. I found this article pretty useful: "new openssh key format and bcrypt pbkdf" on www.tedunangst.com.

Generate your new sexy Ed25519 key

Protip Use the same passphrase on all of your key types and profit with more convenience. (See also Multi-key aware SSH client.)

$ ssh-keygen -o -a 100 -t ed25519 Generating public/private ed25519 key pair. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/gert/.ssh/id_ed25519. Your public key has been saved in /home/gert/.ssh/id_ed25519.pub. The key fingerprint is: SHA256: [...] gert@hostname The key's randomart image is: [...]

Note the line 'Your identification has been saved in /home/gert/.ssh/id_ed25519'. Your current RSA/DSA keys are next to it in the same ~/.ssh folder. As with any other key you can copy the public key in ~/.ssh/id_ed25519.pub to target hosts for authentication.

Multi-key aware SSH client

All keys available on default paths will be autodetected by SSH client applications, including the SSH agent via ssh-add. So, if you were using an application like ssh/scp/rsync before like...

$ ssh user@host

it will now offer multiple public keys to the server and the server will request proof of possession for a matching entry for authentication. And your daily use of the ssh-add command will not change and autodiscover the Ed25519 key:

$ ssh-add Enter passphrase for /home/gert/.ssh/id_rsa: Identity added: /home/gert/.ssh/id_rsa (gert@hostname) Identity added: /home/gert/.ssh/id_ed25519 (gert@hostname)

It not only discovered both keys, it also loaded them by entering a single passphrase (because it's the same)!

We've reached a very important goal now. Without any change to your daily routine we can slowly change the existing configuration on remote hosts to accept the Ed25519 key. In the meantime the RSA key will still work. Great, right!?

Change or set a passphrase

If you're afraid this will change your key, don't worry. The private part of your keypair is encrypted with a passphrase which only exists locally on your machine. Change it as often as you like. This is recommended to prevent abuse in case the key file gets into the wrong hands. Repeat for all your key files to ensure a new key format with 100 bcrypt KDF rounds:

$ ssh-keygen -f ~/.ssh/id_rsa -p -o -a 100

Upgrade your current RSA key

Using Ed25519 will (and should) work in most situations by now, but legacy systems may not support them as of yet. The best fallback is a strong RSA keypair for this.

While the OpenSSH client supports multiple RSA keys, it requires configuration/command line options to specify the path so it's rather error-prone. Instead, I'd recommend upgrading your existing key in-place to keep things simple once this is done. Depending on the strength (key size) of your current RSA key you can migrate urgently or comfortably.

In case you have a weak RSA key still, move it out of the way from the standard path and generate a new one of 4096 bits size:

$ mv ~/.ssh/id_rsa ~/.ssh/id_rsa_legacy $ mv ~/.ssh/id_rsa.pub ~/.ssh/id_rsa_legacy.pub $ ssh-keygen -t rsa -b 4096 -o -a 100

If you are using an agent, manually point it to all your keys:

$ ssh-add ~/.ssh/id_rsa ~/.ssh/id_rsa_legacy ~/.ssh/id_ed25519

Once you are finished the transition on all remote targets you can go back to convenience and let it autodiscover your new RSA and Ed25519 keys; simply omit the keyfile arguments.

Software support for Ed25519

Support is available since OpenSSH 6.5 and well adopted in the Unix world OSs for workstations. Ubuntu 14.04+, Debian 8+, CentOS/RedHat 7+ etc. all support it already. (If you have details about Mac OS X please drop a line, couldn't find it with a quick search). Some software like custom desktop key agents may not like the new keys for several reasons (see below about the Gnome-keyring for example).

Github works pretty well too, by the way. Launchpad and Gerrit code review however, seem to require RSA keys unfortunately. PuTTY on Windows? See below.

My Gnome-keyring doesn't work anymore

The Gnome-keyring, as used in Ubuntu Unity at least, fails to read the new RFC4716 format keys but reports success. It's bugged. More details here in my AskUbuntu Q&A post. I'd recommend disabling the Gnome keyring for SSH agent use and use the plain OpenSSH agent instead.

I'm using Windows with PuTTY

Sorry, I'm not using PuTTY, but make sure to upgrade first. This page suggests Ed25519 support since a late-2015 version according to a wishlist item. Generally speaking, I'm not too excited with the speed of implementation of security features in it.

Is this the ultimate secure SSH keypair?

We've taken some steps, important ones, but it's far from ultimate security. When dealing with high assurance environments I would strongly discourage key usage like described in this post as this holds the unencrypted private key in memory. Instead, use hardware security (smart cards) to avoid leaking keys even from memory dumps. It's not covered in this post, mainly because it requires a hardware device you need to buy and secondly because the limitations are device dependent. A nice cute solution would be to make use of your TPM already built-in your PC probably, but that would definitely deserve another post.

Follow-up posts

I'm planning on writing some more on how to harden SSH a bit more; custom host keys, custom DH moduli, strong ciphers (e.g. chacha20-poly1305 ) and secure KeyExchange/MACs. For now this is a great resource already: https://stribika.github.io/2015/01/04/secure-secure-shell.html

Your thoughts

Want to share some ideas? Post it below in the comments.

Love my post? Please share it.