Hi all,

Following my 2 last posts on SSH and using Cygwin with Console2 for a much superior terminal experience the next logical step is key-based authentication.

There are 2 ways to authenticate over SSH - passwords (that you type) and key-based authentication. For the second method to work you generate on the host/desktop you want to use as a client a set of SSH keys.

This is done very easily by typing:

ssh-keygen

Note: You can provide arguments such as -t for a different type of key (such as "dsa" or "rsa") but it's not really needed as the default which is rsa is considered secure enough.

This will get you the following output:

Generating public/private rsa key pair.
Enter file in which to save the key (/home/Lampros/.ssh/id_rsa):

Just press Enter to take the default and continue - .ssh is the standard location for keys.

Then you'll get:

Enter passphrase (empty for no passphrase):

A passphrase is a good idea in an environment/situation where you're worried that your keys might get stolen by someone. This would provide them access to the server you are setting the key-based authentication for. For a testing environment however skipping the passwords is perfectly fine.

Then you'll ask to verify your passphrase:

Enter passphrase (empty for no passphrase):

And then you'll get the key fingerprint and randomart image:

Your identification has been saved in /home/Lampros/.ssh/id_rsa.
Your public key has been saved in /home/Lampros/.ssh/id_rsa.pub.
The key fingerprint is:
82:58:ac:84:b9:1b:c5:0d:ff:8d:bb:d5:cf:e6:13:4a Lampros@Jamie-HP
The key's randomart image is:
+--[ RSA 2048]----+
|  .              |
| + =             |
|o + =            |
| + + o o         |
|o o . + S        |
| o     o .E .    |
|.     . .... .   |
|       o  .oo    |
|      .    o+.   |
+-----------------+

Most importantly note the parts:

Your identification has been saved in /home/Lampros/.ssh/id_rsa.
Your public key has been saved in /home/Lampros/.ssh/id_rsa.pub.

The ssh-keygen command generates two files - the above ones. The identification file is also known as the "private" key - never give this out to anyone. The public key on the other hand is what we are interested in.

Use a viewer like less to check what the key looks like:

less /home/Lampros/.ssh/id_rsa.pub

You'll see something like this:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcPToMocAzfEC5D50HjgDyww2HKJZenzaHPl3IUZaKF6xuW5T7tK7Y+GK7RNUDBbdYerE+WlLh7XfS/mW1gDQePtBfJFGiOXvKXPjCQ1GJHKe/dfDqKKl/K78wubbvr7IwkRQwvFVqoEJwepsIDTOhIxt7S2/UiwsjdvyrF6GJbaosSExGTvF6zj2a1+l4T98LGKC7zO/e+4Fb4KnldRuazPTGj0WPzPzuHjuxFUQf7/mvESZgdG7zH0y8W7Kc0tMGpOE764UoI8x/64lerleKUNCMQgm3SvapASGsU42kPCejdWJO89NS3yJnK26QIJCZeB//iN/UQM+gixxYXgLp Lampros@Jamie-HP

The above output is correct - the key is one line - if your editors enter line breaks in between then you'll end up breaking your key! be careful with line wrapping vs line breaks.

What we now want to do, is copy the public key to our target server. We can't just copy it anywhere though, SSH keys have their special place - it needs to go under the home directory of the user we're trying to ssh as, then under the directory .ssh and into the file authorized_hosts.

You can copy paste the whole thing - make sure to include "ssh-rsa" all the way to the end of the key.

Then on the target server navigate to your target user's home directory - in our example it's user root so it's home directory is /root.

And edit the file (create it if it doesn't exist) .ssh/authorized_keys - in this example I edit it with vim:

vim .ssh/authorized_keys

And paste the key - make sure there are no empty lines before or after the key.

Save and exit.

If you want to make sure there are no lines breaks, do a simple check like this (this is in the case you have only 1 key file in your authorized_keys file:

cat /root/.ssh/authorized_keys | wc -l
       1

The above pipes the contents of authorized_keys in wc (word count). The -l parameter counts lines. If you have only 1 key and get anything else but 1 then you have a problem.

Before we even test the key a note on SSH permissions - they are very strict. If your file permissions are not correct you will get authentication fails which can be very frustrating.

To make sure they're correct on the target do:

stat -x /root/.ssh/authorized_keys | grep Mode

Note: The above command is for FreeBSD only. The stat command is different on FreeBSD as it's not the GNU tools version.

You'll get something like this:

Mode: (0644/-rw-r--r--)         Uid: (    0/    root)  Gid: (    0/   wheel)

If you get 644, then it's probably a good idea to change the mode to 600. The .ssh directory itself should be set to 700.

Change the permission of all files under .ssh to 600:

chmod 600 /root/.ssh/*

Check the permissions again:

stat -x /root/.ssh/authorized_keys | grep Mode
  Mode: (0600/-rw-------)         Uid: (    0/    root)  Gid: (    0/   wheel)

Much better!

Now check the /root/.ssh directory itself:

root@weirdbricks:/root # stat -x /root/.ssh/ | grep Mode
  Mode: (0700/drwx------)         Uid: (    0/    root)  Gid: (    0/   wheel)

Looks good no need to change.

Now from your local computer try to connect over SSH - you should get no password prompt:

$ ssh root@192.168.2.16
Last login: Tue Apr  9 12:20:52 2013 from 192.168.2.3
FreeBSD 9.1-RELEASE (GENERIC) #0 r243826: Tue Dec  4 06:55:39 UTC 2012

...andddd boom! we're in with no password prompt! good times :)