-1

I have the fingerprint from the remote host which is said to be its public key fingerprint according to What is a SSH key fingerprint and how is it generated?.

Asking for the host fingerprint:

ssh-keygen -lf <(ssh-keyscan MY_SERVER.com 2>/dev/null)

gives for example:

2048 SHA256:asdfaewfbadsdasfasgasefasfasdvfth56sdghjum7 id_rsa (RSA)

and the following line:

ssh -o visualhostkey=yes -o FingerprintHash=SHA256 MY_SERVER.com

reaches the same:

2048 SHA256:asdfaewfbadsdasfasgasefasfasdvfth56sdghjum7 id_rsa (RSA)

and should be enough to say that the connection is the expected one.

On the other hand, I have the public (MY_PUBLIC_SSH_KEY) + private (MY_PRIVATE_SSH_KEY) ssh key pair at hand for the server. I can connect to the server with the private ssh key, and then with the right login_name, I do not need to enter a password anymore, which is the idea of the ssh key. Therefore, the public key that is saved on the server must also be the right one:

ssh -o visualhostkey=yes -o FingerprintHash=SHA256 -i MY_PRIVATE_SSH_KEY MY_LOGIN_NAME@MY_SERVER.com
# # or the same: 
# ssh -o visualhostkey=yes -o FingerprintHash=SHA256 -i MY_PRIVATE_SSH_KEY MY_LOGIN_NAME@MY_SERVER.com

But the fingerprint of the public ssh key MY_PUBLIC_SSH_KEY does not give the same fingerprint as that of the server. It does not use 2048 at the bit size of the underlying key, but the default 4096:

ssh-keygen -b 2048 -t rsa -lf id_rsa.pub

gives:

4096 SHA256:asfawefbrgaqeffaefafrew546rtghhdhdfhsert45y id_rsa (RSA)

The public key that I have at hand looks like:

ssh-rsa AAAABasfjjeiaj;jkaskl;dfkjsafe9w0fo-0oas[kfoamks;dfk...(4096 bits size)== MY_FILE_NAME

while that on the server (cat .ssh/id_rsa.pub) is:

ssh-rsa AAAABasfjieajfjaei;jfi;ajisejifjdfasdf(2048 bits size)...== ANOTHER_DIFFERENT_FILENAME

The fingerprints are not the same because the underlying key lengths and the added comment at the end are different. Yet, they should be the same thing. The -b parameter does not react to anything, and I can even use -t ecdsa and the fingerprint will still be the same, as if it always just gives something that is already fixed by the public key content itself.

ssh-keygen always defaults to 4096 bit key size, I need 2048, the -b parameter does not seem to work.

From this I see that either the public key has changed to the better 4096 standard and the ssh-keygen might default to that -t parameter which was used in the new public key while the server still outputs the old fingerprint for whatever reason, or the fingerprint of the public key cannot be the same as the fingerprint of the host since they are calculated from different bit sizes.

I also found that you can change the default of ssh-keygen, see Can you make default client key length larger for ssh-keygen?, but should it not just also work out with the -b parameter? 4096 is a good default, I do not want to change it. Or do I oversee something general here?

I know from other Q/A that it should already be enough to do the two steps above that reach the same fingerprint. But then I still want to know what I should do with the fingerprint of that 4096 bit public key at all if I do not need it for the successful comparison above.

I must have misunderstood something. With a key pair at hand, and the private key working, how can I find the "counterpart public key" on the server and compare fingerprints?

questionto42
  • 2,691

2 Answers2

2

The -b parameter does not react to anything, and I can even use -t ecdsa and the fingerprint will still be the same, as if it always just gives something that is already fixed by the public key content itself.

Yes, that is actually how public keys work – all those parameters define the key itself, not the fingerprint, and they're pretty much immutable once the key has been generated.

The -b parameter literally defines the size of the key; if you have a 4096-bit sized RSA key, it will always be 4096 bits in size, and it will always be an RSA key. You can't just ask the software to cut it down to 2048 bits, or treat it like an ECDSA key.

So because the -l option in ssh-keygen -l instructs it to show information about an existing key, this means that if it says "4096" then it's a 4096-bit key and that's the end of it.

But those options are irrelevant to computing the fingerprint. SSH key fingerprints are nothing more than a direct SHA256 hash of the public key. If you look at the actual public-key file, it consists of "key-type key-data comment"; its fingerprint is simply SHA256() of the 'key-data' field, after Base64-decoding it. For example:

$ ssh-keygen -lf id_rsa.pub 
2048 SHA256:aOWdMg2Aoocj1yO90p9646d7ktNPIAjbjWm1PXTA9P0 root@frost (RSA)

$ awk '{print $2}' id_rsa.pub | base64 -d | openssl sha256 -binary | base64 aOWdMg2Aoocj1yO90p9646d7ktNPIAjbjWm1PXTA9P0=

As you can see, nowhere in the process even the key type is checked, much less type-specific parameters like the bit-size of the RSA prime.

While SSH servers typically have both an RSA key and an ECDSA key, the two are usually stored in different files, so if you want to see the fingerprint of the ECDSA key you have to copy the correct file. (The "public" files could be concatenated together into one file, then ssh-keygen would automatically list multiple fingerprints.)

grawity
  • 501,077
-1

This answer only shows how I got it done in the end and why theory and reality are a bit apart here, therefore I had to accept my own answer here without saying that the other answer is not helpful. For more typical settings, you will probably learn more from the other answer.

Server for user login only

The server was setup to let each user enter with its own "home of the public key"! This is an LDAP (Lightweight Directory Access Protocol) authentication system which is not used anymore on that server.

Step by step

How to find the user public key

I had to look up where to find the .ssh folder with the public key in a list of "password foldernames" mapped to a wide range of users:

etc/pass (long list of various users of the server with their passwords/secrets mapped):

... [long list]
proxy:x:13:13:proxy:/abc:/bin/sh
www:x:33:33:www:/xyz/www:/bin/sh
backup:x:34:34:backup:/zyx/backups:/bin/sh
... [long list]

My user www therefore had the .ssh in /xyz/www.

(Side-note: When looking through the server without seeing the directory tree in the terminal, you may use pwd to see where you are.)

Outdated public key in user .ssh

I switched to /xyz/www/.ssh. But in the folder, there was an outdated 2048 bit public key "id_rsa.pub", and not the server public key as in the first two commands of the question - checked with the fingerprint command again.

Server public key nowhere to find

I still do not know where that 2048 bit server key of the first two commands of the question is, and it is not the question here, but I guess that it is in /root which I cannot open in the terminal although it is there. There is also a root user that uses /root/.ssh for the secrets and passwords. Since the server is a VM, the working directories at start change with the users and different volumes are mounted for each user.

Found 4096 bit public key

The needed 4096 bit key was in the authorized_keys file in that same folder instead. The authorized_keys file looked like:

$ cat authorized_keys
... [longer list]
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAA... +some comment
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABA... +some comment
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABA... +some comment <-- my key

This last key in the list, "my key", is the one that I also have as a public key at hand, see above in the question (I changed the letters everywhere, but I take over the example from above):

ssh-rsa AAAABasfjjeiaj;jkaskl;dfkjsafe9w0fo-0oas[kfoamks;dfk...(4096 bits size)== MY_FILE_NAME

Side-note: MY_FILE_NAME is a comment that you add when making the key pair and is at your free choice, in my case the file_name, can be whatever.

And this key is different from the server key (first two examples in the question) but is the one that is checked when I connect to the server with my user www.

Matching fingerprints

Since the two public keys are the same, their fingerprints match as well, both

ssh-keygen -lf id_rsa.pub

give

4096 SHA256:asfawefbrgaqeffaefafrew546rtghhdhdfhsert45y id_rsa (RSA)

User public key

Therefore, this has all to do with a user public key that I need to check in an .ssh for that user only. It is not a server key, and the still existing server key is not used anymore and probably outdated (only 2048 bits). The rights and ssh keys for this server are all managed on user level. I guess that this has grown with the need to change to 4096 bit keys. Because of this user access structure, I had problems to find the 4096 bit public key on the server although it had to exist since my private key worked.

Wrap up

The question was changed from

How can I make a fingerprint from the public key that is the same as the server fingerprint?

to:

With a key pair at hand, and the private key working, how can I find the "counterpart public key" on the server and compare fingerprints?

because the first question was misleading. I could not know it better at the time of asking, though. It asked for the server public key fingerprint but in reality, that global server public key was not used anymore (outdated) and any access was arranged on user level with different .ssh subfolders, passwords and secrets for each different user. Please vote accordingly, meaning: the other answer is for the "earlier question", and though not accepted, it is of course helpful.

questionto42
  • 2,691