Passwordless SSH using digital signatures
En Español  På Norsk  

When we log in via SSH to a remote computer, usually a server, a way to authenticate with it that does not require the use of a password is the use of digital signatures. What we do in this case is to generate a key pair (a public key and a private key), and then add our public key to the list of authorized keys in the server that we want to be able to log into.

The first thing that we do is to create a key pair in the computer from which we will access the SSH server:

ssh-keygen -t rsa -b 4096

This will create two files, one called id_rsa which is our private key, and one called which is our public key. After this, we just need to add our public key to the list of authorized keys in the SSH server. This file is located in ~/.ssh/authorized_keys

A way to do this is to simply upload the file to the server, and then concatenate the contents of the file into ~/.ssh/authorized_keys. If the file authorized_keys, or the folder .ssh does not exist, you can create the folder with mkdir and the file with touch, although the cat command itself would create the file if it doesn't previously exist.

scp ~/.ssh/ user@domain:~/
ssh user@domain
ls -d .ssh || mkdir .ssh
cat >> ~/.ssh/authorized_keys

Another way to do it it's to use the commands together in one single (but long) command:

cat ~/.ssh/ | ssh user@domain 'ls -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys'

Once this is done, don't forget to give to this folder and file the appropriate permissions, or else another user in the same system as you may just add a key to your file of authorized keys and this user would be able to log in via SSH into the system as you.

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

And we are done, in the future I will write an extensive explanation of how exactly does this work, with graphics an all, but for the moment the important thing here is that, information which is encrypted with our private key can only be decrypted by our public key, and information that is encrypted with our public key can only be decrypted by our private key.

Digging deeper

As you may already know, there are two protocols of SSH, the old implementation (protocol 1) and the most recent and better implementation (protocol 2). I am not sure why would anyone continue allowing access to a legacy SSH implementation that can only use the first protocol, but, I'm sure there are some that find it useful, personally I only allow the second protocol.

There are different algorithms for digital signing, in SSH there is RSA (Rivest, Shamir and Adleman; it is named after its creators), DSA (Digital Signature Algorithm) and ECDSA (Elliptic Curve Digital Signature Algorithm). To not make this long (I believe this ought to have a dedicated article):

  • DSA is known to utilize a broken RNG (Random Number Generator), it is no longer accepted by default after openSSH 7.0, I don't recomend using it.
  • ECDSA allow us to have smaller keys and therefore it takes a shorter time to do the calculations. A 256-bit elliptic curve public key provide comparable security to a 3072-bit RSA public key.
  • RSA is strong, if you use a 4096-bit RSA you are very safe. An advantage is that this one is implemented pretty much everywhere, where as an ECDSA key is not (but it should, on these days chances are you are not going to find systems where it doesn't work).

The use of this keys is merely for authentication with the server when you log in, once you are logged in, a different type of encryption is used so what you do is secure from snooping.

Using ECDSA instead of RSA

If you prefer to use ECDSA for authentication with the SSH server, you can use the following commands:

ssh-keygen -t ecdsa -b 521

This will generate the files id_ecdsa (your private key) and (your public key), and then we just add the key to authorized_keys by method 1:

scp ~/.ssh/ user@domain.tld:~/
ssh user@domain.tld
ls -d .ssh || mkdir .ssh
cat >> ~/.ssh/authorized_keys

Or method 2:

cat ~/.ssh/ | ssh user@domain.tld 'ls -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys'