Why and How: Switch from RSA to ECDSA SSH keys

Why and How: Switch from RSA to ECDSA SSH keys

As a developer, the chances are pretty high that you have your own keys to connect to servers, and be it only the server hosting the git repository. At least I haven't heard of anybody typing his username and password into the terminal while pushing the latest commits to the remote repository. Those keys are mostly generated by using the RSA algorithm, which was and still is the standard for generating the cryptographic keys.

If you are not interested in the why, but in the how, you may jump directly to the third headline.

Why RSA might not serve you well for the next decades

Invented back in 1977, RSA) seemed to be the best solution to generate secure keys. Computers were slow and it might take several decades until RSA would be rendered insecure by cracking the algorithm. However, advancing 40 years, keys are no longer really secure if they are less than 1024 bit. The ENISA (European Union Agency for Cybersecurity) recommends the usage of keys with a length of 2048 bit for short-term security only. Therefore, do not generate new keys shorter than 4096 bit characters!

One could argument, that simply using longer key lengths would solve this problem, so let's generate new keys with a length of 8192 bit. The problem here is, that the time to actually process keys of this length is not suitable for low-powered devices, while the actual gained security strength does not raise proportionally: A key length of 1024 bit for an asymmetrical key (which we use for SSH) only has a "real" strength of 80 bit based on symmetrical methods. Increasing that length from 1024 to 2048, however, does not increase the "real" security to 160, but only 112 bit.

Stage enter: Elliptic Curve Algorithms

To solve the problem that long keys lead to much higher processing times while only increasing security a bit, some really smart people figured out algorithms based on elliptic curves. Sadly, I cannot explain how those mathematical constructs work in detail. Based on the information available about the topic, those elliptic curves can be used to generate strong secure keys while keeping them shorter than regular RSA keys. For example, a key with a length of 256 bit is equal to a AES key of 128 bit which is considered quite secure. This way shorter keys, while granting a stronger security than RSA, are also easier to process on low-powered machines.

Elliptic curves cryptography ist just the theory, which ECDSA (Elliptic Curve Digital Signature Algorithm) and ECDH (Elliptic-curve Diffie–Hellman) are based on. Both technologies are used in SSH to connect two peers: ECDSA to generate the keys and ECDH as the key exchange protocol.
When generating a key, you can choose between two variants: the NIST-standardized ECDSA, and Curve25519. Although the latter is considered the better choice for new keys in the cryptography community, the former is implemented into more systems and applications, leading to a higher compatibility.

Given all those aspects, switching from RSA to ECDSA might be a good idea. And if you know that your RSA-based key is just 1024 bit long, please switch as soon as possible!

How to switch from RSA to ECDSA

Before switching, a word of caution: the following process may take some time, depending on the number of server you connect to and where your public keys are stored. Also, please do yourself a favor and make a backup of both your id_rsa and id_rsa.pub files right now. Copy them to a .backup directory inside your .ssh folder, copy them to a secure USB stick, whatever fits you most. Just keep them secure at all times.

Done? Fine.

Generate a new ECDSA key

Generating a new key based on ECDSA is the first step. The following command is an example and you should customize it:

ssh-keygen -t ecdsa -b 521 -C "mail@example.com"
  • The -t ecdsa part tells the ssh-keygen function (which is part of OpenSSL), which algorithm to use. In contrast to ecdsa you may also use ed25519 for using Curve25519, but for better compatibility, stay at ECDSA.
  • Notice, that despite being located in the binary world, we do not use 512 as the key length, but 521, specified by -b 521. Reason is the mathematical structure of the key, which does not adhere to the power of two.
  • Finally, you specify your email address with the -C "mail@example.com" flag. Obviously, replace the example address with your own.

Saving the key and setting a passphrase

After hitting enter the program will ask you for the location of the newly generated key. If you have no previous ECDSA key in your .ssh folder, you may skip this because the keygen will name the new key id_ecdsa in contrast to id_rsa for RSA keys.

The next thing you do is specifying a passphrase. Please do not skip this. I see numerous blog posts and tutorials that are fine with skipping this step. DO NOT SKIP THIS! Setting a passphrase is the same as setting a password for your email account. If an attacker or any other random person gets access to your private key file, they can use it without any hurdles if you skip setting a passphrase! And with access to your private key this third party has access to all servers you connect to using the key. So, please set a password. In the best case it has the same strength as any other password you generate. Use a damn password manager if you don't want to remember passwords.

If you set your passphrase, the keygen will do its magic. Congratulations, you are now the proud owner of a brand new ECDSA key! The output should look similar to this:

Generating public/private ecdsa key pair.
Enter file in which to save the key (/Users/kg/.ssh/id_ecdsa): ./id_ecdsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./id_ecdsa.
Your public key has been saved in ./id_ecdsa.pub.
The key fingerprint is:
SHA256:Hp34bIvFV1lpCLkjnkganWYIqDGUtCgbvwLb/1K+6oU mail@example.com
The key's randomart image is:
+---[ECDSA 521]---+
|ooo        ..    |
|+o..       .. . .|
|=+  . o .   .. o.|
|o+   o * + +  .o |
|o .   * S = . o  |
|.o . o.o B   .   |
|o o Eo. . * .    |
| . ....  + o     |
|   .++o.. .      |
+----[SHA256]-----+

Pushing the new key to your servers

Of course, you want to use your new key and push it to all servers you are using. No problem. I assume that the servers you want to connect to follow the most basic security guidelines and thus are somewhat up-to-date, which means they should run the latest version of OpenSSH or a similar SSH server. If your server does not support ECDSA yet you may have some other problems right now: update the server.

An easy command to push your new SSH key to your server comes pre-installed with OpenSSH:

$ ssh-copy-id -i ~/.ssh/id_ecdsa [username]@[hostname]

Specify the used key (-i ~/.ssh/id_ecdsa) and your SSH credentials ([username]@[hostname]), and the command should automatically copy the public key to the server. Try to login to the server using the new key to check if it's working correctly: ssh -i ~/.ssh/id_ecdsa [username]@[hostname]

A more manual way, of course, is to manually login to the server and past the content of the public key into the authorized key file.

PS: Don't forget to add the new key to Github, Gitlab and similar services.

Configure SSH to use your new key

Last but not least: we want to tell SSH that it should use the new key by default. The main problem here is, that SSH assumes that you have an RSA key set and uses it if one was found. But we want to use our new fancy ECDSA key, and not some old RSA thingy.
The most suitable way to do this, is to use the standard SSH config. In my opinion all other approaches are more hacks than solutions to make this work. If you don't already use the SSH config: it's the main configuration file for your local machine. It's usually located at ~/.ssh/config. In that file you can specify either global settings which will then be applied to all SSH connections, or settings per host. You can also create aliases for your connections, to reduce something like company_username@48.35.183.137 to companyssh.

So, open the .ssh/config file now. At the very top, if not present already, add the following lines:

Host *
    IdentityFile ~/.ssh/id_ecdsa

The first line tells SSH to apply the next settings to all hosts, hence the wildcard *. The second line then sets the newly generated key ~/.ssh/id_ecdsa as the new identity. That's it. There is nothing more to configure. Make sure that, when connecting to an old server that does not yet has the new key, add the -i ~/.ssh/id_ecdsa flag to your SSH command: ssh ~/.ssh/id_ecdsa [username]@[some-old-server].

PS for all macOS users: to prevent macOS asking for the key passphrase every time you use the key, add UseKeychain yes to the global settings in your SSH config. Linux users may use ssh-agent.

Conclusion

Despite being a pretty long blog post, you essentially have to run only a couple commands to create your new key, push it to your servers and then configure SSH to use the new key. Depending on the amount of servers you have to add the key to it may take 10-20 minutes of your time. After passing the finish line you are good to go with your new, super secure SSH key.


This article was first published on Blog.Kovah.de