Having to type (and remember) numerous SSH passwords for my sites everyday always drove me mad. So-called 'public key authentication' is one way to end this struggle and work more effectively. I've read several HOWTOs covering this feature but had no time (or shall I say – was far too lazy) to try it myself. One day, finally, SSH got the better of me so I decided to dig into it. Here is what I've found.

Introduction

Let's start with the basics – believe me, it might save you a fair share of time hacking and solving problems. However, if you feel confident in different aspects of SSH, you may just skip to next section.

First and foremost, you have to know there are two versions of Secure Shell protocol: SSHv1 and SSHv2. Those are in fact different protocols which are not compatible with each other but some SSH servers and client may support both (while other will only support one version). Today there is no valid reason to use SSHv1 because it has some serious security issues so I'll assume we're talking SSHv2 from now on.

But there is more – you will find two popular implementations of SSH protocol: SSH (commercial, but free for educational and non-commercial use) and OpenSSH (open-source, free-as-in-speech). There are some not-so-subtle differences so it's important to know which versions are installed on both sides, remote and local. To find out, type 'ssh -V' (note the capital 'V') in local and remote shells:

          user@local:~# ssh -V
OpenSSH_3.8.1p1 Debian-8.sarge.3, OpenSSL 0.9.7d 17 Mar 2004

user@remote:~$ ssh -V
ssh: SSH Secure Shell 3.0.1 (non-commercial version) on i386-unknown-freebsd4.4

        

In this example, local host has OpenSSH installed, whereas remote is using non-commercial version of SSH.

You can get more information about the history of SSH and differences between two versions at OpenSSH.org and in Secure Shell FAQ.

Generating public/private key pairs

Public key authentication is based on asymmetric cryptography principles – this way a user is authenticated by a pair of keys: public, which is not secret, and private, known only to user. You generate your keys using ssh-keygen command. It is available both in SSH and OpenSSH although syntax might be slightly different.

But first we shall create directory structure on all local and remote hosts, paying close attention to permissions (for OpenSSH):

          user@local:~$ mdkir -p ~/.ssh
user@local:~$ chmod 700 ~/.ssh
user@local:~$ cd ~/.ssh
user@local:~/.ssh$ chmod 600 *

        

For SSH, you do the same but directory name shall be /.ssh2 instead of /.ssh.

Note: With recent versions of SSH and OpenSSH you can simply run ssh-keygen on every machine – it will create the directory and set all permissions.

Select a good secure (alpha-numeric, mixed-case, 8-character or longer) passphrase and we'll procede to generate the keys – just keep in mind that there is no indication (asterisks or whatever) when you're typing the passphrase. First in OpenSSH:

          user@local:~$ ssh-keygen -t dsa -b 1024
Generating public/private dsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_dsa):
Created directory '/home/user/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_dsa.
Your public key has been saved in /home/user/.ssh/id_dsa.pub.
The key fingerprint is:
bc:59:e9:7e:40:76:50:8f:28:04:1f:40:34:75:6c:e5 user@local

        

And now for SSH:

          user@local:~$ ssh-keygen -t dsa -b 1024
Generating 1024-bit dsa key pair
 6 Oo.oOo.oOoo.
Key generated.
1024-bit dsa, user@local, Sun Feb 27 2005 20:46:37 +0300
Passphrase :
Again      :
Private key saved to /home/user/.ssh2/id_dsa_1024_a
Public key saved to /home/user/.ssh2/id_dsa_1024_a.pub

        

Setting up public key authentication

Either way, both keys are now stored on your hard disk. Private key shall be kept, ahem, private and public key is going to be uploaded to all your remote servers to provide authentication.

Local OpenSSH, remote OpenSSH

If both local and remote machines are running OpenSSH the process is pretty straight-forward. Transfer your public key to remote host via FTP or SFTP and then merge its contents with remote host's ~/.ssh/authorized_keys2 file:

          user@local:~/.ssh$ scp id_dsa.pub user@remote:~/.ssh/local.pub
user@local:~/.ssh$ ssh user@remote
user@remote's password:
user@remote:~$ cd .ssh/
user@remote:~/.ssh$ cat local.pub >> authorized_keys2
user@remote:~/.ssh$ rm local.pub

        

Et voila! You can log out and re-login with a new passphrase instead of your old password:

          user@local:~$ ssh user@remote
Enter passphrase for key '/home/user/.ssh/id_dsa':
user@remote:~$

        

Local SSH, remote SSH

With SSH on both sides it isn't much harder. It's just that instead of pasting your entire public key into ~/.ssh/authorized_keys2 you mention it in ~/.ssh2/authorization file:

          user@local:~/.ssh2$ scp id_dsa_1024_a.pub user@remote:~/.ssh2/local.pub
user@local:~/.ssh2$ ssh user@remote
Password:
user@remote:~$ cd .ssh2/
user@remote:~/.ssh2$ echo "key local.pub" >> authorization

        

Log out and re-login – you shall now be prompted to enter your passphrase:

          user@local:~$ ssh user@remote
Passphrase for key "/home/user/.ssh2/id_dsa1024_a" with comment "1024-bit dsa, created by user@local Sun Feb 27 2005 20:46:37 +0300":
user@remote:~$

        

Local OpenSSH, remote SSH

Now here comes the tricky part – well, fear not, I've 'been there, done that' and have it all covered for you. So, since SSH and OpenSSH use a different pubkey format, we will have to convert our local key so it could be used by the remote side:

          user@local:~$ ssh-keygen -e -f ~/.ssh/id_dsa.pub > ~/.ssh/local_ssh.pub
user@local:~$ scp ~/.ssh/local_ssh.pub user@remote:~/.ssh2/local_ssh.pub
user@local:~$ ssh user@remote
Password:
user@remote:~$ echo "key local_ssh.pub" >> ~/.ssh2/authorization

        

This should be it – log out, log in and you are all set! Easy, eh?

Local SSH, remote OpenSSH

This setup is not much more different – you just have to do a conversion backwards. But first generate your keys, upload the pubkey to remote server and log in with your old password:

          user@local:~$ scp ~/.ssh2/id_dsa_1024_a.pub user@remote:~/.ssh/local_ssh.pub
user@local:~$ ssh user@remote
user's password:
user@remote:~$ ssh-keygen -i -f ~/.ssh/local_ssh.pub > ~/.ssh/local.pub
user@remote:~$ cat ~/.ssh/local.pub >> ~/.ssh/authorized_keys2
user@remote:~$ rm ~/.ssh/local*.pub

        

Nothing too scary, right? Again, you can log out, re-login and, if everything went right, will be prompted to type in your new passphrase.

What could possibly go wrong?

So you've done everything as described above and still can't login with your shiny new passphrase? Well, it happened to me as well. I've spent about 2 hours trying to get it right, tried everything but still couldn't get it work. Fortunately, the host which denied me to authenticate with pubkey had rather unrestrictive shell setup so I could view SSH server config files in /etc/ssh2/sshd2_config file. There were these lines:

          #AllowedAuthentications   hostbased,publickey,password
AllowedAuthentications   password

        

Apparently admins have quietly disabled public key authentication and all I tried was in vain! It made me kinda mad so I decided to write this article. At least I hope it will help you not to make the same mistake, hehe.