AICT Home > Research Support Group > Linux Cluster > PKA > PKA OpenSSH


Public Key Authentication With OpenSSH

These instructions apply to the OpenSSH client on Linux, Macintosh OS X, and Windows (under Cygwin). If you encounter any problems, please send a note to research.support@ualberta.ca.

Contents


Preliminary Setup

Setting up public key authentication to access a particular remote host is a one-time procedure comprising three steps.

In general, your id (account name) on your local desktop and on the remote host will be different. In the examples on this page, they are the same.

Step 1

Generate a public/private key pair on your local desktop. Use the ssh-keygen command as illustrated below. The key-type flag -t is mandatory, accepting either "rsa" or "dsa" as an argument. In the example, the -f option is also used to override the default name and location for the resulting private-key file. See man ssh-keygen for additional details.

When prompted for a passphrase, your CCID password makes a good choice since you have probably already committed it to memory and it has withstood password cracking tests. However, the OpenSSH documentation recommends an actual phrase of 10 to 30 characters with word breaks, mixed case, numbers, and non-alphanumeric characters, for example, "I've BeeN studYing@Univ 4 2 ears." Instead of trying to create a good passphrase on your own, seriously consider the recommendations posted on www.diceware.com.

Under no circumstances should you enter an empty passphrase.
$ ssh-keygen -t dsa -f ./mykey
Generating public/private dsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in ./mykey.
Your public key has been saved in ./mykey.pub.
The key fingerprint is:
c3:0f:73:8c:4c:7b:2a:7b:7c:23:d5:fc:a4:c8:fe:72 esumbar@puke
$ ls -l
total 2
-rw-------  1 esumbar None 736 Dec  8 09:32 mykey
-rw-r--r--  1 esumbar None 602 Dec  8 09:32 mykey.pub

The command produces two text files: mykey contains the private key, and mykey.pub contains the public key. The private key must be kept secret. Accordingly, access to mykey is restricted to the file owner and its contents are encrypted using the passphrase.

If you share your computer and you do not have a separate account (id) with private disk space, do not use public key authentication. If in doubt, do not use public key authentication.

You can recreate mykey.pub from mykey with

ssh-keygen -y -f ./mykey > mykey.pub

You can not recreate mykey from mykey.pub however.

Step 2

Install the public key on the remote host to which you want to connect. Do this by copying mykey.pub to your home directory on the remote host and appending its contents to the authorized_keys file in the .ssh directory.

$ scp mykey.pub esumbar@cluster.srv.ualberta.ca:
esumbar@cluster.srv.ualberta.ca's password: 
mykey.pub                                     100%  602     0.6KB/s   00:00    
$ ssh -x -l esumbar cluster.srv.ualberta.ca
esumbar@cluster.srv.ualberta.ca's password: 
Last login: Fri Dec  8 13:00:55 2006 from puke.aict.ualberta.ca

  Documentation:
    http://www.ualberta.ca/AICT/RESEARCH/LinuxClusters/index.html

$ ls -l
total 4
lrwxrwxrwx  1 esumbar uofa  14 Jun 27 10:37 afshome -> /u/e/s/esumbar
-rw-r--r--  1 esumbar uofa 602 Dec  8 13:10 mykey.pub
$ cat mykey.pub >> .ssh/authorized_keys
$ rm -f mykey.pub 
$ logout
Connection to cluster.srv.ualberta.ca closed.

You can install the same public key on any number of additional remote hosts.

The private key is not installed on any remote host.

Step 3

Verify that public key authentication works. Basic public key authentication is invoked by using the -i flag with the ssh or scp commands, specifying mykey as the flag's argument.

$ ssh -x -l esumbar -i ./mykey cluster.srv.ualberta.ca
Enter passphrase for key './mykey': 
Last login: Fri Dec  8 14:12:23 2006 from puke.aict.ualberta.ca

  Documentation:
    http://www.ualberta.ca/AICT/RESEARCH/LinuxClusters/index.html

$ pwd 
/home/esumbar
$ ls -l
total 0
lrwxrwxrwx  1 esumbar uofa 14 Jun 27 10:37 afshome -> /u/e/s/esumbar
$ logout
Connection to cluster.srv.ualberta.ca closed.

Supplying the passphrase when prompted decrypts the private key on the fly for use in the authentication process. If you see a password prompt instead of a passphrase prompt, the administrators of the remote host may have disallowed public key authentication. Some sites take this step to prevent the use of unencrypted private keys (generated with a null passphrase), which pose a security threat.

Typical Usage

At first glance, basic public key authentication offers no advantages since a passphrase is always required. However, single signon can be achieved by setting up ssh-agent to assist in the authentication process (see man ssh-agent).

To set up ssh-agent manually, start the program by executing the command as follows.

$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-uuOPSl1188/agent.1188; export SSH_AUTH_SOCK;
SSH_AGENT_PID=3196; export SSH_AGENT_PID;
echo Agent pid 3196;

Each of the three output lines is formatted as a command in the syntax of your current shell (bash, in this case). They reference two environment variables SSH_AUTH_SOCK (Unix domain socket) and SSH_AGENT_PID (agent process id). Add these to your current shell environment by executing the commands as they appear.

$ SSH_AUTH_SOCK=/tmp/ssh-uuOPSl1188/agent.1188; export SSH_AUTH_SOCK;
$ SSH_AGENT_PID=3196; export SSH_AGENT_PID;
$ echo Agent pid 3196;
Agent pid 3196

Then, use the ssh-add program to add the private key to the ssh-agent.

$ ssh-add ./mykey 
Enter passphrase for ./mykey: 
Identity added: ./mykey (./mykey)

The passphrase is requested so that the ssh-agent can store the unencrypted private key in memory, ready to respond to an authentication request. Subsequent ssh and scp commands do not need to specify the private-key file nor will you be prompted for a passphrase.

$ scp source.f esumbar@cluster.srv.ualberta.ca:
source.f                                      100%   32KB  32.2KB/s   00:00    
$ ssh -x -l esumbar cluster.srv.ualberta.ca
Last login: Mon Dec 11 13:05:57 2006 from puke.aict.ualberta.ca

  Documentation:
    http://www.ualberta.ca/AICT/RESEARCH/LinuxClusters/index.html

$ ls -l
total 36
lrwxrwxrwx  1 esumbar uofa    14 Jun 27 10:37 afshome -> /u/e/s/esumbar
-rw-r--r--  1 esumbar uofa 32938 Dec 11 13:06 source.f
$ logout
Connection to cluster.srv.ualberta.ca closed.

The ssh-agent process is available in any terminal that correctly defines SSH_AUTH_SOCK and SSH_AGENT_PID in its environment. To facilitate this, the output from the ssh-agent command can be saved in a file, $HOME/.sshrc for instance, and sourced when required.

Manually configuring ssh-agent can become tedious. As an alternative, use the following ssh and scp wrapper scripts. They handle all the details of working with ssh-agent in any terminal.

#!/bin/bash
#
# File: myssh
#
# ssh wrapper script
#
sshcomm=ssh
sshsource=myssh.source
source $(dirname $0)/$sshsource
#!/bin/bash
#
# File: myscp
#
# scp wrapper script
#
sshcomm=scp
sshsource=myssh.source
source $(dirname $0)/$sshsource
#
# File: myssh.source
#
# Common code for ssh and scp wrapper scripts
#
privkeyfile=$HOME/mykey
sshenvfile=$HOME/.sshrc

[[ -r "$sshenvfile"  ]] && source $sshenvfile >/dev/null 2>&1

ssh-add -l >/dev/null 2>&1 ; retval=$?

if [ $retval -eq 0 ]; then
    $sshcomm $@
elif [ $retval -eq 1 ]; then
    if [ ! -r "$privkeyfile" ]; then
        echo "$(basename $0): key file not found: $privkeyfile"
        exit 1
    fi
    ssh-add $privkeyfile
    $sshcomm $@
elif [ $retval -eq 2 ]; then
    if [ ! -r "$privkeyfile" ]; then
        echo "$(basename $0): key file not found: $privkeyfile"
        exit 1
    fi
    for agent in $(/bin/ps -ef | grep ssh-agent | awk '{print $2}'); do
        kill $agent
    done
    ssh-agent -s >| $sshenvfile
    source $sshenvfile >/dev/null 2>&1
    ssh-add $privkeyfile
    $sshcomm $@
else
    echo "$(basename $0): ssh-add: unknown exit status: $retval"
    exit $retval
fi

For convenience, place these scripts in a directory on your PATH. Locate the private-key file somewhere accessible only to you and update the privkeyfile variable in myssh.source.

Use the scripts like you would the actual commands. You will be prompted for the passphrase only once.

$ myscp source.f esumbar@cluster.srv.ualberta.ca:
Enter passphrase for /home/esumbar/mykey: 
Identity added: /home/esumbar/mykey (/home/esumbar/mykey)
source.f                                      100%   32KB  32.2KB/s   00:00    
$ myssh -x esumbar@cluster.srv.ualberta.ca
Last login: Tue Dec 12 13:56:51 2006 from puke.aict.ualberta.ca

  Documentation:
    http://www.ualberta.ca/AICT/RESEARCH/LinuxClusters/index.html

$ ls -l
total 36
lrwxrwxrwx  1 esumbar uofa    14 Jun 27 10:37 afshome -> /u/e/s/esumbar
-rw-r--r--  1 esumbar uofa 32938 Dec 12 14:00 source.f
$ rm -f source.f 
$ logout
Connection to cluster.srv.ualberta.ca closed.

$ myssh -x esumbar@cluster.srv.ualberta.ca
Last login: Tue Dec 12 14:00:59 2006 from puke.aict.ualberta.ca

  Documentation:
    http://www.ualberta.ca/AICT/RESEARCH/LinuxClusters/index.html

$ ls -l
total 0
lrwxrwxrwx  1 esumbar uofa 14 Jun 27 10:37 afshome -> /u/e/s/esumbar
$ logout
Connection to cluster.srv.ualberta.ca closed.

Wrapper scripts myssh and myscp work with either console terminals or X terminals. Whereas each console terminal starts with an unrelated environment, X terminals inherit their environment through the process hierarchy from the window manager. Consequently, the environment variables associated with ssh-agent can be propagated to all subsequent X terminals by starting ssh-agent and X in the same shell as follows.

#!/bin/bash
#
# File: mystartx
#
# startx wrapper script
#
privkeyfile=$HOME/mykey

if [ ! -r "$privkeyfile" ]; then
    echo "$(basename $0): key file not found: $privkeyfile"
    exit 1
fi

eval $(ssh-agent)
ssh-add $privkeyfile
startx
ssh-agent -k

Execute the mystartx wrapper script to start X. It will prompt you for the passphrase before X and the first X terminal is started. Thereafter, you can use the ssh and scp commands without having to specify a private-key file or answering a passphrase prompt.

Security Considerations

In essence, the private key that you generate represents your "identity" in the public key authentication method. Therefore, as already stated, the private key should be stored in a file that only you can access, and the key should be encryped with a passphrase for added security. If this is not possible, do not use public key authentication.

When using ssh-agent, the private-key file needs to be available only for the time it takes to add the key. As such, you can enhance security by storing the key on personal removeable media such as a USB memory stick. Make it available only when necessary. If you use the wrapper scripts, insert the media before the first login or file transfer, then remove it after answering the passphrase prompt. When not in use, keep the removeable media in a safe place. Some USB memory sticks are designed as key fobs for example.

It is unwise to enable agent forwarding (-A option). If the remote host is insecure, the forwarded agent could potentially be used by unauthorized persons. Typically, this is off by default, or use the -a option to be sure.

If you suspect that your private key has been comprimised, immediately remove the associated public key from the authorized_keys file on all of your remote hosts or have the system administrators do it for you. Before generating a new key, identify the source of the comprimise and adopt preventive measures to minimize your vulnerability in the future. If this is not possible, do not use public key authentication.

You can also limit the impact of a lost or stolen private key by restricting public key authentication to specified hosts. For example, prepending from="*.ualberta.ca" to a public key in the authorized_keys file on a remote host will permit computers only from the ualberta.ca domain to connect to this remote host with this public key. See the AUTHORIZED_KEYS FILE FORMAT section in man sshd for additional details.

As an additional precaution, use your current private key for only a limited time, say six months to one year. Periodically delete it and purge all your remote authorized_keys files, then generate a new private key and distribute the new public key. However, juggling multiple private keys and numerous remote hosts can get complicated. Keep it simple by maintaining only one private key for public key authentication.

Finally, remember that your password is still valid and password authentication is still available. However, with public key authentication set up, you can "randomize" your password if you suspect it to be weak and then forget about it. If you ever need to use a password in the future, a system administrator can always reset it.


© 2006 University of Alberta