これはなに?
sshのknown_hostsファイルを見たらハッシュ化されていて、どういうハッシュ化なのか気になったので調べた結果をメモする。
本題
known_hostsのハッシュ化?
known_hostsファイルが流出したときに備えてホスト名やアドレスを隠すための機能とのこと。1
known_hostsへのアクセスが可能な状況が想定されているので、実際の状況は様々かもしれませんが、最悪の場合、当該ユーザーのユーザーディレクトリには侵入できると想定すると、例えばプライベートネットワーク内のサーバーのアドレスが分かると攻撃者にとっては(攻撃を拡大するために)有用な情報になってしまう、ということを想定しているのかと思いました。
ハッシュ化アルゴリズムについて
こちらの記事にアルゴリズムの詳細がかかれています。
|1|uu_salt|uu_result
という形式で書かれており、 uu_salt
はソルト、 uu_result
がハッシュ値(結果)と書かれていますが、デコードしているコードとPythonのドキュメント によるとソルトと呼ばれている uu_salt
は key
と呼ばれることもあるようです。(後で openssl
で指定するときに key
として指定することの正当化)
ところで、実際にソルトと元のホスト名/アドレスからPythonでハッシュ値を得るコードがありますが、個人的にPythonはあまり使わないのでopensslなどのコマンドでできるようにしたいです。
コマンドでハッシュ値を再生成する
当然ですがハッシュ値から元のホスト名/アドレスを生成することはできないので、目的のエントリを探すには探したいホスト名/アドレスからハッシュ値を再生成して比較するしかありません。
HMAC-SHA1は openssl
で計算できるようだったのでこちらのページを参考に計算してみた。
まず ssh-keyscan
コマンドで known_hosts
ファイルのエントリを生成してみる:
$ ssh-keyscan -H -t ed25519 github.com
# github.com:22 SSH-2.0-babeld-8f627ebe
|1|A7mBfgQFBh/axJPBkhN1czQ4QXo=|ULxHU20iBKTPncOF6w/R9h59d/g= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
ここで得られたソルトを base64
でデコードして指定し、ハッシュ値を求める平文はファイルで指定するようなのでコマンド置換で github.com
という文字列を与えるとこのようになる:
$ openssl dgst -hmac "$(printf 'A7mBfgQFBh/axJPBkhN1czQ4QXo=' | base64 -d)" -sha1 <(printf 'github.com')
HMAC-SHA1(/dev/fd/63)= 50bc47536d2204a4cf9dc385eb0fd1f61e7d77f8
得られたハッシュ値は16進数表記なので、 ssh-keyscan
のハッシュ値をBase64をデコードすると
$ printf 'ULxHU20iBKTPncOF6w/R9h59d/g=' | base64 -d | od -t x1 -w24
0000000 50 bc 47 53 6d 22 04 a4 cf 9d c3 85 eb 0f d1 f6 1e 7d 77 f8
0000024
となって openssl
で得られたハッシュ値が ssh-keyscan
の結果と同じであることを確かめられた。
有用な情報
実際に known_hosts
から目的のエントリを検索したり、エントリの追加/削除がしたい場合はこちらのブログにある通り、 ssh-keyscan
(追加)/ssh-keygen
(検索/削除)を使うとよい2。