ssh-keygen does not respect the syntax for hostname with -F option

Bob Proulx bob at
Tue Apr 13 03:25:09 AEST 2021

Daniele Palumbo wrote:
> From the man page of ssh-keygen:
>      -F hostname | [hostname]:port
> I have hosts with ssh running on a different port, 
> but for the sake of bug reproducer, let's remain on port 22.

I am going to comment upon the usage but not whether this is a bug or
a mis-feature or other.  I am putting on the eyeloop magnifier and
zooming in on a very small part of things.

> I assume that the syntax is:
> $ ssh-keygen -F

That does not match the man page documentation that you quoted just
before this point.

> From the man page of ssh-keygen:
>      -F hostname | [hostname]:port

Therefore it would be either this for a hostname:

    ssh-keygen -F

Or if a port is included then the hostname must be in brackets.  And
because square brackets are shell file glob characters they must be

    ssh-keygen -F '[]:22'

Or at least the opening square bracket must be quoted.  (Otherwise the
results depend upon what files match or do not match the bracketed
file glob expansion in the directory.)

    ssh-keygen -F \[]:22

  A test showing the data dependent nature of the file expansion and
  why shell quoting is required.
    $ echo ssh-keygen -F []:22
    ssh-keygen -F []:22
    $ touch 1:22
    $ echo ssh-keygen -F []:22
    ssh-keygen -F 1:22
    $ echo ssh-keygen -F \[]:22
    ssh-keygen -F []:22
  Some patterns are unusual and unlikely to be hit by accident.  But
  people are extremely clever and will often work against you.

Since you have hosts with ssh running on a different port then you
would need to bracket the hostname, add the custom port, and quote the
brackets appropriately to guard against file name glob expansion.

> But, with the given syntax, port 22 and any other port fail
> Example:
> $ ssh-keygen -F -v
> $ echo $?
> 1
> $ ssh-keygen -F []:22 -v
> $ echo $?
> 1
> $

Right.  No match.  Because the known_hosts file does not store the
port when it is the default port 22.  Therefore there is no match in
the file.

> Everything is working without any port specified:
> $ ssh-keygen -F -v
> # Host found: line 44
> ecdsa-sha2-nistp256 [...]
> $ echo $?
> 0

Here is my editorial comment.  First, I do not know.  But I have the
idea that the ssh-keygen feature was needed once the known_hosts file
became hashed to obscure the contents and the values of the hostnames.
I had never used it before them.  Originally the known_hosts file was
not hashed and the contents contained the actual hostnames in plain
text.  Therefore one could use the awk, grep, sed utils as easily as
any other to read the file and to locate the matching hostname line.

However at some point in the timeline it was believed that it was more
secure to hash the known_hosts file hostnames to prevent an attacker
who had gained access from potentially learning additional hostnames
for which the ssh key might provide access.  Therefore instead of
storing the hostnames in plain text they were hashed to obscure them.

This hashing is not the default.  But it is a typical OS customization
applied in the ssh_config file.  And therefore these days unless the
user takes an action to avoid it the hosts stored in the known_hosts
file are stored in a hashed format now.

It is with a hashed hostname in the known_hosts ssh-keygen -F or
something similar is required in order to "grep" the line (grep-like
using ssh-keygen -F) from the known_hosts file.

Therefore the -F feature really does not at this moment match
hostnames and port names and return the information as if it were a
database lookup.  There is no understanding and interpretation.
Instead it is performing the function of a fancy grep returning the
line as stored in the known_hosts file.  Which is rather a different
thing.  Whether that is a bug or simply not coded as a feature I will
leave to others to decide as I am simply a lurker and user of it.


More information about the openssh-unix-dev mailing list