How to generate and manage ssh keys on Linux

The SSH (Secure Shell) protocol provides the ability to perform encrypted communications over computer networks. Typical operations we can perform using the protocol are remote login and remote command executions. When we login on a remote computer (with the ssh utility, for example), we are requested to provide the password for the account we are using to login. For enhanced security we can decide to use SSH keys as credentials: once the SSH server is configured appropriately, to be able to login we must know something (the password) but also possess something (a key). In this tutorial we see how to generate, manage and use SSH keys.

In this tutorial you will learn:

  • What is a SSH keypair
  • What is the difference between a private and public ssh key and what is their role
  • How to generate SSH keypairs
  • How to modify the password of a private ssh key
  • How to transfer public keys to an ssh server

How to generate and manage ssh keys on Linux

How to generate and manage ssh keys on Linux

Software requirements and conventions used

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Distribution independent
Software OpenSSH utilities
Other No other requirements needed
Conventions # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux-commands to be executed as a regular non-privileged user

How SSH keypairs work

SSH keys are used as login credentials, often in place of simple clear text passwords. They work in pairs: we always have a public and a private key. The private key must remain on the local computer which acts as the client: it is used to decrypt information and it must never be shared. The public key, on the other hand, is used to encrypt data and must be copied on the remote server (its content is copied in the ~/.ssh/authorized_keys file in the $HOME directory of the user we login as on the server – we will see how to perform such operation in the course of this tutorial).

The ability to use ssh-keys as login credentials must be allowed server-side by the system administrator, by setting the PubkeyAuthentication option to yes in the /etc/ssh/sshd.config file. Both clear text passwords and public keys can be allowed as authentication methods at the same time, or, for example, one could decide to allow access only via public keys.

The tools and utilities we will use in this tutorial are installed by default in all the major Linux distributions, as part of the OpenSSH software suite.



Generating an SSH keypair

Generating an SSH keypair is a very simple operation: all we have to do is to use the ssh-keygen utility. The easiest way to perform the operation is just to invoke the command without any argument or option:

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/egdoc/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/egdoc/.ssh/id_rsa
Your public key has been saved in /home/egdoc/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:JRcJ3a3eQ4wO/lX4vaCcPckyeayu0ai80EMcdA7m5Dk egdoc@fingolfin
The key's randomart image is:
+---[RSA 3072]----+
|       =.+.o .   |
|      * = o.. .  |
|       E..o  + . |
|      . o+. o + .|
|       oS. + o o.|
|      o   + o.+ o|
|     . o o.oB.o..|
|      o o .B.B . |
|       +..oo= .  |
+----[SHA256]-----+

Let’s analyze what happens when invoke the command this way. The first thing we are asked for is where the generated keys should be stored: by default the generated private key is called id_rsa, and the name of the public one is obtained by adding the .pub extensions to it. Both of them, by default, are created inside the ~/.ssh directory; we are free, however, to provide alternative names and location.

The second thing we are asked for, is to provide a passphrase: it is used to secure the private key. We can either enter passphrase or just press enter and leave the field blank. In the first case, we will be prompted to provide the password we used each time we attempt to use the key. If we leave the field empty, instead, we can achieve a passwordless login on the server: this could represent a security risk, since everyone with access to the key could easily impersonate us; on the other hand this setup is usually used to perform unattended operations via ssh, as, for example scheduled backups.

After we provide a password the keys are generated and the key fingerprint and randomart image are displayed on screen. It’s done! At this point we have our ssh keypair in place.

Change key type and bit size

By default, when no specific options are passed to the ssh-keygen command, an rsa key pair is generated with a size of 3072 bits. To use an alternative key type, we must use the -t option of ssh-keygen and provide the type of key we want to use as its argument. The available key types are:

  • dsa
  • ecdsa
  • ecdsa-sk
  • ed25519
  • ed25519-sk
  • rsa

Every key type has its default in term of bit size. DSA keys, for example must be of exactly 1024 bits, while for ECDSA keys, as stated in the manual:

-b flag determines the key length by selecting from one of the elliptic curve sizes: 256, 384 or 521 bits.

Other key types like ECDSA-SK, Ed25519 and Ed25519-SK have a fixed length which cannot be changed.

Where possible, to change the bit size which should be used for the key generation, we can use the -b option of the ssh-keygen utility, and pass the number of bit size as its argument. Let’s say we want to generate an RSA key of 4096 bits (instead of the default 3072); we would run:

$ ssh-keygen -b 4096


Specify the path of the keys non-interactively

As we saw in the example, when not otherwise specified the default name used for the generated keys will be id_rsa. Of course we can change it interactively, when requested, but what if we want to provide it beforehand? Well, in that case we can invoke ssh-keygen together with the -f option, and pass the filename to use for the key as its argument. Suppose we want our keys to be stored as ~/.ssh/linuxconfig_rsa (private) and ~/.ssh/linuxconfig_rsa.pub (public);
we would run:

$ ssh-keygen -f  ~/.ssh/linuxconfig_rsa

Changing a private key password

As we already saw, when we create an ssh keypair we have the chance to protect the private key with a password we can provide when requested. What if we want to modify this password sometime in the future? How can we change the password of a private key?

It’s easy! All we have to do is to invoke the ssh-keygen utility with the -p option. When we invoke the command with this option, first we will be prompted to provide the path of the private key we want to change, then we will be asked to provide the old passphrase used for it (if any), and finally we will be asked to enter the new passphrase twice:

$ ssh-keygen -p
Enter file in which the key is (/home/egdoc/.ssh/id_rsa):
Enter old passphrase:
Key has comment ''
Enter new passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved with the new passphrase.

The default key that will be selected for password change is ~/.ssh/id_rsa, just like happens at creation time. If we want to provide the path of a private key directly and non-interactively, we can, again, use the -f option, and pass
the key path as argument, for example:

$ ssh-keygen -p -f ~/.ssh/id_rsa


Loading the public key on the server

To be able to use the SSH keys we generated as authentication method on a remote server, we need to upload our public key on it. The OpenSSH set of tools provides an utility which is specifically designed to perform this task:
ssh-copy-id. Here is an example of its usage. To copy the default ssh key id_rsa.pub on a remote server, we would run:

$ ssh-copy-id -i ~/.ssh/id_rsa.pub egdoc@192.168.0.39

What we did in the example above is pretty simple. We invoked the ssh-copy-id utility with the -i option: this option let us specify the public key which should be used. We pass its path key as the option argument (the .pub suffix is added automatically if not present). The main argument we provided is, instead, the user we want to login as (optional) together with the IP address of the server.

The output of the command above will be something similar to the following:

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/egdoc/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
egdoc@192.168.0.39's password:

For the key to be installed on the ssh server, we should first provide the current password we are using to login. After we do it, if everything goes as expected, we will see the following response:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'egdoc@192.168.0.39'"
and check to make sure that only the key(s) you wanted were added.

If we are not sure about what keys would be copied on the remote server, we can launch ssh-copy-id with the -n option to perform a dry-run: the keys will not be installed on the server; instead the ones that would be copied will be reported onscreen.

The default port used by the ssh server is 22; sometimes the system administrator, however, could decide to change it, just to avoid the most generic brute force attacks. In such cases, four our ssh connection to work, we must use the -p (short for --port) option when invoking the ssh-copy-id command and pass the port that should be used for the connection as its argument. Supposing the port used is 15342, for example, we would run:

ssh-copy-id -i ~/.ssh/id_rsa.pub -p 15342 egdoc@192.168.0.39

Conclusions

In this tutorial we learned the basics of SSH keys: we saw that a key pair is also composed by a public and private key, what they are used for, and how they should be treated. We saw how to generate a keypair, what are the different type of keys we can use, and how we can specify their size in bits at the time of creation. We also saw how an ssh private key can be protected by a password, and how we can change it. Finally we learned how we can use the ssh-copy-id utility to copy a specified public key on the destination server.



Comments and Discussions
Linux Forum