SSHの公開鍵認証のセッションIDの生成方法と、なりすまし防止の話
#中間者攻撃 #セキュリティ
経緯
「なりすましを防止して、楕円曲線ディフィー・ヘルマン鍵共有でForward secrecyなエンドーツーエンド暗号化する方法を考える」で考えた方法がSSHの公開鍵認証方式とほぼほぼ似てることが判明。以下の記事から似ていることがわかった。
SSHの公開鍵認証における良くある誤解の話 - Qiitaに正しいと思われるSSHの公開鍵認証の手法が解説されている。
SSHの公開鍵認証方式でやりたいことと同じだなと気づいて検索したはずで、SSHで使われている方法なら、安心して実装できると思える。「なりすましを防止して、楕円曲線ディフィー・ヘルマン鍵共有でForward secrecyなエンドーツーエンド暗号化する方法を考える」とSSHの公開鍵認証方式で違うのは、署名する対象。SSHの公開鍵認証方式だとセッションID(セッション識別子)を署名している。一時的な秘密鍵を署名するより安全そうで良さそうである。
そこでどうやって、セッションIDを算出しているのかが気になった。クライアントとサーバーで共通のIDを生成する必要がある。そして、クライアントとサーバーのどちらかがセッションIDを任意で決めるのは、「めくら判」になる可能性があるので、やっていないはず。めくら判が問題になる理由は、例えば悪意のあるサーバーが署名してほしいデータをクライアントに投げつけると、クライアントは署名してくれるので、悪意のあるサーバーがほしいクライアント署名済みデータを手に入れることができてしまう。
Qiitaの記事内でも紹介されている、が仕様の和訳なので詳しくはこれを見ると良さそう。
セッションIDの生成方法
Stack Overflowのセキュリティ版にセッションIDの生成方法に対応するOpenSSHのソースコードと説明を書いてくれている人がいた。
SSH session_id in RFC 4253 (key exchange) - Information Security Stack Exchange
以下のように、RFCのも引用されていて、ざっくり意味を取ると「最初に交換された鍵のハッシュをセッションIDとして使っている」という感じ。
The exchange hash H from the first key exchange is additionally used as the session identifier, which is a unique identifier for this connection.
ディフィー・ヘルマンなどで秘密鍵は得ているので、それが交換された鍵を意味しているはず。
確かに、ディフィー・ヘルマンで互いに無関係の2つ鍵を交換して、一つをセッションIDとして、もう一つを暗号化用にすれば、良さそう。