When SSH needs you to decrypt your keys

July 9, 2015

Here's something nice but vaguely surprising that I just learned about how SSH handles encrypted keys. Start with the following in your .ssh/config:

Host *
  # encrypted key:
  IdentityFile /u/cks/.ssh/ids/key-ed2

Here's the question: suppose that you're not running ssh-agent and you try to ssh off to a host where you have an account that doesn't use this SSH key. Do you get prompted for the passphrase for your encrypted key? After all, your ssh client is going to try to use it to authenticate you, since it's your default key.

My naive expectation was that you would, but it turns out that I'm wrong. As you can see with 'ssh -v' (although it's not quite explicit), the SSH protocol is that the client first asks the server 'can I authenticate with this public key?' before proceeding to actually do so. When you have what I've casually called an encrypted SSH key, only the private key is actually encrypted; the public key is stored in the clear and your SSH client can send it off to the server without having to ask you for a passphrase. If the server declines the public key, that's it. Only if the server tells ssh 'sure, now prove you know the private key' does ssh need you to decrypt it and thus asks you for the key's passphrase.

In short, ssh only needs to know your key passphrase if it's about to authenticate you with it.

This has two consequences. The first is that if you get prompted to decrypt a SSH key, that's a good sign; you're about to be accepted if you can do so (well, normally, unless the server is playing funny games). This is unlike plain password prompts, where the server will demand a password even if you have no access and the remote login doesn't even exist.

The second is that it is relatively harmless to have additional encrypted SSH keys set up in your .ssh/config and offered to remote hosts. Specifically, you won't have your ssh commands interrupted to provide passphrases only to find out that you did it for nothing.

(Until I found this out just now it was a concern of mine, since I have a mix of encrypted general keys and narrow purpose unencrypted keys in .ssh/config and sometimes try things that ssh off to 'narrow purpose' destinations when I don't have ssh-agent up and active.)

Comments on this page:

By Perry Lorier at 2015-07-09 04:26:48:

I'm not sure how this interacts with encrypted keys, but I know if you have too many keys then ssh will often disconnect you for too many auth attempts before it gets to the key that you actually want to auth with.

The number of keys is something like 6. So beware.

By yggdrasil at 2015-07-09 07:03:36:

I had that just happen to me with a new OpenBSD box and 5 keys. First ssh attempt to the box: connection closed, too many authentication tries. I was stumped quite a bit until ssh -vv helped me figure this out.

Is there a general advice how to handle this, apart from temporarily copying the keys out of .ssh?

By Albert at 2015-07-09 08:30:40:

I've connected using public key authentication having only the private key stored locally (the public one on the remote server), and it works fine (the private key was not encrypted though).

I suppose that in this case SSH can't send the public key in advance and will unconditionally ask for the private key password.

By yggdrasil at 2015-07-09 09:40:27:

Albert: makes sense. Either I have already set up public key logins on the machine, then I'll have that fact in my .ssh/config, or I haven't, in which case sending the public keys is a waste of bandwidth. So out with them from .ssh (barring some unusual configurations where you for some reason can't configure every server using a key in you .ssh/config, but still want to log in with keys)

By cks at 2015-07-09 13:25:05:

Albert: I just did a test out of curiosity and indeed if you don't have the .pub file sitting around, ssh will stop to ask you to decrypt the private key.

yggdrasil: If the extra keys are loaded into ssh-agent but wouldn't be offered without it (ie aren't in .ssh/config), you can set IdentitiesOnly in a 'Host <whatever>' block that also specifies an appropriate IdentityFile. If some of the wrong keys are coming from eg a 'Host *' block with the right key specified in a specific 'Host <whatever>' block, the solution is to move the specific block so it's earlier in .ssh/config. Keys are offered to the server in the order they're encountered in IdentityFile lines, so this way the first key you offer is the right key and how many other ones you have don't matter.

(I suppose one way to have this happen is to have default-named identity files for all of the various SSH keypair types available. My opinion is that you don't want to use all of those key types, at least not as generic keys. I stick to RSA and ED25519 general keys; if I ever have to deal with something that won't accept anything except eg a DSA key, I'll generate a DSA keypair specifically for it.)

By cks at 2015-07-10 14:29:17:

It turns out that I'm wrong about the details here and things are significantly more complicated (and annoying). See SSHConfigIdentities for the gory details (including the comments).

(My comment is correct if you have no ssh-agent but wrong if you do, because acceptable keys from ssh-agent are tried before everything else and they aren't tried in the order that you necessarily want.)

Written on 09 July 2015.
« Making GTK applications in alternate locations, settings edition
What SSH keys in your .ssh/config will be offered to servers »

Page tools: View Source, View Normal, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Thu Jul 9 01:16:51 2015
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.