1. Introduction

Public key authentication is an alternative method of identifying ourselves to a remote server. Unlike regular passwords, public key authentication uses cryptographic key pairs for validation.

Using strong passwords may help prevent brute force attacks, but public-key authentication provides cryptographic strength. Moreover, it allows us to have automated password-less logins. This increases the trust between two Linux servers for easier file transfers.

In this tutorial, we’ll cover how to set up public-key authentication on Linux systems.

2. Creating SSH Key Pair

We first need to generate an SSH key pair on our local computer to configure SSH key authentication.  To achieve this, we can use a special utility called ssh-keygen, included with the standard OpenSSH suite of tools.

By default, ssh-keygen creates a 3072-bit RSA key pair. Let’s use this command to generate an SSH key pair:

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

Using the -b option, we can also specify a length in bytes for the key pair that will be generated:

$ ssh-keygen -b 4096

We’ll be prompted to select a save location for the created key pair. The keys are stored in the ~/.ssh directory by default. It’s advisable to use the default location at this stage because it allows the SSH client to automatically find our SSH keys.

We can press ENTER to stick with the default location or type in a different location to save the key pair.

If an SSH key pair was previously generated, we’ll get a prompt to overwrite the existing key:

/home/user/.ssh/id_rsa already exists.
Overwrite (y/n)?

Selecting yes will overwrite the existing key and we won’t be able to use it again. This is an irreversible process.

Next, we’ll  be prompted to enter a passphrase to encrypt the private key on our local computer:

Created directory '/home/user/.ssh'.
Enter passphrase (empty for no passphrase):

A passphrase serves as an extra layer of security to secure the private key generated. We need to enter it every time we use the private key.

Entering a passphrase is optional, but recommended for a secure system. We get this output on successful key pair creation:

Your identification has been saved in /home/user/.ssh/id_rsa
Your public key has been saved in /home/user/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:f6sdCUZLKUm61/Mbv7DZh+NNR4Dn7oA+vnb4JB82qyc user@user-PC
The key's randomart image is:
+---[RSA 3072]----+
|        .        |
|       o . . .   |
|      . o + . o  |
|       . = . o . |
|      . S *   . .|
|       . o = o . |
|          +.& ..o|
|         .EBo^ooo|
|         o*XX.*+.|

This creates two files:

  • id_rsa: represents the private key
  • id_rsa.pub: represents the public key

We now have a public key and a private key we can use for authentication. The next step is copying the public key to a remote server.

3. Copying the Public Key to a Remote Server

There are multiple methods we can use to upload the public key to a remote SSH server:

  • using ssh-copy-id
  • using SSH
  • manually copying it

Let’s explore each of the methods closely.

3.1. Using ssh-copy-id

ssh-copy-id is a utility to copy the public key to a remote SSH server. It’s the easiest and most recommended method for copying a public key.

It’s included in the OpenSSH packages in most Linux distributions, so we don’t need to install it. We must have password-based authentication enabled to use this method.

It requires us to specify an IP address for the remote host, and the user account with password-based authentication enabled:

$ ssh-copy-id user@remote_host_ip_address
The authenticity of host 'xxx.x.xxx.x (xxx.x.xxx.x)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)?

Getting this message is normal because our local computer doesn’t yet recognize the remote server. Let’s type in yes, then hit ENTER to continue.

The utility will proceed to scan for the public key we generated earlier. Once it locates the key, it’ll prompt us to enter the password on the remote server.

When we enter the correct password, the utility will connect to the remote server and copy over our public key. The key is copied to the ~/.ssh directory on the remote server, in a file name authorized_keys.

We should get this output:

Number of key(s) added: 1

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

3.2. Using SSH

We can also upload the public key through the conventional SSH method. To do this, we need to output the contents of our public key and pipe it through SSH to the remote server.

Let’s use the >> redirection operator to append the content instead of overwriting any existing keys:

$ cat ~/.ssh/id_rsa.pub | ssh user@remote_host_ip_address "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
The authenticity of host 'xxx.x.xxx.x (xxx.x.xxx.x)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)?

Again, getting this message is normal because our local computer doesn’t yet recognize the remote server. We just need to type in yes, then hit ENTER to continue.

Next, we’ll be prompted to enter the password on the remote server. On authorization, the public key on our local computer will be copied at the end of the authorized_key file.

3.3. Manually Copying the Public Key

We can also copy the public key manually in cases when we don’t have password-based access to the remote server. To do this, we’ll need to manually copy the content in our public key, and paste it to the remote server.

Let’s use cat to display our public key:

$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAA...truncated...AGvaQ== user@host_ip_address

Next, we need to copy the key from the terminal and then access our remote server by whatever means available to us. For example, we could use a web-based console or dashboard.

Then, we use the mkdir command to create the ~/.ssh directory if it doesn’t already exist:

$ mkdir -p ~/.ssh

Or, we just create the folder manually in cases where we don’t have access to a web-based console.

Finally, let’s create or modify the authorized_keys directory and paste the public key we copied:

$ echo public_key >> ~/.ssh/authorized_keys

This appends the contents of our public key to the authorized_keys file without overwriting it.

4. Testing Authentication Through SSH Keys

Once we have the public key copied and pasted to our remote server, we should be able to successfully log in without a password. Let’s use this command to test our keys:

$ ssh user@remote_ip_address

We’ll be prompted to enter the passphrase if we created it during key pair generation. Otherwise, we’ll be immediately logged in to the remote server and can access its files and folders.

Here’s a sample output:

Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-154-generic x86_64)


Last login: Thu Jan  6 10:48:29 2022 from xxx.xxx.xx.xxx

Once logged in, we can see a lot of important information about our remote server including the number of currently logged-in users, CPU usage stats, and many more.

5. Disabling Password Authentication on Remote Server

It’s critical for us to disable password-based authentication that’s still active to protect our remote server against brute-force attacks.

We need to make sure that we have an SSH key authentication setup with the root user or any other available user with sudo privileges. This is important to ensure that we’ll still be able to gain administrative access.

First, let’s log in to our remote server through SSH and then open the SSH configuration file through nano:

$ sudo nano /etc/ssh/sshd_config

Once in the file, let’s search for a line that reads “PasswordAuthentication”. It may be uncommented depending on our system, but we can enable it by removing the “#” sign at the beginning, then set its value to “no”:

PasswordAuthentication no

Finally, let’s save and close the file. To implement the change we just made, we’ll need to restart the ssh service:

$ sudo systemctl restart ssh

Alternatively, we can use this command:

sudo kill -HUP `cat /var/run/sshd.pid`

One more method is to use this command:

sudo kill -HUP $(cat /var/run/sshd.pid)

This disables password authentication while logging in through SSH.

6. Additional Information

Let’s look at some additional information on public-key authentication that is useful.

6.1. Backing up an Existing SSH Key Pair

We can copy the files to an existing backup server, an external media storage device, or even print the key pair on a piece of paper if we prefer non-digital methods.

6.2. Add or Replace the Passphrase for an Existing Key

To add or modify the existing passphrase on the default SSH private key, we’ll need to use the ssh-keygen command:

$ ssh-keygen -p

To specify a different filename, we can pass it using the -f flag:

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

6.3. Protection of SSH Keys

To protect our SSH keys we need to do the following:

  • restrict all privileges of the account
  • use a strong passphrase. It can be a sentence with numbers and special characters
  • avoid sharing the private keys anywhere online or on unsecured servers

7. Conclusion

In this article, we’ve covered the important steps required to set up public-key authentication between a local computer and a remote server. We’ve also looked at how we can disable the traditional password-based authentication to protect our remote server from brute-force attacks.

Finally, we’ve covered some benefits of using public-key authentication and useful tips we could use when interacting with SSH key pairs.