Authentication, authorization, and everything in between
SSH keys are complicated, I get it. But it’s not because it’s actually complicated… it’s because the rationale isn’t clear behind them. To understand SSH keys, we will first define the problem:
- Host Key Verification — A client should know that the server he is trying to connect is indeed the server it claims to be
- Key-Based Authentication — A server must know who is the user trying to connect, and whether or not he is allowed to do so
Host Key Verification
Do you remember getting this message?
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
Please contact your system administrator.
Add correct host key in /home/ron/.ssh/known_hosts to get rid of this message.
Offending key in /home/ron/.ssh/known_hosts:3
RSA host key for 192.168.0.100 has changed and you have requested strict checking.
Host key verification failed.$
SSH provides a mechanism to verify that the server that you are trying to connect to is actually the host it claims to be. This is done by the following algorithm:
- When an SSH server is initialized, it creates a host key, which is a public/private keypair. The SSH server gives out the public key to anyone who connects to it
- Your SSH client checks if the host you are trying to connect to has a host key in the ~/.ssh/known_hosts file
- If the entry does not exist, add the host key to the ~/.ssh/known_hosts file
- If the entry exists, use the host key (which is a public key) to encrypt a message, and expect the server to decrypt it. If the server has successfully decrypted the message, then it means that the server holds the private key which matches the given host key, meaning that it is who it claims to be
The host key verification mechanism promises the client that once it connected to a specific server, every connection to that same hostname will check that the server is in fact the same server you connected to the first time.
If you were to replace the server, the host key will change, and all clients that have the previous key will start receiving this message until they replace the stored key.
This is where the real magic happens. Just like the client wants to know if the host is who he really claims to be, this time the server wants to know if the user that is connecting is in fact the user it claims to be.
Key-based authentication is the best method of authentication since it does not involve a password. However, if you lose your key, then you will not be able to connect to the server.
To start using key-based authentication, the client must generate an SSH keypair. The keys are not automatically generated, you will need to generate them yourself. To generate a key, just run the OpenSSH utility ssh-keygen.
After a client has an SSH keypair (usually resides in ~/.ssh/id_rsa for an RSA key along with ~/.ssh/id_rsa.pub) then you can configure the server to allow connections to a specific user by using your key. This is done by appending your client’s public key to the user’s ~/.ssh/authorized_keys file on the server.
Let’s go with an example: Let’s say you would like to log in to ssh.foo.com using the user “ron”. This means that you have some way of modifying /home/ron/.ssh/authorized_keys. You need to take the contents of the file ~/.ssh/id_rsa.pub from your local client which will be connecting (the public key which represents your private personal key) and append it to /home/ron/.ssh/authorized_keys on the server.
The authentication flow then looks like this:
- The client connects to ssh.foo.com and goes through the previously discussed host-key verification process.
- The server asks for a user name and the client responds with one. (“ron”)
- The client (my MacBook) offers the public key for /Users/ron/.ssh/id_rsa (which is stored in /Users/ron/.ssh/id_rsa.pub)
- The server checks to see if the public key is in the list of authorized keys that would allow us to connect to the user’s account on that server (the authorized keys are in /home/ron/.ssh/authorized_keys)
- If the key exists, the server will encrypt a message using the public key from the authorized keys list and expect the client to be able to decrypt it, since it should have the private key
- The client will get the encrypted token from the server, decrypt it, and send it back (it actually sends back a hash of the token and a session key, but this is not important for the sake of this explanation)
- The server will see that the token was decrypted successfully, and will allow the user to log in as “ron” by impersonating the user
I hope this article makes it easy to understand how SSH keys actually work. Enjoy!
Hacker Noon is how hackers start their afternoons. We’re a part of the @AMIfamily. We are now accepting submissions and happy to discuss advertising &sponsorship opportunities.
To learn more, read our about page, like/message us on Facebook, or simply, tweet/DM @HackerNoon.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!