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 type of key smoothly, why you would want this and show some tips and tricks on the way there.

Tl;dr:

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

DSA and RSA 1024 bit are deprecated now

If you've created your key using software released before 2013 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!

Picture of an ancient key

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.)

:::console hl_lines="1"
$ 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!

Launchpad gained support for Ed25519 keys since February 16, 2022. Thanks Colin Watson for pointing this out in the comments!

Gerrit Code Review gained support since 2017 with the 2.14 release.

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

For SSH host key validation, please see my other article: SSH host key validation done right – strict yet user-friendly.

Your thoughts

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

Love my post? Please share it.

Share on: Twitter ❄ Hacker News ❄ Facebook ❄ LinkedIn ❄ Reddit ❄ Email

Comments

comments powered by Disqus

Related Posts


Published

Last Updated

Category

Security

Tags

Connect with me on...