0

I am trying to verify the SSH fingerprint of a GitLab server. Its published fingerprints are wrong, possibly from load balancing. VerifyHostKeyDNS=yes doesn't error but I don't trust not seeing fingerprints and would like to do so without connecting.

SSHFP SHA1 and SHA256 are in hex. I would also prefer the numeric IDs like "4 2" to be converted to English names like "SHA256 (ED25519)".

$ resolvectl query -t sshfp ssh.gitlab.gnome.org
ssh.gitlab.gnome.org IN SSHFP 1 1 9d319c15965b939bc2086cbebca96d8bbb89e9a3 -- link: enp39s0
ssh.gitlab.gnome.org IN SSHFP 1 2 591469a16a3bb33333c2591815e2e88f4508b665477c023eafe845833c060118 -- link: enp39s0
ssh.gitlab.gnome.org IN SSHFP 3 1 17b29179778339d7c91cb2c281b7afa2798c61d5 -- link: enp39s0
ssh.gitlab.gnome.org IN SSHFP 3 2 4e203da68ea73ba8c5b28ef040dcb8c4b96d875d2521f8efd5dc6e0da6d522ac -- link: enp39s0
ssh.gitlab.gnome.org IN SSHFP 4 1 457e9cb0d575697e27fe8b2185580df5d45ce46b -- link: enp39s0
ssh.gitlab.gnome.org IN SSHFP 4 2 63d1b87568887e2e772d1dc89c95ac21bbf895e9141e89eafc7aea4d39bfadcc -- link: enp39s0

-- Information acquired via protocol DNS in 1.1133s. -- Data is authenticated: yes; Data was acquired via local or encrypted transport: yes -- Data from: network

However, ssh-keyscan gives me Base64 for SHA1 and SHA256. Only the MD5 absent from SSHFP would be in hex. SHA256 Base64 is also the format that git prompts me with when connecting. My use case is to manually inspect the fingerprint, then somehow trust it into ~/.ssh/known_hosts. For simplicity, I only care about ED25519.

$ ssh-keyscan ssh.gitlab.gnome.org | tee gnome.pub
# ssh.gitlab.gnome.org:22 SSH-2.0-OpenSSH_8.0
ssh.gitlab.gnome.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHG6b3deoYMPwKEu9Sj+y6MBHYYUKQiAnta/go3aNv7R
# ssh.gitlab.gnome.org:22 SSH-2.0-OpenSSH_8.0
ssh.gitlab.gnome.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCmUnZ33O26kvhcmc6k1T8xlL3yJjeNt3gphvW9/5u/CO0z5G8PGr2km4jUhStuPJR9m77LrdCF5Ywm26hsBnoxK+1zMs7YTjriiGt4r0Q5btQS5J5zFAV6aYJEmCbQz/23n8+w9Jx3hPVS8A3VE9Vd52S+5DMeIQY8QR3LPpROyCIpkR425sN0D0VjRUAH0hn61zS8N1+Pw5te2ULbBriBB9cub2n1GBCsZ2ErX1ernwKffOz/fbi5mpGbGLlJabLBm81/AiNk6NLZWTAZiNZjztxRySZFSpSzGF54kttIePxNC1x9AtW4KMaIzjVK2DIrFONyZYiEX47ox5TXlc7VQaBICUoTrR91wpb5xl2HPKP4MvFqUAzubU2V8r91ISXrnJyfwDrSB7L9Jwg6B6pN+acIttC4gOFGTJg9qanmLxtonSpwv/NaLehI1+D4LR9Or+e8jjtKSc6vu8+ghqAni3XHoT9uSmt1UPd89dOhqbpk8Hc3KTubUC3WIjGnotE=
# ssh.gitlab.gnome.org:22 SSH-2.0-OpenSSH_8.0
ssh.gitlab.gnome.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH8NuGQ3ArFGochlv6TKXhMhsgIwG743e93pLkAQTzfgds0g0k6QBimb40zavVjITjytiSaQsf+KncJgUjYd98o=
# ssh.gitlab.gnome.org:22 SSH-2.0-OpenSSH_8.0
# ssh.gitlab.gnome.org:22 SSH-2.0-OpenSSH_8.0
$ <gnome.pub ssh-keygen -lf -
3072 SHA256:WRRpoWo7szMzwlkYFeLoj0UItmVHfAI+r+hFgzwGARg ssh.gitlab.gnome.org (RSA)
256 SHA256:TiA9po6nO6jFso7wQNy4xLlth10lIfjv1dxuDabVIqw ssh.gitlab.gnome.org (ECDSA)
256 SHA256:Y9G4dWiIfi53LR3InJWsIbv4lekUHonq/HrqTTm/rcw ssh.gitlab.gnome.org (ED25519)

How can I reconcile the two formats? Ideally I would like a few flags to pass ssh-* or other commands.

The following commands might give the correct answers but are unacceptable because they are too long to remember/type and are formatted badly. My use case would be to run these once when setting up a new computer, so .bashrc aliases won't be present.

(x="$(<gnome.pub)"; for y in sha1 sha256; do echo "$x" | ssh-keygen -lf - -E "$y"; done) | xargs -d\\n -n1 bash -c "echo \"\$0\"; echo \"\$0\" | sed 's/[^:]\+:\([^ ]\+\).*/\1=/' | base64 -d | xxd -p -c 32"
resolvectl query -t sshfp ssh.gitlab.gnome.org | grep ' IN SSHFP ' | xargs -n1 -d\\n bash -c 'echo "$0"; echo "$0" | cut -d\  -f 6 | xxd -p -r | base64'
grep -v \# gnome.pub | cut -d\  -f2- | xargs -n1 -d\\n bash -c 'ssh-keygen -r ssh.gitlab.gnome.org -f <(echo "$0")'
Daniel T
  • 113

1 Answers1

2

To convert from base64 to hex, you can use perl for instance:

$ ssh-keygen -lf gnome.pub | perl -MMIME::Base64 -lpe 's{SHA256:\K\S+}{unpack("H*", decode_base64($&))}e'
256 SHA256:63d1b87568887e2e772d1dc89c95ac21bbf895e9141e89eafc7aea4d39bfadcc ssh.gitlab.gnome.org (ED25519)
3072 SHA256:591469a16a3bb33333c2591815e2e88f4508b665477c023eafe845833c060118 ssh.gitlab.gnome.org (RSA)
256 SHA256:4e203da68ea73ba8c5b28ef040dcb8c4b96d875d2521f8efd5dc6e0da6d522ac ssh.gitlab.gnome.org (ECDSA)

ssh-keyscan also has a -D option to print the output as SSHFP records:

$ ssh-keyscan -D ssh.gitlab.gnome.org
; ssh.gitlab.gnome.org:22 SSH-2.0-OpenSSH_8.0
ssh.gitlab.gnome.org IN SSHFP 1 1 9d319c15965b939bc2086cbebca96d8bbb89e9a3
ssh.gitlab.gnome.org IN SSHFP 1 2 591469a16a3bb33333c2591815e2e88f4508b665477c023eafe845833c060118
; ssh.gitlab.gnome.org:22 SSH-2.0-OpenSSH_8.0
ssh.gitlab.gnome.org IN SSHFP 3 1 17b29179778339d7c91cb2c281b7afa2798c61d5
ssh.gitlab.gnome.org IN SSHFP 3 2 4e203da68ea73ba8c5b28ef040dcb8c4b96d875d2521f8efd5dc6e0da6d522ac
; ssh.gitlab.gnome.org:22 SSH-2.0-OpenSSH_8.0
ssh.gitlab.gnome.org IN SSHFP 4 1 457e9cb0d575697e27fe8b2185580df5d45ce46b
ssh.gitlab.gnome.org IN SSHFP 4 2 63d1b87568887e2e772d1dc89c95ac21bbf895e9141e89eafc7aea4d39bfadcc
; ssh.gitlab.gnome.org:22 SSH-2.0-OpenSSH_8.0
; ssh.gitlab.gnome.org:22 SSH-2.0-OpenSSH_8.0

And ssh-keygen -r can give you the SSHFP records for a given public key, so you can also do:

$ perl -ne '
  if (/^\s*+([^#]\S*)\s+(.*)/) {
    open K, "|-", qw(ssh-keygen -f /dev/stdin -r), $1;
    print K $2;
    close K;
  }' gnome.pub
ssh.gitlab.gnome.org IN SSHFP 4 1 457e9cb0d575697e27fe8b2185580df5d45ce46b
ssh.gitlab.gnome.org IN SSHFP 4 2 63d1b87568887e2e772d1dc89c95ac21bbf895e9141e89eafc7aea4d39bfadcc
ssh.gitlab.gnome.org IN SSHFP 1 1 9d319c15965b939bc2086cbebca96d8bbb89e9a3
ssh.gitlab.gnome.org IN SSHFP 1 2 591469a16a3bb33333c2591815e2e88f4508b665477c023eafe845833c060118
ssh.gitlab.gnome.org IN SSHFP 3 1 17b29179778339d7c91cb2c281b7afa2798c61d5
ssh.gitlab.gnome.org IN SSHFP 3 2 4e203da68ea73ba8c5b28ef040dcb8c4b96d875d2521f8efd5dc6e0da6d522ac
  • Thanks for the ssh-keyscan -D and the other compact commands! I completely overlooked the -D flag. One small thing, is there a way to make ssh-keyscan print both the SSHFP and something else like the key or another fingerprint to avoid a TOCTOU between verifying and trusting? If not, I could always recover some confidence by interleaving ssh/git and ssh-keyscan a few times, which is better than nothing when my commands were too long. – Daniel T Feb 24 '24 at 19:56
  • You can always use ssh-keyscan without -D to same in your gnome.pub, compare to sshfp queries (making sure the result is signed and validated), and then use ssh -o UserKnownHostsFile=gnome.pub (or add those to your ~/.ssh/known_hosts). Or just use ssh -o VerifyHostKeyDNS once and let ssh add the keys by itself to do all that process automatically in a safer way. – Stéphane Chazelas Feb 25 '24 at 07:10