SSH keys

From ArchWiki
Revision as of 21:35, 18 December 2011 by Ntwk (talk | contribs) (Add section on using ssh_pam)
Jump to navigation Jump to search

This template has only maintenance purposes. For linking to local translations please use interlanguage links, see Help:i18n#Interlanguage links.

Local languages: Català – Dansk – English – Español – Esperanto – Hrvatski – Indonesia – Italiano – Lietuviškai – Magyar – Nederlands – Norsk Bokmål – Polski – Português – Slovenský – Česky – Ελληνικά – Български – Русский – Српски – Українська – עברית – العربية – ไทย – 日本語 – 正體中文 – 简体中文 – 한국어

External languages (all articles in these languages should be moved to the external wiki): Deutsch – Français – Română – Suomi – Svenska – Tiếng Việt – Türkçe – فارسی

SSH keys are an implementation of public-key cryptography. They solve the problem of brute-force password attacks by making them computationally impractical. Additionally, by using SSH keys, you can easily connect to a server, or multiple servers, without having to enter your password for each system.

It is possible to setup your keys without a passphrase, however that is unwise as if anyone gets hold of your key they can use it. This guide describes how to setup your system so that a passphrase is used to encrypt the private key and must be entered to use it.

Generating SSH Keys

First you must install the openssh package, available from the official repositories.

The keys can then be generated by running the ssh-keygen command as a user:

$ ssh-keygen -b 521 -t ecdsa -C"$(id -un)@$(hostname)-$(date --rfc-3339=date)"
Generating public/private ecdsa key pair.
Enter file in which to save the key (/home/mith/.ssh/id_ecdsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/mith/.ssh/id_ecdsa.
Your public key has been saved in /home/mith/.ssh/
The key fingerprint is:
3a:43:37:6d:e2:5b:97:e2:6f:e2:80:f9:23:97:70:0c mith@middleearth

It will prompt you for a location (which you should leave as the default), however the passphrase is the important bit! You should already be aware of the criteria that make a good passphrase.

So what did we just do? We generated a 521 bit long (-b 521) public/private ECDSA (-t ecdsa) key pair with an extended comment including the data (-C"$(id -un)"@$(hostname)-$(date --rfc-3339=date)) via the ssh-keygen command.

Note: These keys are used only to authenticate you, choosing stronger keys will not increase CPU load when transfering data over SSH.

Elliptic curve cryptography provides smaller key sizes and faster operations for equivalent estimated security. It was introduced as the preferred method for authentication in OpenSSH 5.7, see OpenSSH 5.7 Release Notes. ECDSA keys might not be compatible with systems that ship old versions of OpenSSH.

If you want to create a RSA (2048-4096 bit) or DSA (1024 bit) key pair instead of ECDSA just use -t rsa or -t dsa and do not forget to increase the key size, running ssh-keygen without (-b) will usually provide reasonable defaults.

Copying the public key to the remote server

Now you have generated the keys you need to copy the public key (*.pub) to the remote server. (The private key is kept on the machine from which you want to connect.)

Simple method

Note: If you are using Terminal on a Mac, you will need to add ssh-copy-id before proceeding.

If your key file is named you can simply do

$ ssh-copy-id

or if you need to use different user name

$ ssh-copy-id

If your key filename is different you will get an error saying "/usr/bin/ssh-copy-id: ERROR: No identities found". In this case you have to provide the location of the identity:

$ ssh-copy-id -i ~/.ssh/

If you need to specify a port, include it within the host declaration:

$ ssh-copy-id -i ~/.ssh/ '-p 221 username@host'

Traditional method

By default, for OpenSSH, the public key needs to be concatenated into ~/.ssh/authorized_keys.

$ scp ~/.ssh/

This copies the public key ( to your remote server via scp (note the : at the end of the server address). The file ends up in the home directory, but you can specify another path if you like.

Next up, on the remote server, you need to create the ~/.ssh directory if it does not exist and concatenate the key authorized_keys file:

$ ssh's password:
$ mkdir ~/.ssh
$ cat ~/ >> ~/.ssh/authorized_keys
$ rm ~/
$ chmod 600 ~/.ssh/authorized_keys

The last two commands remove the public key from the server (which is not needed now), and sets the correct permissions on the authorized_keys file.

If you now disconnect from the server, and attempt to reconnect, you should be asked for the passphrase of the key:

$ ssh
Enter passphrase for key '/home/mith/.ssh/id_ecdsa':

If you are unable to login with the key, double check the permissions on the authorized_keys file.

Also check the permissions on the ~/.ssh directory, which should have write permissions off for 'group' and 'other'. Run the following command to disable 'group' and 'other' write permissions for the ~/.ssh directory:

$ chmod go-w ~/.ssh

Disabling password logins

Setting up SSH keys is not enough to gain any security benefit. You must also disable password logins:

PasswordAuthentication no
ChallengeResponseAuthentication no

Remember key passphrases

Now you can login to your servers by using a key instead of a password, but how is this any easier, as you still need to enter the key passphrase? The answer is to use a SSH agent, a program which remembers the passphrases of your keys! There a number of different tools available, so have a read through and choose the one which seems best for you.


ssh-agent is the default agent included with OpenSSH.

$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-vEGjCM2147/agent.2147; export SSH_AUTH_SOCK;
echo Agent pid 2148;

When you run ssh-agent, it will print out what environment variables it would use. To make use of these variables, run the command through the eval command.

$ eval `ssh-agent`
Agent pid 2157

You can add this to /etc/profile so that it will be run whenever you open a session:

# echo 'eval `ssh-agent`' >> /etc/profile

Note the correct quotes: the outer ones are single quotes, where as the inner ones are backticks.

Now that the ssh-agent is running, we need to tell it that we have a private key and where that is.

$ ssh-add ~/.ssh/id_ecdsa
Enter passphrase for /home/user/.ssh/id_ecdsa:
Identity added: /home/user/.ssh/id_ecdsa (/home/user/.ssh/id_ecdsa)

When asked for the passphrase, enter it. Now you can login to your remote server without having to enter your password while your private key is password-protected.

The only downside is that a new instance of ssh-agent needs to be created for every new console (shell) you open, that means you have to run ssh-add every time again on each console. There is a workaround to that with a program or rather a script called keychain which is covered in the next section.

Using GnuPG Agent

The GnuPG agent, distributed with the gnupg2 package, has OpenSSH agent emulation. If you use GPG you might consider using its agent to take care of all of your keys. Otherwise you might like the PIN entry dialog it provides and its passphrase management, which is different from keychain.

To start using GPG agent for your SSH keys you should first start the gpg-agent with the --enable-ssh-support option. Example (don't forget to make the file executable):


# Start the GnuPG agent and enable OpenSSH agent emulation

if pgrep -u "${USER}" gpg-agent >/dev/null 2>&1; then
    eval `cat $gnupginf`
    eval `cut -d= -f1 $gnupginf | xargs echo export`
    eval `gpg-agent --enable-ssh-support --daemon`

Once gpg-agent is running you can use ssh-add to approve keys, just like you did with plain ssh-agent. The list of approved keys is stored in the ~/.gnupg/sshcontrol file. Once your key is approved you will get a PIN entry dialog every time your passphrase is needed. You can control passphrase caching in the ~/.gnupg/gpg-agent.conf file. The following example would have gpg-agent cache your keys for 3 hours:

 # Cache settings
 default-cache-ttl 10800
 default-cache-ttl-ssh 10800

Other useful settings for this file include the PIN entry program (GTK, QT or ncurses version), keyboard grabbing and so on...:

 # Environment file
 write-env-file /home/username/.gnupg/
 # Keyboard control
 # PIN entry program
 #pinentry-program /usr/bin/pinentry-curses
 #pinentry-program /usr/bin/pinentry-qt4
 pinentry-program /usr/bin/pinentry-gtk-2

Using keychain

Keychain manages one or more specified private keys. When initialized it will ask for the passphrase for the private key(s) and store it. That way your private key is password protected but you will not have to enter your password over and over again.

Install the keychain package, available from the official repositories.

Append the following command to your .bashrc, .bash_profile, or create /etc/profile.d/ as root and make it executable (e.g. chmod 755

eval `keychain --eval --agents ssh --nogui -Q -q id_dsa`

Adding the -q or --quiet flag to the keychain command will suppress the output to new sessions. Also note that the --agents flag is not strictly necessary, because keychain will build the list automatically based on the existence of ssh-agent or gpg-agent on the system. If you want greater security replace -Q with --clear but will be less convenient.

If necessary, replace ~/.ssh/id_dsa with the path to your private key. For those using a non-Bash compatible shell, see keychain --help or man keychain for details on other shells.

Finally, open a new shell or close your current shell and open it again. If it is your first run keychain will prompt you for the passphrase of the specified private key.

Alternate method

/usr/bin/keychain -Q -q --nogui ~/.ssh/id_dsa
[[ -f $HOME/.keychain/$HOSTNAME-sh ]] && source $HOME/.keychain/$HOSTNAME-sh

Using ssh-agent and x11-ssh-askpass

You need to start the ssh-agent everytime you start a new Xsession. The ssh-agent will be closed when the X session ends.

Install a variant of x11-ssh-askpass which will ask your passphrase everytime you open a new Xsession. Either use the original x11-ssh-askpass, go with ksshaskpass (depends on kdelibs) or with openssh-askpass (depends on qt), all available from the official repositories.

After installing these, closing your Xsession and relogging you will henceforth be asked your passphrase on Xsession init without any further work.

Using the pam_ssh Pluggable Authentication Module

The pam_ssh project exists to provide a Pluggable Authentication Module (PAM) for SSH private keys. This module can provide single sign-on behavior for your SSH connections. On login, your SSH private key passphrase can be entered in place of, or in addition to, your traditional system password. Once you have been authenticated, the pam_ssh module spawns ssh-agent to store your decrypted private key for the duration of the session.

To enable single sign-on behavior at the tty login prompt, install the unofficial pam_sshAUR package, available in the Arch User Repository.

Edit the /etc/pam.d/login file to add the lines highlighted in bold in the example below. The order in which these lines appear is significiant and can affect login behavior.

Warning: Misconfiguring PAM can leave the system in a state where all users become locked out. Before making any changes, you should have an understanding of how PAM configuration works as well as a backup means of accessing the PAM configuration files, such as an Arch Live CD, in case you become locked out and need to revert any changes. An IBM developerWorks article is available which explains PAM configuration in further detail.


In the above example, the login program uses pam_ssh to check the password against the user's SSH private key passphrase. If the password matches, the user is immediately granted access to the system. If the password does not match, it is handed to the pam_unix module which provides traditional password authentication by checking /etc/passwd. In this way, ssh_pam will be transparent to users without an SSH private key.

If you use a another means of logging in such as an X11 display manager, you must edit it's respective PAM configuration file located under /etc/pam.d/ in a similar fashion.

Further details on using pam_ssh are available in the pam_ssh man page.

Known issues with ssh_pam

Work on the pam_ssh project is infrequent and you should be aware of some of its limitations.

  • SSH keys employing the newer option of ECDSA (elliptic curve) cryptography do not appear to be supported by pam_ssh. You must use either RSA or DSA keys.
  • The ssh-agent process spawned by pam_ssh does not persist between user logins. If you like to keep a gnu screen session active between logins you may notice when reattaching to your screen session that it can no longer communicate with ssh-agent. This is due to the fact that the gnu screen environment and those of its children will still reference the instance of ssh-agent which existed when gnu screen was invoked but was subsequently killed in a previous logout. The alternative keychain method avoids this problem by keeping the ssh-agent process alive between logins.

GNOME Keyring

If you use the GNOME desktop, the GNOME Keyring tool can be used as an SSH agent. Visit the GNOME Keyring article.


If it appears that the SSH server is ignoring your keys, ensure that you have the proper permissions set on all relevant files.

For the local machine:

$ chmod 700 ~/
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/id_ecdsa

For the remote machine:

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

Failing this, run the sshd in debug mode and monitor the output while connecting:

# /usr/sbin/sshd -d

See also