Why does Keychain compain that id_rsa.pub is missing?

Solution 1:

I freely concede that I have no knowledge of the inner workings of keychain, but it's completely reasonable that a local ssh agent should be upset not to have a public key that corresponds to a private key that it does have.

Consider what happens when you approach a remote server to authenticate. The remote server knows, from its authorized_keys file, that it's prepared to accept a client that can prove it has the corresponding private key to each entry therein. But how does it ask for that from the client? It can't give each private key itself, nor any property thereof, because it doesn't have it; all it can do is present the public key(s), or fingerprints thereof, that it will accept.

If the client has any of those those public keys, it can immediately select the matching private key, and make a response which the server will accept as correct. If it doesn't have those public keys, what is it to do? Try every private key in its repertoire in turn? A better recipe for unsafe information disclosure could scarcely be imagined; a black-hat would only have to set up a man-in-the-middle attack on a single new connection to harvest legitimate responses from every key in your keyring.

It's possible that keypairs have some kind of internal numbering, but this would be completely arbitrary and unwise to rely on. There's no guaranteed internal property tying a private and public key together, because there's nothing shared by the keys in a keypair, save that one is (hopefully) the only entity that can undo what the other does.

No, the best way for the client to select the right private key to use to any given server is to have the matching public keys to assist it in key selection.

Solution 2:

I think keychain is trying to be more secure than the program for which it is a helper (ssh).

As of my current version of OpenSSH, it is possible to add a private key to ssh-agent with ssh-add without having the public key file. After you do this, you can see if it succeeded, as ssh-add -l will also list the private key file name. ssh will use the cached key to connect, even if more than one identities are available. Trying them in turn is explicitly mentioned in the documentation.

$ ssh -V
OpenSSH_7.2p2, OpenSSL 1.0.2g  1 Mar 2016
$ man ssh_config
...
     IdentityFile
      ...
             It is possible to have multiple identity files speci‐
             fied in configuration files; all these identities
             will be tried in sequence.  Multiple IdentityFile
             directives will add to the list of identities tried
             (this behaviour differs from that of other configura‐
             tion directives).
      ...

I think it is best to use the AddKeysToAgent option to ssh. It will ask for the passphrase only the first time in your session, if you have ssh-agent available. In your .bashrc you can add just eval $(keychain --eval --noask)