Setting Up Secure SSH Key-Based Authentication


In this post you’re going to learn how to generate SSH key pairs and how to use them to authenticate with your remote server or Git repositories hosted on GitHub and similar sites.

What Are SSH Keys?

When connecting to remote servers or Git repositories, you have two options to authenticate yourself:

  • you enter your username and verify that it really is you by providing the matching password
  • you use a SSH key pair consisting of a public part and a secret, private part

SSH keys are not only securer than the username/password combination but also much more convenient.

What’s Wrong With Passwords?

Two reasons: passwords can be cracked, companies can be hacked. And it happen’s all the time. Every couple of weeks it’s in the news that some company has been hacked again and that a massive amount of passwords, email addresses, etc. has been leaked. There’s a very real chance that someone already has your email/password combination. You should check whether your email address was among the leaked addresses just to be sure (click here).

You see, it’s not a question if you will be hacked some day but when you will be hacked. It really is only a matter of time. Now imagine that someone somehow figured out your password and now has access to ALL your internet accounts, because you have only one single password that you use everywhere. Imagine it. The hacker is now in your Facebook, your iCloud, your Google, your Amazon, your bank account, and so on. That’s bad. Really bad. But even worse: as soon as the hacker has access to your Email account, he has everything. All he has to do now is to press the “I forgot my password” button and he can not only set a new passwort on any site but also lock you out of your own accounts.

But I get it, passwords are hard to remember. You cannot remember more than one or two, maybe three passwords, let alone a different password for each and every site. Heck, even one password is hard to remember—or at least extremely annoying to type—if it’s supposed to be secure. That’s why most people use weak passwords. But weak passwords may be cracked by brute-force attacks. You can take that literally. It doesn’t even require some sophisticated algorithm but only brute force, i.e. compute power. And any regular modern computer has enough of that to crack your passwords within a couple of hours. So your girlfriend’s name plus the year you were born is not at all a good password. It doesn’t even need a hacker to take over your accounts, just a few educated guesses from your ex-girlfriend or one of your “funny” buddies. Also, what if you break up with your girlfriend? Do you really want to change your password on dozens of websites?

So the typical password isn’t safe. But what about stronger passwords? What if you replace each E with a 3 and each A with a 4, you ask? Your password contains numbers now and passwords with numbers are secure, you say? Well, no… besides that every hacker knows this “trick”, it does not add any security at all. If your password has less than 16 characters, it is NOT SAFE, no matter how complex you think it is. What matters in cryptography is a metric called entropy and a high amount of entropy is achieved through length, not complexity. With techniques like so-called rainbow tables, even the most complicated passwords are not safe if they have less than 16 characters–––and as computers get better each and every year, even 16 characters are not enough anymore. How the hell are you supposed to remember such a password?! That’s why you use memorable although very long passwords such as correct horse battery staple and better still a password manager like 1Password. But even if you settle with such a password, it will be extremely secure but you’ll become annoyed rather quickly if you have to type that every single time you want to connect to a remote server.

Introducing Key-Based Authentication

A SSH key pair consists of two parts—a public part and a secret, private part. Think of them as the lock of your front door (the public part) and your latchkey (the private part). Everyone can see your front door from the outside, but despite your lock is publicly visible, nobody can get into your apartment, because only you have the latchkey to open the door.

If we apply that analogy to our SSH key pair, you may give your public key to everyone—add it to your GitHub, store it on your DigitalOcean server, etc.––but you must never give anyone your private key. It must NEVER leave your computer and enter the internet. That means don’t put it in your Dropbox, don’t send it to yourself via email, don’t send it to yourself using Airdrop. Since your private key never ever leaves your computer, no company will ever know your private key and thus cannot pretend to be you. Your public key is called public, because anyone may have access to it. But as soon as someone other than you get’s access to your private key, you’re in big trouble.

You may be asking “If I’m not allowed to put my private key into Dropbox, how do I access my GitHub repos if I buy a new computer? And what if I use more than one Mac?”. That’s easy. You could, of course, copy your private key from the one computer to the other computer using a good old USB stick, operating completely offline. But that is bad practise because of security reasons. Since you may have as many SSH key pairs as you like at the same time and because it’s so easy to create one, you should much rather create a new key pair for each individual computer. In case your laptop gets stolen with the private key on it, you have to create only one new key pair for your new laptop but don’t have to change all the key pairs on your iMac and your computer at work. In case you don’t need an old key pair anymore, simply delete it after you’ve copied your new public key to the server so that you don’t lock yourself out.

Check if You Already Have a Key Pair

First, you should check if you have already created a SSH key pair at some point. To do so, open your Terminal and type:

ls -al ~/.ssh

If you get an error message that says that the directory ~/.ssh doesn’t exist, don’t worry! This simply means that you don’t have a SSH key pair yet.1 We will create one in the next section.

In case you already have one or more SSH key pairs, you can check how secure they are and whether you should create new ones. The default name for a key, depending on the level of its security, is either id_dsa or id_rsa. A key pair consists of two files (duh), e.g. id_rsa (the private key) and id_rsa.pub (the public key). Look for the name of your public key and check its security level using this command (replace id_rsa with your public key’s name if it’s different):

ssh-keygen -l -f ~/.ssh/id_rsa.pub

If the result begins with 4096 and ends with (RSA), you’re good. But you probably wouldn’t be reading this guide if that was the case. So presumably you’re seeing either 1024 or 2048 or DSA/DSS instead of RSA. If that’s the case, your keys are not secure and you should definitely create a new key pair.

How to Create a SSH Key Pair

RSA and 4096 Bit are totally fine and very secure and you really don’t have to upgrade them in case you already have a key pair. But if we have to create a new key pair anyway, we’ll create a key pair that is even more secure. For that, we’ll be using Ed25519 instead of RSA, a signature scheme based on elliptic curves. To create the key pair, enter:

ssh-keygen -t ed25519 -o -a 100 -C "any comment you like, e.g. your name"

As for the comment, you may enter anything you like, e.g. your own name, your computer’s name, your email address, or nothing at all (use -C ""). If you omit the -C parameter, it will automatically set the comment to [email protected] by default, e.g. [email protected], which is something not everyone wants to be public for privacy reasons.

When you’re asked for a location to store your key pair, just press the Enter button. Your key pair will then get the default name and be stored in the default location, i.e. ~/.ssh/id_ed25519.pub for the public key and ~/.ssh/id_ed25519 for the private key. If you want to create more than one key pair (e.g. one for GitHub, one for DigitalOcean, one for AWS, etc.), then you have to specify a location after you’ve created your first key pair, because obviously from then on there will already be a key pair with the default name in the default location.

When you’re asked for a passphrase, you can leave the field empty and simply press Enter again. However, I urge you to set one for the worst case scenario that you somehow lose your private key.2

To break down the above command, we just created a key pair of the type Ed25519 (-t flag) with a hundred KDF rounds instead of the default 16 rounds (-o -a 100 flag). When you create a key pair, the passphrase gets encrypted too and the amount of rounds specify how well it get’s encrypted. Imagine that you accidentally uploaded your private SSH key to GitHub and you used a weak passphrase. Then anyone can crack your passphrase with brute force and your weak passphrase helps you as much as no passphrase. The more rounds you used to encrypt your passphrase, the harder it is and the longer it takes to crack it. This gives you a couple of hours more time to react and exchange the SSH keys on your servers. But the more rounds you use the longer it takes to verify yourself each and every time you want to log in. Thus 100 rounds are more than enough.

Configuring SSH

You didn’t make the switch to SSH key pairs just to trade your password for a passphrase. Since you neither want to type your passphrase every time you log in to your server, there is a useful (and secure) program on your computer called ssh-agent that can retrieve the passphrase from the macOS Keychain where it is securely stored after you’ve entered it the first time. That means you have to enter your passphrase only once and will from then on never be asked for it again. But macOS Sierra introduced some changes that let your computer forget after each reboot that you’ve already entered your passphrase. To make that persistent and add your key pairs and passphrases to the ssh-agent for good, you need to perform these commands:

echo 'Host *' >> ~/.ssh/config
echo '    AddKeysToAgent yes' >> ~/.ssh/config
echo '    UseKeychain yes' >> ~/.ssh/config
echo '    IdentityFile ~/.ssh/id_ed25519' >> ~/.ssh/config

Getting Your Public Key To GitHub

To get your public SSH key to GitHub, first copy the content of your public key to the clipboard:

pbcopy < ~/.ssh/id_ed25519.pub

Then go to GitHub’s Settings page, specifically the SSH and GPG keys section, and click on “New SSH key”. There you can give your new SSH key a name, e.g. “Personal MacBook” or “MacBook Work”, and paste the public key from the clipboard in the field below.

To test your SSH configuration, perform this command:

It should tell you Hi …! You've successfully authenticated, but GitHub does not provide shell access..

Getting Your Public Key to the Server

If you have a remote server, you’ll want to get your public key there too. The process is a little bit different than the one with GitHub but is just as easy. By the way, I have my remote server at DigitalOcean to host this very site. It costs only $5/month and I couldn’t be happier with them. Click on the link to get your first two months for free, if you want to try them out at no risk.

An extremely easy way to copy your public key to your server is with a tool called ssh-copy-id. You need to have Homebrew installed, then you can get ssh-copy-id like so:

brew install ssh-copy-id

You’ll then need to find out the user name of the server, e.g. root or david, as well as the IP address of the server (a number that looks similar to 192.168.0.1). Replace the placeholders in the following command with your own username and the actual IP address (192.168.0.1 was just an example and will not work):

ssh-copy-id [email protected]

In case you use multiple key pairs for the case that one gets compromised (e.g. one for GitHub, one for DigitalOcean, one for AWS, one for work, etc.), then you of course have to specify which of those public keys you want to copy to the server. You do this using the -i flag:

ssh-copy-id -i ~/.ssh/digitalocean.pub [email protected]

Attention: Be sure to use the .pub ending, since you want to copy the PUBLIC key to your server and not your private key. But I think copying your private key to a remote server isn’t even possible using ssh-copy-id and it (rightly so) wouldn’t let you do it. Anyway, you see how easy it can be to accidentally mess up and share your private key. I hope you’ve set a passphrase when you created your key pair :wink: In case you forgot, don’t worry! Here’s how you add a passphrase to your existing key without having to create a new pair (replace the default name id_ed25519 if necessary):

ssh-keygen -f ~/.ssh/id_ed25519 -p -o -a 100

The passphrase is only necessary to unlock your private key, so this does NOT change your existing public key. You’re private key doesn’t leave your computer anyway and your public key remains unchanged, so adding or changing the passphrase has absolutely no consequences. You don’t have to replace your public key on your servers or anything like that. You can change your passphrase as often as you like. There is nothing you have to do after after this command.

So there you have it :relaxed: You’ve set up the most secure form of authentication and can now clone your Git repositories and connect to remote servers using SSH. If you’re having trouble setting up your key pairs, leave a comment down below. If you found this article helpful, I’d really appreciate it if you’d let me know or if you would share this article with your classmates / co-workers to let them benefit, too!

  1. ~/.ssh/ is a hidden folder in your home directory where your SSH key pairs are stored. This folder gets created automatically when we generate our first key pair. 

  2. People accidentally upload their private keys to GitHub repositories all the time and the internet does not forget. Once it’s there, it’s there forever.