Secrets of the Secure Shell: Part I

A turtle hiding in its shell on the ground surrounded by leavesPhoto © Lisa Zins (CC-BY)

Secure Shell ,  SSH for short, is indispensable and somewhat complicated.

When it's working as intended, a lot of folks might not even notice it. If you've ever used version control before, chances are that you've used SSH. Those chances are even greater if it was Git or Mercurial.

Here in the Managed Services department at Mindgrub, we use SSH all day, every day.

The first version of SSH debuted back in 1995, when you couldn't open your mailbox without an AOL floppy disk falling out of it. Its authors intended for it to replace several older protocols, namely rlogin, rsh, telnet, and FTP.

SSH is more secure than all of these. Why? It's a secret.

Secrets, lots of them

SSH relies on public key cryptography. The gist here is that each party involved in secure communication has a pair of keys: one public and one private. As their names suggest, the public key is shared, the private key is kept secret.

The keys are essentially just numbers, and they're mathematically related. Given a private key, you can generate the public key, and given a public key, you can encrypt a message that can only be decrypted by the private key.

Lots of protocols use this kind of cryptography: SSL/TLS, email, and even Bitcoin.

In the case of SSH, for example, the host has private and public keys. You use its public key to verify that you're connecting to the right place and that nobody has intercepted your transmission.

In the early days of SSH, you could only use the RSA cryptosystem to generate key pairs.

These days, you've got your pick of several encryption schemes, notably RSA, DSA, ECDSA, and Ed25519. On top of the choice of algorithm, in some cases, you've also got the choice of key size, which is the length of the private key in bits.

Private key formats

By generating your own private key and distributing your public key to the servers you visit, you can skip all that pesky entering a password to login business.

Now you might be asking, “Which one should I use?”

Great question! Let's run through each scheme.

RSA

The RSA standard is tried and true. RSA keys are supported all the way back to the inception of SSH, so you won't have to worry about portability.

Without going into too much math, an RSA key involves two really big prime numbers that get multiplied into one really, really big number.

At this time, the only known way to break RSA encryption is to try and factor out those two prime numbers in order to try to solve the rest of the equation. The bigger the number (i.e., the bigger the key size), the harder it is to break.

Since the creation of RSA in 1991, the biggest key length to be broken was 768 bits (that's a number with 232 digits), and it took 2,000 computer years to do it!

These days, if you generate an SSH key without specifying which algorithm to use, OpenSSH creates an RSA key that's 2048 bits in length. If you want your key to stand the test of time, I'd recommend a key length of 4096 bits, and to hope that Quantum Computing doesn't take off any time soon.

Running ssh-keygen -t rsa -b 4096 will place a 4096-bit private key at ~/.ssh/id_rsa and a public key at ~/.ssh/id_rsa.pub.

DSA

If you use OpenSSH to create a DSA key, it always makes one that's 1024 bits in length. OpenSSL, on the other hand, lets you specify the length.

Either way, it doesn’t really matter - DSA has fallen out of favor.

In fact, OpenSSH 7.0 has deprecated the algorithm. Not long ago, I discovered that I couldn't SSH into an old file server in my basement. Its host key was generated using DSA, and my laptop had a much newer version of OpenSSH without DSA support.

One of the reasons for this is that DSA is easy to break if the random number generator used during encryption is ever faulty or deterministic.

If an attacker has an encrypted message and can determine, with any level of reliability, which numbers are being fed into the algorithms used to do the encryption, it's a cake walk to figure out the private key.

Running ssh-keygen -t dsa will place a 1024-bit private key at ~/.ssh/id_dsa and a public key at ~/.ssh/id_dsa.pub.

ECDSA

Older systems might not support the ECDSA algorithm — it was introduced in 2011 when OpenSSH 5.7 was released. So if you're connecting to old systems, ECDSA is probably not for you.

ECDSA is very much like DSA, except it uses a different form of mathematics, elliptic-curve cryptography, to do its work.

ECDSA keys can only be 256, 384, or 521 bits in length.

The best part about ECDSA is that you can get equivalent security using smaller keys. That means less computation time to encrypt and decrypt data.

However, it still suffers from DSA's sensitivity to faulty random number generation. This problem is exactly how hackers in 2010 determined Sony's private key used to sign software for the PlayStation 3, and how hackers in 2013 managed to hijack bitcoin transactions from users of an Android wallet app.

Running ssh-keygen -t ecdsa -b 521 will place a 521-bit private key at ~/.ssh/id_ecdsa and a public key at ~/.ssh/id_ecdsa.pub.

Ed25519

Ed25519 is a relative newcomer to the SSH landscape, added to OpenSSH in 2014 with the release of version 6.5. Again, if you're connecting to old systems, Ed25519 is probably not for you.

Ed25519 keys have a fixed length. The standard implies that it's on par with the difficulty to break an RSA key length of ~3000 bits (which is very, very, very difficult).

The best part about Ed25519 is that it’s fast; really fast. While it also uses elliptic-curve cryptography, it's not vulnerable to the problem that ECDSA has with faulty random number generators. It's also resilient to many kinds of side-channel attacks, including timing attacks (where the amount of time a cryptosystem takes to encrypt or decrypt data reveals information about the numbers involved).

Running ssh-keygen -t ed25519 will place a private key at ~/.ssh/id_ed25519 and a public key at ~/.ssh/id_ed25519.pub.

The right choice

Are any one of these more secure than the others? Yes and no.

Breaking basically any encryption is a certainty. It's just a matter of the advancement of computing power, the number of computers crunching numbers, and how long it will take to solve the formula (similar to how an immortal monkey with a typewriter, hitting keys at random, will eventually type out the entire works of Shakespeare).

A short gif of a Simpsons episode with the caption "It was the best of times, it was the blurst of times..." "You stupid monkey!"

The choices are pretty clear. RSA is the right choice, and so is Ed25519.

The good news? You can use both! There's nothing wrong with having two private keys. After all, a server generates a key for each algorithm it supports, so why shouldn't you?

If the server to which you're connecting supports Ed25519, that key will be used. Otherwise, RSA is your fallback. So long as you distribute both of your public keys, you'll have no problems.

Securing your key

All the encryption in the world won't help you if you don't keep your private key secret.

The specifications for the SSH protocol actually require that a private key be used for authentication  in order to be readable only by its owner, and by no other users of the system on which it resides. For you Unix aficionados, that means chmod 0600.

On top of that, you can choose to apply a passphrase to your key (and you should ) to keep it safe in the event that the file itself manages to find its way into an adversary's hands. Without your passphrase, the key can't be used.

Agents and key rings

Applying a passphrase to a key means that every time you want to use it, you need to enter the passphrase. Boy, does that ever slow you down when you use SSH a lot. For that reason, lots of people remove the passphrase...and that, frankly, makes my skin crawl.

OpenSSH solved this problem a long time ago by introducing the ssh-agent program. Every major operating system has either this exact program or something similar to it. Windows (via PuTTY's Pageant), macOS, Linux, you name it.

Here's how it works:

First, add any keys that you want to use to the agent (e.g., with ssh-add). You’ll be prompted to enter the passphrase for each key.

Once you enter the passphrases, the agent stores the unprotected keys in memory, which it can then use for any process that needs them.

So, you'll only need to enter your password once. Depending on your setup, the agent or key ring stays active only until you log out. Other setups have the agent run until the system is shut down or rebooted.

Agent forwarding

Agent forwarding is handy, but also somewhat risky. It allows for the SSH agent on a remote server to act as a proxy to the local SSH agent on your system.

This is extremely useful in the case of bastion host, where you connect to one server and then jump to another. If you didn't use SSH agent forwarding in this case, you would need to place your private key directly on the bastion host.

You want as few copies of your private key floating around as possible.

Agent forwarding implies some trust in the remote system. Since the remote system would have the ability to use your private keys to authenticate to other systems, you'd want to know beforehand that you could trust it to not use them without having to run commands yourself.

To use agent forwarding, just pass the -A flag to your SSH command. Be forewarned, however: The remote system must be configured to allow agent forwarding for it to work.

Conclusion

You've got lots of different choices when it comes to SSH private keys.

Most importantly, keep your private key secret, then pick the right encryption. Finally, use an agent when it's convenient and safe.

Are you looking for some help securing your digital product or service? Mindgrub can help!