Secure Shell (SSH)
Understanding the difference between public and private keys
I had a hard time understanding what to do with my private/public keys when I was learning SSH. I don't know why it was a difficult concept for me, but I have worked with enough other people who were confused in the same way I was that I think it's worth it to just spell out what to do with each key.
Private key (id_rsa)
Your private key (default name is id_rsa
) should NEVER leave the server it was created on, and should not be accessible to any other user (chmod 600
). There are exceptions to this, such as when uploading a keypair to an Azure or Hashicorp vault, or providing to a Docker container. But in general, when creating SSH tunnels between machines, the private key is meant to stay on the machine it was created on.
Public key (id_rsa.pub)
Your public key can be freely shared. You can repeatedly derive the same public key from a given private key, but a private key cannot be derived from a public key.
More on how it works
The math/algorithm involved allows your public key to encrypt data that only the private key it was derived from can decrypt. This is a one-way operation, meaning a message encrypted by a public key *cannot be decrypted by that same public key (or any other). Only the paired private key can decrypt messages encrypted by the public key.
Which is better, ed25519
or rsa
?
An SSH key can use one of 4 algorithms to generate a key: RSA
, ECDSA
, Ed25519
, and DSA
(but don't use DSA
!). The default is rsa 2048
, but it is recommended to use a higher key size like 4096
. The minimum is 1024
. RSA is the most compatible key type, it will work with just about every SSH server, but has a larger key size and the potential to be cracked by quantum computing if you use the standard 2048
key size.
It is a hotly debated topic which is more secure, ed25519
or rsa
. This StackExchange answer lays out a high level overview of why ed25519
may be better in theory, but after a certain point you are competing against "cannot now and will not for the foreseeable future be broken," which becomes a meaningless endeavor.
Short version: use rsa
with 4096
bytes.
Read more about SSH key algorithms on the Arch Linux wiki
The public key is what you can send to the remote you want to connect to. For example, to add an SSH key to a Github repository, you copy the contents of your id_rsa.pub
and paste them into Github, then tell your SSH client to use your id_rsa
private key. When you connect, Github compares your public and private key and allows you to connect if you use the private key the public was derived from.
Note
Your keys are never sent in full, instead an algorithm reassembles a key that will be identical when derived from the same public/private key. This type of encryption is known as asymettrical encryption.
When you're setting up an SSH connection to a remote host, you copy the public key using a command like ssh-copy-id -i .ssh/id_rsa.pub user@host
, and you can then use your private key to connect instead of a password with ssh -i .ssh/id_rsa user@host
.
Create an SSH key pair
You can create a keypair using the ssh-keygen
utility. This is installed with SSH (openssh-server
on Linux, see installation instructions for Windows), and is available cross-platform.
Note
You can run $ ssh-keygen --help
on any platform to see a list of available commands. --help
is not a valid flag, so you will see a warning unknown option -- -
, but the purpose of this is to show available commands.
If you run ssh-keygen
without any arguments, you will be guided through a series of prompts, after which 2 files will be created (assuming you chose the defaults): id_rsa
(your private key) and id_rsa.pub
(your public key).
You can also pass some parameters to automatically answer certain prompts:
- The
-f
parameter specifies the output file. This will skip the promptEnter file in which to save the key
$ ssh-keygen -f /path/to/<ssh_key_filename>
- When using
-f
, a private and public (.pub
) key will be created
- The
-t
parameter allows you to specify a key type- To generate an rsa key (the default key type):
$ ssh-keygen -t rsa
- Other types of key types are:
dsa
ecdsa
ecdsa-sk
ed25519
ed25519-sk
- To generate an rsa key (the default key type):
- The
-b
option allows you to specify the number of bits. For rsa keys, the minimum is1024
and the default is3072
. - You can set a stronger value like
4096
with:$ ssh-keygen -b 4096
Example ssh-keygen commands
Generate 4096-bit RSA key at ~/.ssh/example_key (and ~/.ssh/example_key.pub) | |
---|---|
Skip prompt for password (Linux) | |
---|---|
Generate an ed25519 key | |
---|---|
Install an SSH key on a remote machine for passwordless ssh login
You can (and should) use your SSH key to authenticate as a user on a remote system. There are 2 ways of adding keys for this type of authentication.
Edit your ~/.ssh/config file
To connect to a remote server using a key, you have to pass -i path/to/<key_name>
every time, i.e. ssh -i ~/.ssh/id_rsa
.
You can create/modify a ~/.ssh/config
file to set which user and key to use for various remote hosts. The ssh
command can use this file to configure connections with SSH keys so you don't have to specify $ ssh -i /path/to/key
each time you connect to a remote you've already copied a key to.
For example, after copying a public key to Github, add this to your ~/.ssh/config
:
Github SSH configuration | |
---|---|
Now, instead of connecting like ssh -i ~/.ssh/id_rsa git@github.com:<user>/<repo>
, you can just run ssh github.com
.
Note that your Host
and HostName
do not need to match. For example, say you have a machine named callisto
with an IP address of 192.168.1.12
, you can connect using ssh callisto
by adding this to your ~/.ssh/config
:
Method 1: Using ssh-copy-id
You can copy your public key to a remote using the ssh-copy-id
utility.
Add an SSH key for user 'test' on host 'example' | |
---|---|
Method 2: Manual method
You can also manually copy your public keyfile (.pub
) to a remote host and cat
the contents into ~/.ssh/authorized_keys
. The most straightforward way of accomplishing this is to use scp
to copy the keyfile to your remote host, typing the password to authenticate, then following up by logging in directly with ssh
.
Instructions:
- Copy your
.pub
keyfile$ scp /path/on/local/to/id_rsa.pub <remote-user>@example.com:/home/<remote-user>
- SSH into the remote
$ ssh <remote-user>@example.com
- You will need to type the user's password this time, but once the key is added you can simply use
$ ssh example.com
- Make sure you configure a
~/.ssh/config
file, using the instruction in the note in "Install an SSH key on a Remote Machine for passwordless login"
- Move the
.pub
keyfile from the user's home into.ssh
- If the
.ssh
directory does not exist, create it withmkdir .ssh
$ mv id_rsa.pub .ssh
- If the
- Change directory to
.ssh
andcat
the contents ofid_rsa.pub
intoauthorized_keys
$ cd .ssh && cat id_rsa.pub authorized_keys
- Remove the
id_rsa.pub
key. Now that it's inauthorized_keys
, you don't need the keyfile on the remote machine anymore.
~/.ssh chmod permissions
It is crucial your chmod
permissions are set properly on the ~/.ssh
directory. Invalid permissions will lead to errors when trying to ssh
into remote machines.
Check the table below for the chmod
values you should use. To set a value (for example on the .ssh
directory itself and the keypair):
Dir/File | Man Page | Recommended Permission | Mandatory Permission |
---|---|---|---|
~/.ssh/ |
There is no general requirement to keep the entire contents of this directory secret, but the recommended permissions are read/write/execute for the user, and not accessible by others. | 700 | |
~/.ssh/authorized_keys |
This file is not highly sensitive, but the recommended permissions are read/write for the user, and not accessible by others| | 600 | |
~/.ssh/config |
Because of the potential for abuse, this file must have strict permissions: read/write for the user, and not writable by others | 600 | |
~/.ssh/identity ~/.ssh/id_dsa ~/.ssh/id_rsa |
These files contain sensitive data and should be readable by the user but not accessible by others (read/write/execute) | 600 | |
~/.ssh/identity.pub ~/.ssh/id_dsa.pub ~/.ssh/id_rsa.pub |
Contains the public key for authentication. These files are not sensitive and can (but need not) be readable by anyone. | 644 |
(table data source: Superuser.com answer)