Working with SSH keys seems to be one of those things I have done just rarely enough to forget most of it between each time. I decided to never let managing SSH keys trip me up again — by dusting off my notes, reading up some more, and turning them into this blog post.
An algorithm generates a key pair 🖇
Public-key cryptography is a cryptographic system that uses pairs of keys. Each pair consists of a public key (which may be known to others) and a private key (which may not be known by anyone except the owner)
There are also others! GitHub is making changes to protocol security these days that might affect you if your SSH keys were generated a long time ago.
Get to know my .ssh directory 🕵🏻♀️
Many guides seem to train me to fire off commands without learning which files are created or edited. “Simply run xyz to auto config, and don’t you worry about what it does on your laptop.” A habit I find never stops giving, is to poke around files and directories more, both before and after executing these types of commands. Makes it easier for me to understand what is what — and then how to debug like a badass when some day a thing doesn’t work as expected.
# List directory contents
ls -la ~/.ssh
This may tell me there is
No such file or directory — or show me what the directory contains, including when the files were created. A typical list might have these files:
configis my user configuration file for ssh
id_ed25519is the private key that I need to keep super secret
id_ed25519.pubis the public key to be shared (for example with GitHub)
known_hostskeeps track of the public key for hosts my laptop connects to with ssh
We can inspect those files 😸
We can totally cat them all and see what they look like. If you thought (like I did) that especially the private key must be a very special type of mysterious file (I mean, look at it, no file-ending!) and therefore best left untouched, it can be kinda underwhelming to see the content.
# Change directory, then view the private key
cd .ssh && cat id_ed25519
# View any other files too, do it do it do it
Now that I know which files I have and what they look like, none of this upcoming keygen business is mysterious. Maybe I want to replace a pair? Set up the first pair on a new device? Set up multiple keys for different purposes? Edit the config? No problem, we got this.
Generate a new key pair 🔑
# Generate a public/private key pair
ssh-keygen -t ed25519 -C "firstname.lastname@example.org"
This is the recommended command from GitHub, and we are going to break it apart:
ssh-keygenis a standard cli tool — I can run
man ssh-keygenfor the full manual
-t ed25519will specify type of key (which algorithm)
-t rsa -b 4096that creates type RSA with 4096 bits
-C "whatever"provides a comment
The email in that command is a comment that can be anything. It can even be changed on existing keys if I used the wrong email. The convention is to identify the public key with an email, so that when the public key is shared, it will not be an anonymous key belonging to who knows who’s device.
Specify file name with intended use
Tool asks where to save the file and suggests
/Users/name/.ssh/id_ed25519 While it’s possible to accept with a quick enter, let’s customize instead. I will use the same path as the suggestion, but opt for a more specific file name that includes algorithm and where I plan to use the key pair:
Secure with passphrase
Enter passphrase? Yes, of course. Generate a long password in my password manager, and also save it there under “SSH key passphrase personal laptop / for github” or similar. (Gotta save the passphrase! I don’t think I need to save the fingerprint or randomart image that is output in the terminal.)
Repeat for any other places that request my public key
And if I now list directory contents of my
.ssh, it might look like this:
Config my key collection ⚙️
Multiple keys will need a
~/.ssh/config looking something like this:
Host github.com AddKeysToAgent yes UseKeychain yes IdentityFile ~/.ssh/id_ed25519_for_github Host something.else // other settings for this key IdentityFile ~/.ssh/id_ed25519_for_something
I used a passphrase, but I don’t want to reenter it every time I use my keys (like when pushing to GitHub). But I can
ssh-add my key to an
ssh-agent is a program to hold private keys used for public key authentication. Through use of environment variables the agent can be located and automatically used for authentication when logging in to other machines using ssh.
# Start the ssh-agent in the background eval "$(ssh-agent -s)"
ssh-add adds private key identities to the authentication agent, ssh-agent
# Add private key to the ssh-agent ssh-add -K ~/.ssh/id_ed25519_for_github
- Will first ask for the passphrase
- And should then output
- Repeat for the other key!
-K in that command is an option to “Load resident keys from a FIDO authenticator” 🤷🏻♀️🤷🏻♀️🤷🏻♀️
Other commands to play around with or know about:
# Lists all identities currently represented by the agent
# Deletes all identities from the agent
They don’t list or delete any keys I have generated, this is only what is added to the authentication agent. Who’s job is to save me from using the passphrase each time I push to GitHub.
Give away the new public keys 🎁
- Add one to my GitHub Account Settings
- Add another to that work thing that needs a key
Test connection 📞
ssh -T email@example.com
I can see from
man ssh that
-T option will “Disable pseudo-terminal allocation.” 🤷🏻♀️🤷🏻♀️🤷🏻♀️
“Sure you want to connect?” Verify with GitHub’s public key fingerprint 👍
If I don’t already have a
known_hosts file already, this will create one. It will also add the public key for hosts my laptop connects to with ssh. Which I learnt because I poke around files and directories, both before and after executing these types of commands.
And if something goes wrong, there is an excellent guide to Troubleshooting SSH — a guide which now is more straight forward for me to parse than before.