private key and public key in same directory causes ssh to fail

I have this really weird problem where I'm trying to connect using SSH to a remote server.

I'm doing this from the command line, and both the private key and public key are located in my current directory. They are named id_rsa and id_rsa.pub respectively. I have verified via the fingerprint that they are matching public and private keys.

When I issue the following command:

ssh -vT -i ./id_rsa user@remotehost

I get the following error: Permission denied (publickey).

However, if I rename my id_rsa.pub to something else, it works fine. What could possibly be causing this? Could it be a setting on the remote server that is causing this?

The output from -vT when I have the id_rsa.pub in the same directory is (and it fails):

OpenSSH_6.1p1, OpenSSL 0.9.8e-fips-rhel5 01 Jul 2008
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 50: Applying options for *
debug1: Connecting to remotehost port 22.
debug1: Connection established.
debug1: identity file ./id_rsa type 1
debug1: identity file ./id_rsa-cert type -1
debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3p1 Debian-3ubuntu7
debug1: match: OpenSSH_5.3p1 Debian-3ubuntu7 pat OpenSSH_5*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.1
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-md5 none
debug1: kex: client->server aes128-ctr hmac-md5 none
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
debug1: Server host key: RSA <removed>
debug1: Host remotehost is known and matches the RSA host key.
debug1: Found key in /home/user/.ssh/known_hosts:10
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
Ubuntu 10.04.4 LTS
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: ./id_rsa
debug1: Authentications that can continue: publickey
debug1: No more authentication methods to try.
Permission denied (publickey).

The debug output when I rename the id_rsa.pub is:

OpenSSH_6.1p1, OpenSSL 0.9.8e-fips-rhel5 01 Jul 2008
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 50: Applying options for *
debug1: Connecting to remotehost port 22.
debug1: Connection established.
debug1: identity file ./id_rsa type -1
debug1: identity file ./id_rsa-cert type -1
debug1: Remote protocol version 2.0, remote software version OpenSSH_53p1     Debian-3ubuntu7
debug1: match: OpenSSH_5.3p1 Debian-3ubuntu7 pat OpenSSH_5*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.1
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-md5 none
debug1: kex: client->server aes128-ctr hmac-md5 none
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
debug1: Server host key: RSA <removed>
debug1: Host remotehost is known and matches the RSA host key.
debug1: Found key in /home/user/.ssh/known_hosts:10
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
Ubuntu 10.04.4 LTS
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Trying private key: ./id_rsa
debug1: key_parse_private_pem: PEM_read_PrivateKey failed
debug1: read PEM private key done: type <unknown>
Enter passphrase for key './id_rsa':
debug1: read PEM private key done: type RSA
debug1: Authentication succeeded (publickey).
Authenticated to reoteserver:22).
debug1: channel 0: new [client-session]
debug1: Requesting [email protected]
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env LANG = en_US.UTF-8

Solution 1:

I was able to reproduce your symptoms by using a public key and a private key, which did not match each other. Even if both keys are permitted by authorized_keys, login fails when the public and private key do not match.

From what I can tell the following happens.

  1. Client notice that the private key is encrypted
  2. Client read the public key file
  3. Client offers this key to the server
  4. Server accepts the public key
  5. Client prompts for password
  6. User enters password
  7. Client continues authentication using mismatching private key

When you remove the public key, the client will ask for a password without knowing if the server will accept the key. This means you may end up being asked to type the password for a private key only to find that the server wouldn't accept it anyway.

Solution 2:

This may be a bug in OpenSSH or the key in server´s authorized_keys and your private key don't match after all. When the authentication succeeds, you get

debug1: identity file ./id_rsa type -1

meaning that the OpenSSH cannot load identity file (I think public key) in that stage. In the source code in the key loading part there is this snippet (authfile.c):

/* try ssh2 public key */
pub = key_new(KEY_UNSPEC);
if (key_try_load_public(pub, filename, commentp) == 1)
    return pub;
if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
    (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
    (key_try_load_public(pub, file, commentp) == 1))
    return pub;

Meaning that OpenSSH will try to load what is given in -i parameter + ".pub" as a public key and succeed as indicated in the log. Without the public key with suffix ".pub" in the current directory this will fail. Later on, when doing the authentication (sshconnect2.c):

/*
 * send a test message if we have the public key. for
 * encrypted keys we cannot do this and have to load the
 * private key instead
 */
    if (id->key && id->key->type != KEY_RSA1) {
        debug("Offering %s public key: %s", key_type(id->key),
            id->filename);
        sent = send_pubkey_test(authctxt, id);
    } else if (id->key == NULL) {
        debug("Trying private key: %s", id->filename);
        id->key = load_identity_file(id->filename);
        if (id->key != NULL) {
            id->isprivate = 1;
            sent = sign_and_send_pubkey(authctxt, id);
            key_free(id->key);
            id->key = NULL;
        }
    }

If the public key was present, OpenSSH will send it as a a test message (?) which will fail for some reason. Without preloaded public key it will try private key and succeed.

I don't know why the failure with public key happens (if I have time, I'll try to figure out more). There is maybe some mismatch the files in .ssh/ are handled compared to other paths, or there is some mismatch with your keys after all.