Linux Login using SSH keys

Published 2012-10-23

Using SSH keys to login to a server provides a convenient alternative to typing your password each time. SSH key-based authentication also allows scripts to run unattended without leaving your password in plain text. And it does your laundry. Well, alright, maybe not that last one.

Once you have ssh auth setup, you can use commands like ssh, scp, sftp, and rsync without having to enter a password. Handy!

SSH Keys in 5 Minutes or Less

If you're lazy or adventurous and prefer to skip the details, you can follow these instructions:

Generate a key if you don't have one already, pressing enter at all the prompts:

$ ssh-keygen

Set permissions on your private key and upload your public key to the server:

$ chmod 400 ~/.ssh/id_rsa*
$ scp ~/.ssh/id_rsa.pub username@example.com:~/id_rsa.pub

Login to the remote server to create the .ssh folder, create the authorized keys file and set permissions:

$ ssh username@example.com
username@example.com's password: <enter password>
$ mkdir ~/.ssh/
$ cat id_rsa.pub >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys
$ rm id_rsa.pub
$ exit

Now when you login via ssh, it should use your ssh key instead of prompting you for a password.

SSH Keys in Slightly More than 5 Minutes

If you got stuck in the \<5 minutes version, would like to know a bit more about what just happened (or what you're about to do), or want to learn about some advanced use cases, read on.

Public vs. Private Keys

SSH relies on a mechanism called public key cryptography, which consists of a matching private key and public key, called a "key pair". For any key pair, anyone with the public key can "sign" or encrypt a message, but only the person with the private key can decrypt it.

If I sign a message with your public key and you are able to decrypt it, then I know you hold the matching private key, which asserts that you are the person who gave me the public key at an earlier date. Provided I assume that you are the only person holding your private key, I can establish your identity without ever seeing your private key, which remains known only to you.

This is exactly what happens when you login using an SSH key. When your SSH client opens a connection to a server, the SSH server signs a message with your public key. The SSH client on your computer uses your private key to decrypt it, and responds to the server. The server verifies that the message was decrypted correctly and allows you to login.

When you connect, the ssh server also sends you a public key which your ssh client uses to sign messages sent to the server, allowing for bi-directional encrypted communication. Since you know the server's public key, you can establish the server's identity, which helps prevent man-in-the-middle attacks if the intermediary network is compromised.

If you only remember one thing about key pairs, remember this: don't share your private key. Whenever you copy your key somewhere you should copy your public key, not your private key.

Generating a Key Pair

Note: If you're using git you may have a key pair already. You can use your existing key pair for other servers (or if you have reservations about that, see the "Managing Multiple Keys" section below).

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

By default, the generated key will be created in your home directory under ~/.ssh/. The private key is named id_rsa and the public key is id_rsa.pub. If you don't have a key pair yet, just press enter to accept the default.

Next, ssh-keygen will prompt you for a passphrase. If you enter a passphrase you will need to enter it each time your key is used, or use an ssh agent like pageant. For convenience I recommend leaving the the passphrase blank.

Once you've entered (or skipped entering) your passphrase, ssh-keygen will output a signature and a randomart graphic.

As a final step, you'll need to change the permissions on your keyfiles so only you can read them:

$ chmod 400 ~/.ssh/id_rsa*

If you cat your keys you'll see something like this:

Private Key

$ cat ~/.ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAvKIl+MRGBX7+r0n5rfeWU4MypoWZEGX9JOtnfKSQ2HbolEUG
doypY5LQe3SE7Qxx9//Ls0EZ9yo926fQyAK5aBprykkSYA9MUx78a8LuNdPBLrw1
                             [ snip ]
wcWjQW9avTxJwGSq+o11KrxBHozpuApewkk2nqRPON/IJm118LS7/fv6u4tdNYrW
7xQQEqOud8ro1fMC1EBxv88h+qjH39gg2ej9vBxfIdW2Zec80Je1uRU=
-----END RSA PRIVATE KEY-----

Public Key

$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8oiX4xEYFfv6v...fLNCHvQBwGUFTa2v cbednarski@ubuntu-1204

You'll notice that the private key is arranged into a series of neat 64-column lines, while the public key is all crammed into one line (and wraps in your terminal). This whitespace is important. If you add or remove line breaks the keys won't work, so copy-paste carefully.

Installing the Public Key

Now that you have your key pair you'll need to copy the public key to the server and add it to the authorized keys file for the user you want to login as.

$ scp ~/.ssh/id_rsa.pub username@example.com:~/

Once the key is uploaded you'll need to login to the server to create the .ssh folder and add your public key to the authorized_keys file on the remote host.

$ ssh username@example.com
username@example.com's password: <enter password>
$ mkdir ~/.ssh/
$ cat id_rsa.pub >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys
$ rm id_rsa.pub
$ exit

At this point, the public key should be installed and we're ready to try logging in.

Logging In

When you login, your ssh client will match the private key from your local home, and match it against the public key on the remote host in the home directory of the user you're logging in as.

For example, if I'm logged in as cbednarski and the remote host has a cbednarski user with my public key installed, I can login simply by doing this:

$ ssh example.com

If the account on the server is different from your client username, you'll need to specify it using one of these two methods:

$ ssh username@example.com
$ ssh -l username example.com

The second option might seem like a bit of extra typing but it obviates the need to specify the username for each hostname if you're connecting to multiple servers using cssh or similar, e.g.:

$ cssh username@example1.com username@example2.com username@example3.com
$ cssh -l username example1.com example2.com example3.com

Using the second form also means that URIs that are copy-pasted to other people don't have the wrong username in them.

Other Considerations

Viewing a Key's Fingerprint

A key's fingerprint is a way to identify or "name" a key pair without exposing either key. The fingerprint is commonly used as a reference for keys that were previously installed on a service like github and AWS, because the fingerprints for the public and private keys will match.

You can view the fingerprint of a key with:

$ ssh-keygen -lf keyfile

Managing Multiple Keys

In some cases, you'll want to use different ssh keys. For example, AWS generates keys for you automatically, and you might want to use different keys for committing to github vs. logging into a production server. You have two options: You can specify a key when you connect, or you can configure hostname-specific keys.

Note: When you specify which key to use for a connection, make sure to specify your private key.

On Connection

If you want to specify a key for a specific ssh session, you can do so with -i.

$ ssh -i keyfile example.com

Passing in the key using -i is the default authentication model on AWS, but you may also find it useful if you want to login to different unix accounts on the same server.

By Hostname

If you frequently login to the same server with the same user account, it's more convenient to configure hostname-specific key files. You can do this using a user-specific ssh config on your client machine.

If you don't already have an ssh config file, create one and change the permissions so only you can read/write to it:

$ touch ~/.ssh/config
$ chmod 600 ~/.ssh/config

Edit this using your favorite text editor and arrange things like so:

Host example1.com
IdentityFile ~/.ssh/keyfile1
Host example2.com
IdentityFile ~/.ssh/keyfile2

Related

linux ssh devops