-1

This question already has an answer here:

When an SSH client connects to an SSH server using public key authentication, the server encrypts a message using a public key from authorized_keys, and the client must prove it can decrypt the message.

How does the SSH server know which public key to use for a given client?

The client cannot be sending the public key to the server, as according to this answer the client doesn't need the public key to login: https://security.stackexchange.com/a/42847/174597

Note I am not asking about how public key authentication works. I am asking which public key does a typical SSH server (e.g. OpenSSH) use to encrypt the challenge sent to the client, from a list of keys stored for example in authorized_keys?

marked as duplicate by Rory Alsop Apr 3 '18 at 8:14

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    The client does indeed send the public key to the server, if public key authentication is enabled. – forest Apr 2 '18 at 23:48
  • @forest do you have any references to back that up? Did you read the linked answer? – aaa90210 Apr 3 '18 at 0:00
  • @forest OK but I am asking about the server. How does it know which public key from authorized keys to send to the client? Does it send multiple challenges based on all of them until the client answers one correctly? – aaa90210 Apr 3 '18 at 0:19
  • 1
    Is this what you are asking: How are unique SSH users linked to authorized_keys file? – forest Apr 3 '18 at 0:21
  • 2
    I'll add one minor detail, that key selection is negotiated. The client tells the server what keys it has, the server picks one, and the client proves it has the private key by sending a signed string. You can see this happen with ssh -vvv user@example.com. – nbering Apr 3 '18 at 1:21
4

RFC 4252 provides guidelines on how public key authentication should work, but it is not entirely specific on the exact order of the exchange. That said, it was stated in the comments that OP is not interested in RFCs but rather the implementation details for "SSH on Linux", which refers to OpenSSH in most cases.

Connecting to a remote host over SSH with the verbose -v flag, you will typically see the following for each key:

debug1: Offering RSA public key: .ssh/id_rsa.pub

Further, we can look at the source code. After a quick skim, the following is relevant:

if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) &&
        PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b),
        sshbuf_len(b), NULL, ssh->compat)) == 0) {
        authenticated = 1;
}

The user_key_allowed function checks for the key in an authorized keys file, while the sshkey_verify appears to verify the signature of some buffer.

Combining this information, it appears that the client will use all of its keys until the server accepts one. This is also evident by the fact that having multiple keys present during a single connection attempt may appear on the server as multiple authentication attempts since all of the keys are tried.

Additionally, see @nbering's comments for the details on the challenges/signatures.

Edit: Here's an example where I have several keys, and only the third one tried is accepted by the server. Using -vvv:

debug1: Next authentication method: publickey
debug1: Offering public key: RSA SHA256:QfriqWH2S2uD6wHbxTFSudppOcJ51bB5ABr8ICrUhL8 .ssh/id_rsa2
debug3: send_pubkey_test
debug3: send packet: type 50 # SSH_MSG_USERAUTH_REQUEST
debug2: we sent a publickey packet, wait for reply
debug3: receive packet: type 51 # SSH_MSG_USERAUTH_FAILURE
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password
debug1: Offering public key: RSA SHA256:3M8bnhs+jGJm8X2cgnWzzMrfoeT3WmDkSp8AEr751Sk user@laptop
debug3: send_pubkey_test
debug3: send packet: type 50
debug2: we sent a publickey packet, wait for reply
debug3: receive packet: type 51
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password
debug1: Offering public key: RSA SHA256:CQeP9lcYBVqV11Rn8Ca4Sv+W8l8uU63WQ4TpyG5ZMmI user@laptop
debug3: send_pubkey_test
debug3: send packet: type 50
debug2: we sent a publickey packet, wait for reply
debug3: receive packet: type 60 #  SSH_MSG_USERAUTH_PK_OK
debug1: Server accepts key: pkalg ssh-rsa blen 279
debug2: input_userauth_pk_ok: fp SHA256:CQeP9lcYBVqV11Rn8Ca4Sv+W8l8uU63WQ4TpyG5ZMmI
debug3: sign_and_send_pubkey: RSA SHA256:CQeP9lcYBVqV11Rn8Ca4Sv+W8l8uU63WQ4TpyG5ZMmI
debug3: send packet: type 50
debug3: receive packet: type 52 # SSH_MSG_USERAUTH_SUCCESS 
debug1: Authentication succeeded (publickey).

This again closely follows RFC 4252, pages 8-9.

  • 2
    Nice. Clear and concise and with source code to boot. Hope this explains things well enough for @aaa90210's purposes. – nbering Apr 3 '18 at 2:00
  • Wrong answer, the client doesn't need a public key to connect using public key authentication. – aaa90210 Apr 4 '18 at 0:02
  • 3
    @aaa90210 You don't need the public key file on your system, but as long as you have the private key, you can derive the public key if needed. Also, with that attitude, it is unlikely you will get much more help. – multithr3at3d Apr 4 '18 at 0:08
  • @multithr3at3d if being surprised all these experts can't answer a basic question is an attitude, then I guess I have one. I am not interested in deriving a public key, I want to know how e.g. OpenSSH knows which key from authorized_keys to encrypt the challenge sent to the client. Such a simple question. – aaa90210 Apr 4 '18 at 0:10
  • 4
    @aaa90210 OpenSSH does not encrypt any challenge. That's not how the protocol works. – forest Apr 4 '18 at 0:19

Not the answer you're looking for? Browse other questions tagged or ask your own question.