Blog.

Upgrade your SSH security

Marco Franssen

Marco Franssen /

10 min read1833 words

Cover Image for Upgrade your SSH security

As a DevOps engineer you are probably familiar with SSH keys and how to use them already. I wrote some blogs on SSH in the past as well see the references. This time I want to zoom in a bit on the encryption strength of your keys and the encryption types you can use.

Why should you care about this?

In todays world password are becoming more and more a security risk. In the near future Github for example will not support password authentication anymore for clone, push and pull actions, just like they did for their APIs. But also to get SSH access to your servers SSH keys are a more secure way to gain access to your servers. Therefore you should be aware on how to setup your SSH keys in a secure way and how to use them securely.

This is how I have been generating my ssh-keys for years now.

terminal
ssh-keygen -t rsa -b 4096 -C marco.franssen@domain.tld

So is this still the recommended approach? Let's find that out.

Algorithms for SSH keys

IndicatorAlgorithmReasoning
🚨DSAUnsafe and no longer supported since OpenSSH version 7!
⚠️RSADepends on key size. If it has 3072 or 4096-bit length, then you’re good. Less than that, you probably want to upgrade it. The 1024-bit length is even considered unsafe.
👀ECDSADepends on how well your machine can generate a random number. There’s also a trustworthiness concern on the NIST curves that being used by ECDSA.
Ed25519It’s the most recommended public-key algorithm available today! It has a 256-bit length and gives equal if not better protections as a 4096-bit RSA key.

So based on above table we can conclude I'm still safe with the keys I'm using today, however there are a few small improvements I can do. Let's have a more detailed look on the algorithms and how to generate them.

DSA

This algorithm is deprecated due to very poor randomness. OpenSSH version 7.0 and newer even refuse DSA keys smaller than 1024-bits. DSA key pairs should not be used anymore.

RSA

This non-elliptic crypto algorithm is based on prime numbers. It is probably the most used algorithm used today. When generating keys with less then 2048-bits it is also considered insecure. The problem with RSA is it's source of entropy that is causing the weakest link. This is probable the first algorithm to fall when quantum computations will get more mature. Using a keysize of 3072-bit you should be safe for the upcoming 2 years, whereas the 4096-bit keys should probably put you on the safe side for at least the next 5 years.

ECDSA

The elliptic-curve (EC)DSA algorithm is supposed to help us combat these quantum computational attacks, while generating keys with significantly smaller key size without compromising the level of security. The size of the elliptic curve determines the difficulty to break the algorithm. However, secure implementations of the ECDSA curves are theoretically possible but very hard in practice. Furthermore, a weakness in RNG was publicly identified but still incorporated by NIST. We later learned from Snowden that the NSA had worked on the standardization process in order to become the sole editor of this Dual_EC_DRBG standard, and concluded that the Dual_EC_DRBG NIST standard did indeed contain a backdoor for the NSA. Why trust NIST curves when there is a more transparent way of doing crypto?

Ed25519

Ed25519 was introduced in OpenSSH 6.5 (January 2014). It’s the EdDSA implementation using the Twisted Edwards curve. It’s using elliptic curve cryptography that offers a better security with faster performance compared to DSA or ECDSA.

Today, the RSA is the most widely used public-key algorithm for SSH key. But compared to Ed25519, it’s slower and even considered not safe if it’s generated with the key smaller than 2048-bit length.

The Ed25519 public-key is compact. It only contains 68 characters, compared to RSA 3072 that has 544 characters. Generating the key is also almost as fast as the signing process. It’s also fast to perform batch signature verification with Ed25519. It’s built to be collision resilence. Hash-function collision won’t break the system.

Long story short: it is not NIST and it is not NSA. The long story is that while NIST curves are advertised as being chosen verifiably at random, there is no explanation for the seeds used to generate these NIST curves. The process used to pick Ed25519 curves is fully documented and can be verified independently. This prevents a malicious party from manipulating the parameters. Furthermore, the Ed25519 algorithm is supposed to be resistant against side-channel attacks.

What to do with this information

As we already concluded my key is still on the safe side, but I can also still improve a few things. When generating the RSA key I'm still saving the private key in the PEM format, however I could store it in the newer more secure OpenSSH format by providing another command line option (for ed25519 this is the default). Doing so stores my private key in a more secure format.

Generate a strong RSA key

terminal
$ ssh-keygen -o -t rsa -b 4096 -C marco.franssen@macbook-pro
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/marco/.ssh/id_rsa): /Users/marco/.ssh/id_rsa_new
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/marco/.ssh/id_rsa_new.
Your public key has been saved in /Users/marco/.ssh/id_rsa_new.pub.
The key fingerprint is:
SHA256:t8yF1u3ahe/BfVtqHz6XO+2L11P9oW6WKw3ojdKZxsY marco.franssen@macbook-pro
The key's randomart image is:
+---[RSA 4096]----+
|                 |
|    E  .@        |
|                 |
|         o .     |
|        S = o . .|
|         * + ..o+|
|        = O o =+%|
|       . E o O+X@|
|        +   *==O%|
+----[SHA256]-----+

⚠️ Please note we are using a password on our private key to protect it. I'm also storing the key in a new file, so I can slowly migrate my keys on various servers to use my new key. (More on that later…)

What commandline options did we use?

  • -o: Save the private-key using the new OpenSSH format rather than the PEM format.
  • -t: Specify the type of key to create, in our case RSA
  • -b: Specify the keylength, in our case 4096 bits. Ensure to use at least 3072-bits.
  • -C: An option to specify a comment. Purely used as informational, mostly we fill out the comment with <login>@<hostname> to be able to identify which key this is about.

Without the -o option we would have had a private key stored that begins with

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,7A720C77B76E72BD9BCE0ADD9EB80961

v+j4P…………………

Using the -o option our key is now stored in the new OpenSSH format.

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDkGszUTi
xCI0MMO………………

Now I also want to have a key using the Ed25519 algorithm as this is considered more future proof as well uses smaller keysize which should improve the performance of my SSH connections. Let's have a look at that.

Generate a Ed25519 key

terminal
$ ssh-keygen -t ed25519 -a 64 -C marco.franssen@macbook-pro
Generating public/private ed25519 key pair.
Enter file in which to save the key (/Users/marco/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/marco/.ssh/id_ed25519.
Your public key has been saved in /Users/marco/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:Mc/2w2DifqTIvLd214aawJtFVl8pv//ZzEXiq8/JwPo marco.franssen@macbook-pro
The key's randomart image is:
+--[ED25519 256]--+
|   @ .. ..       |
|                .|
|        o   .. . |
|         = . .o. |
|        S O   o..|
|       o *.= . o.|
|     o .+O. *o...|
|      +.+=o o=o==|
|      .+=+++E+*.B|
+----[SHA256]-----+

⚠️ Please note we are using a password on our private key to protect it. I have used 64 KDF rounds which seems to be a good tradeoff between waiting time and brute force attacks.

  • -a 16 takes on average 0.247 (seconds) *default*
  • -a 32 takes on average 0.586
  • -a 64 takes on average 1.206
  • -a 100 takes on average 1.962
  • -a 150 takes on average 2.664

What commandline options did we use?

  • -o: Save the private-key using the new OpenSSH format rather than the PEM format. Implicitly implied when using ed25519.
  • -t: Specify the type of key to create, in our case RSA
  • -a: The numbers of KDF (Key Derivation Function) rounds. Higher numbers result in slower passphrase verification, increasing the resistance to brute-force password cracking should the private-key be stolen.
  • -C: An option to specify a comment. Purely used as informational, mostly we fill out the comment with <login>@<hostname> to be able to identify which key this is about.

Looking at the generated key we can see the ed25519 key sizes are indeed much smaller then our RSA keys.

terminal
$ for k in ~/.ssh/id_* ; do wc -m $k ; done
     464 /Users/marco/.ssh/id_ed25519
     108 /Users/marco/.ssh/id_ed25519.pub
    3326 /Users/marco/.ssh/id_rsa
     752 /Users/marco/.ssh/id_rsa.pub
    3434 /Users/marco/.ssh/id_rsa_new
     752 /Users/marco/.ssh/id_rsa_new.pub

Using the newly created SSH keys

To use your SSH keys they will have to be loaded into your ssh-agent. Furthermore we can define which key we want to use for which server connection. This allows us to migrate.

~/.ssh/config
Host github.com
  IdentityFile ~/.ssh/id_ed25519

Host my.legacy.server.com
  IdentityFile ~/.ssh/id_rsa_new

Host *
  IdentityFile ~/.ssh/id_ed25519
  IdentityFile ~/.ssh/id_rsa_new
  IdentityFile ~/.ssh/id_rsa

Once you migrated all you keys you can eventually cleanup the old id_rsa key. Please note if all the servers you are connecting support the ed25519 algorithm, then you can eventually just go with only the id_ed25519 key.

~/.ssh/config
Host *
  IdentityFile ~/.ssh/id_ed25519

For more details on how to configure SSH settings, you can have a look at my other blogposts on SSH. In there I go a bit further into detail on configuring your SSH client. E.g. configuring agent forwarding etc.

References

See you next time. Please consider sharing with your peers so we can make our job more secure.

You have disabled cookies. To leave me a comment please allow cookies at functionality level.

More Stories

Cover Image for How to do Enums in Go

How to do Enums in Go

Marco Franssen

Marco Franssen /

It has been a while since I wrote a blog on Go. Since I'm getting the question if Go supports enums every now and then, I thought it would be good to write an article on how to do enums in Go. Go natively does NOT have an enum type like you might be used to from c# or Java. However that doesn't mean we can easily define our own type. In this blog we will cover defining our own type, combined with a piece of code generation. If you are new to Go, then consider reading Start on your first Go pro…

Cover Image for Hello Next.js, goodbye Hexo

Hello Next.js, goodbye Hexo

Marco Franssen

Marco Franssen /

For the folks reading my blog for a long time, you might have noticed I'm using my current theme and blogging engine for a long time. About 5 years ago I migrated from Wordpress to Hexo. Wordpress at that point in time was costing me serious money to get a decent performing webpage according to modern standards. So back then I decided to move into a statically generated blog, where I could write my blogs offline using markdown. Hexo has served me very well the last couple of years. It is a stat…