SSHの暗号化とホスト認証

SSH(Secure Shell)は、暗号化に対応していないTelnet(テルネット)、rsh(リモートシェル)、rlogin(アールログイン)の代替として利用されています。それぞれ通信プロトコル名やアプリケーション名ですが、一般的には遠隔地のサーバーを操作するために利用します。遠隔地と書きましたが、他のコンピューターという意味なので隣にあってもかまいません。

通信の暗号化

まずは通信そのものを暗号化します。SSHにはSSH1とSSH2があります。手順はそれぞれ異なりますが、データ通信自体の暗号化には共通鍵方式が用いられます。

SSH1

SSH1では、 サーバーキー が利用されます。

  1. サーバーキーの公開鍵をクライアントが受け取ります。
  2. クライアントは、サーバーとの暗号化通信(セッション)に利用する共通鍵(セッションキー)を作成します。
  3. 共通鍵をサーバーキーの公開鍵で暗号化してサーバーに送ります。
  4. サーバーは暗号化された共通鍵を、秘密鍵で復号化します。
  5. 以降、お互いに共通鍵を利用して暗号通信を行います。
サーバーキー
サーバーで一定時間毎に生成される鍵です。 ^ セッションキー
クライアントとサーバーとの暗号化通信に利用される共通鍵です。接続が終了するまで利用されます。

SSH2

SSH2では、 Diffie-Hellman鍵共有 (DH鍵共有)を利用して共通鍵を生成します。

SSH1ではサーバーキーを利用しましたが、SSH2では共通鍵の交換がありません。クライアントとサーバーがお互いに生成した公開鍵を交換することで、共通鍵が生成されます。つまり共通鍵がネットワークに流れることがありません。

数学的な話になるので詳細は省きますが、ある数式から解を求めるのは簡単だが、解から数式の要素を求めることは困難であるという 一方向性関数 の性質を利用しています。DH鍵共有では 離散対数的問題 を利用しています。

離散対数問題
$$g^a\mod n=y$$という数式で、g、a、nが分かっていればyを求めるのは簡単ですが、a以外の値(g、n、y)からaを求めることは困難というものです。

  1. クライアントとサーバーでnとgを決定します。この段階では暗号化されていませんが、知られても問題ありません。
  2. クライアントとサーバーが各自で秘密鍵aとbを作成します。\(K_A=g^a\mod n\)\(K_A=g^a\mod n\)を計算します。\(K_A\)\(K_B\)が公開鍵となり、それぞれ交換します。
  3. クライアントはサーバーの公開鍵\(K_B\)と秘密鍵aを利用して、\(K_B^a=g^{ba}\mod n\)を求めます。
  4. サーバーはクライアントの公開鍵\(K_A\)と秘密鍵bを利用して、\(K_A^b=g^{ab}\mod n\)を求めます。
  5. \(g^{ab}\mod n=g^{ba}\mod n\)となるので、\(K_A^b\)\(K_B^a\)が共通鍵となります。

あくまでも概要なので、詳しい内容は他のサイトも参考にしてください。

ホスト認証(サーバー認証)

ログインの前提として目的のサーバーと接続する必要があります。いくら通信を暗号化できるといっても、接続相手が偽物(なりすまし)だったらどうしますか?パスワード認証であればアカウントを盗難されてしまいます。

そこでホスト認証という仕組みが必要となります。暗号化通信を確立する際に行われ、クライアントはサーバーの ホストキー の公開鍵を一緒に受け取り、公開鍵暗号方式で正当なサーバーかを判断します。

  1. クライアントはホストキーの公開鍵を受け取ります。
  2. ランダムなデータを生成し、受け取った公開鍵で暗号化してサーバーに送ります。
  3. サーバーは受け取ったデータを秘密鍵で復号化します。
  4. 復号化したデータのハッシュ値を求めて、クライアントに送ります。
  5. クライアントもランダムデータのハッシュ値を求め、サーバーから受け取ったハッシュ値と比較します。

初めての接続であれば、以下の様な表示が出るでしょう。

「ホストの信頼性が不明です。それでも接続しますか?」と表示されます。 RSA key fingerprint is に公開鍵のハッシュ値が表示されているので、前もってサーバー管理者から確認している正規のハッシュ値と比較します。一致していればそのまま接続して問題ありません。不一致であれば、目的外のサーバーに接続されていることが分かります。

とは言え、レンタルサーバーでは事前にハッシュ値を確認するのは難しいでしょう。そのため、警告が出てもそのまま許可してしまうことがほとんどです。もし安全性を重視するならサポートに問い合わせるしかありません。

接続するとパソコン(クライアント)の「known_hosts」というファイルにサーバーの公開鍵が保存されます。これにより次回以降は自動的に認証が行われるため警告が表示されなくなります。目的外のサーバーに接続している場合やサーバーの公開鍵が変わっている場合、警告が表示されます。一般的にはホストキーの変更は滅多に行わなれないため、許可済みのサーバーに接続した際、 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! のような警告が出た場合は注意する必要があります。

このホスト認証が終わるとログイン処理が始まります。

ハッシュ関数/ハッシュ値/フィンガープリント
ある1つのデータから規則性のない固定長の数値を生成する関数。生成された値をハッシュ値と呼びます。同じデータからは常に同じ値が生成されるため、例えばクライアントとサーバーにあるデータが同じものかを、ハッシュ値により比較できます。このページで出てくるフィンガープリント(指紋)は、ホストキーの公開鍵のハッシュ値のことです。
ホストキー
サーバーを識別するためのキーで、基本的には永続的に利用されます。SSHサーバーの最初の起動時に自動的に生成されます。