7. Key Exchange (鍵交換)
7. Key Exchange (鍵交換)
鍵交換 (key exchange, kex) は, 各側がサポートするアルゴリズムの名前リスト (name-list) を送信することから始まります。各側は各カテゴリで優先アルゴリズムを持ち, ほとんどの実装が任意の時点で同じ優先アルゴリズムを使うと仮定されます。各側は相手がどのアルゴリズムを使っているか推測してもよく (MAY), 優先メソッドに適切なら初期鍵交換パケットを送信してもよいです (MAY).
次の場合, 推測は誤りとみなされます.
-
kex アルゴリズムおよび/またはホスト鍵アルゴリズムの推測が誤り (サーバーとクライアントの優先アルゴリズムが異なる), または
-
他のアルゴリズムのいずれかについて合意できない (手順は以下セクション 7.1 で定義).
それ以外の場合, 推測は正しいとみなされ, 楽観的に送信されたパケットは最初の鍵交換パケットとして扱わなければなりません (MUST).
ただし推測が誤りで, 一方または両方が楽観的にパケットを送信した場合, そのようなパケットは (推測の誤りが初期パケットの内容に影響しない場合でも) 無視されなければならず (MUST), 適切な側は正しい初期パケットを送信しなければなりません (MUST).
鍵交換メソッドが鍵交換メッセージに署名またはサーバーの真正性の他の証明を含む場合, 明示的なサーバー認証 (explicit server authentication) を用います。サーバーが共有秘密 K を知っていることを, クライアントが検証できるメッセージと対応する MAC を送ることで証明しなければならない場合, 暗黙のサーバー認証 (implicit server authentication) を用います。
本文書で定義される鍵交換メソッドは明示的なサーバー認証を用います。ただし暗黙のサーバー認証を用いる鍵交換メソッドもこのプロトコルで使用してもよいです (MAY). 暗黙のサーバー認証による鍵交換の後, クライアントはさらにデータを送信する前にサービス要求メッセージへの応答を待たなければなりません (MUST).
7.1. Algorithm Negotiation (アルゴリズムのネゴシエーション)
鍵交換は各側が次のパケットを送信することから始まります.
byte SSH_MSG_KEXINIT
byte[16] cookie (random bytes)
name-list kex_algorithms
name-list server_host_key_algorithms
name-list encryption_algorithms_client_to_server
name-list encryption_algorithms_server_to_client
name-list mac_algorithms_client_to_server
name-list mac_algorithms_server_to_client
name-list compression_algorithms_client_to_server
name-list compression_algorithms_server_to_client
name-list languages_client_to_server
name-list languages_server_to_client
boolean first_kex_packet_follows
uint32 0 (reserved for future extension)
各アルゴリズムの name-list は, アルゴリズム名のカンマ区切りリストでなければなりません (MUST) ([SSH-ARCH] のアルゴリズム命名および [SSH-NUMBERS] の追加情報を参照). 各サポート (許可) アルゴリズムは, 最も優先度が高いものから低いものへの順でリストされなければなりません (MUST).
各 name-list の最初のアルゴリズムは, 優先 (推測) アルゴリズムでなければなりません (MUST). 各 name-list には少なくとも 1 つのアルゴリズム名が含まれていなければなりません (MUST).
cookie
The 'cookie' MUST be a random value generated by the sender.
Its purpose is to make it impossible for either side to fully
determine the keys and the session identifier.
kex_algorithms
Key exchange algorithms were defined above. The first
algorithm MUST be the preferred (and guessed) algorithm. If
both sides make the same guess, that algorithm MUST be used.
Otherwise, the following algorithm MUST be used to choose a key
exchange method: Iterate over client's kex algorithms, one at a
time. Choose the first algorithm that satisfies the following
conditions:
+ the server also supports the algorithm,
+ if the algorithm requires an encryption-capable host key,
there is an encryption-capable algorithm on the server's
server_host_key_algorithms that is also supported by the
client, and
+ if the algorithm requires a signature-capable host key,
there is a signature-capable algorithm on the server's
server_host_key_algorithms that is also supported by the
client.
If no algorithm satisfying all these conditions can be found, the
connection fails, and both sides MUST disconnect.
server_host_key_algorithms
A name-list of the algorithms supported for the server host
key. The server lists the algorithms for which it has host
keys; the client lists the algorithms that it is willing to
accept. There MAY be multiple host keys for a host, possibly
with different algorithms.
Some host keys may not support both signatures and encryption
(this can be determined from the algorithm), and thus not all
host keys are valid for all key exchange methods.
Algorithm selection depends on whether the chosen key exchange
algorithm requires a signature or an encryption-capable host
key. It MUST be possible to determine this from the public key
algorithm name. The first algorithm on the client's name-list
that satisfies the requirements and is also supported by the
server MUST be chosen. If there is no such algorithm, both
sides MUST disconnect.
encryption_algorithms
A name-list of acceptable symmetric encryption algorithms (also
known as ciphers) in order of preference. The chosen
encryption algorithm to each direction MUST be the first
algorithm on the client's name-list that is also on the
server's name-list. If there is no such algorithm, both sides
MUST disconnect.
Note that "none" must be explicitly listed if it is to be
acceptable. The defined algorithm names are listed in Section
6.3.
mac_algorithms
A name-list of acceptable MAC algorithms in order of
preference. The chosen MAC algorithm MUST be the first
algorithm on the client's name-list that is also on the
server's name-list. If there is no such algorithm, both sides
MUST disconnect.
Note that "none" must be explicitly listed if it is to be
acceptable. The MAC algorithm names are listed in Section 6.4.
compression_algorithms
A name-list of acceptable compression algorithms in order of
preference. The chosen compression algorithm MUST be the first
algorithm on the client's name-list that is also on the
server's name-list. If there is no such algorithm, both sides
MUST disconnect.
Note that "none" must be explicitly listed if it is to be
acceptable. The compression algorithm names are listed in
Section 6.2.
languages
This is a name-list of language tags in order of preference
[RFC3066]. Both parties MAY ignore this name-list. If there
are no language preferences, this name-list SHOULD be empty as
defined in Section 5 of [SSH-ARCH]. Language tags SHOULD NOT
be present unless they are known to be needed by the sending
party.
first_kex_packet_follows
Indicates whether a guessed key exchange packet follows. If a
guessed packet will be sent, this MUST be TRUE. If no guessed
packet will be sent, this MUST be FALSE.
After receiving the SSH_MSG_KEXINIT packet from the other side,
each party will know whether their guess was right. If the
other party's guess was wrong, and this field was TRUE, the
next packet MUST be silently ignored, and both sides MUST then
act as determined by the negotiated key exchange method. If
the guess was right, key exchange MUST continue using the
guessed packet.
SSH_MSG_KEXINIT メッセージ交換の後, 鍵交換アルゴリズムが実行されます。鍵交換メソッドで指定されるとおり, 複数回のパケット交換が含まれる場合があります。
当事者が鍵交換または再交換のために SSH_MSG_KEXINIT メッセージを送信したら, SSH_MSG_NEWKEYS メッセージ (セクション 7.3) を送信するまで, 次以外のメッセージを送信してはなりません (MUST NOT).
-
トランスポート層汎用メッセージ (1 から 19) (ただし SSH_MSG_SERVICE_REQUEST と SSH_MSG_SERVICE_ACCEPT を送信してはなりません (MUST NOT));
-
アルゴリズムネゴシエーションメッセージ (20 から 29) (ただし追加の SSH_MSG_KEXINIT メッセージを送信してはなりません (MUST NOT));
-
特定の鍵交換メソッドのメッセージ (30 から 49).
セクション 11 の規定は認識されないメッセージに適用されます。
ただし鍵の再交換中は, SSH_MSG_KEXINIT メッセージを送信した後, 各当事者は, 相手から SSH_MSG_KEXINIT メッセージを受信する前に飛行中 (in-flight) にあり得る任意の数のメッセージを処理する準備ができていなければなりません (MUST).
7.2. Output from Key Exchange (鍵交換の出力)
鍵交換は 2 つの値を生成します: 共有秘密 K と交換ハッシュ H. 暗号化鍵と認証鍵はこれらから派生します。最初の鍵交換からの交換ハッシュ H はさらにセッション識別子 (session identifier) として使用され, この接続の一意の識別子です。認証メソッドでは, 秘密鍵の保有の証明として署名されるデータの一部として用いられます。一度計算されたセッション識別子は, 後から鍵が再交換されても変更されません。
各鍵交換メソッドは鍵交換で用いるハッシュ関数を指定します。鍵導出 (key derivation) でも同じハッシュアルゴリズムを使用しなければなりません (MUST). ここではこれを HASH と呼びます。
暗号化鍵は次のように, 既知の値と K の HASH として計算されなければなりません (MUST).
-
クライアントからサーバーへの初期 IV (Initialization Vector): HASH(K || H || "A" || session_id) (ここで K は mpint として, "A" はバイトとして, session_id は生データとしてエンコードされます. "A" は文字 A 1 文字, ASCII 65 を意味します).
-
サーバーからクライアントへの初期 IV: HASH(K || H || "B" || session_id)
-
クライアントからサーバーへの暗号化鍵: HASH(K || H || "C" || session_id)
-
サーバーからクライアントへの暗号化鍵: HASH(K || H || "D" || session_id)
-
クライアントからサーバーへの完全性鍵: HASH(K || H || "E" || session_id)
-
サーバーからクライアントへの完全性鍵: HASH(K || H || "F" || session_id)
鍵データはハッシュ出力の先頭から取得されなければなりません (MUST). 必要なバイト数だけハッシュ値の先頭から取ります。必要な鍵長が HASH の出力より長い場合, K と H とこれまでの鍵全体の連結の HASH を計算し, 得られたバイト (HASH が生成する分だけ) を鍵に追加することで鍵を拡張します。この処理を十分な鍵素材が得られるまで繰り返します。鍵はこの値の先頭から取ります。言い換えると.
K1 = HASH(K || H || X || session_id) (X is e.g., "A")
K2 = HASH(K || H || K1)
K3 = HASH(K || H || K1 || K2)
...
key = K1 || K2 || K3 || ...
K に含まれるエントロピー量が HASH の内部状態サイズより大きい場合, この処理はエントロピーを失います。
7.3. Taking Keys Into Use (鍵の使用開始)
鍵交換は各側が SSH_MSG_NEWKEYS メッセージを送信することで終了します。このメッセージは古い鍵とアルゴリズムで送信されます。このメッセージの後に送信されるすべてのメッセージは, 新しい鍵とアルゴリズムを使用しなければなりません (MUST).
このメッセージを受信したら, 受信には新しい鍵とアルゴリズムを使用しなければなりません (MUST).
このメッセージの目的は, 鍵交換に問題が生じた場合に, 当事者が相手が理解できる SSH_MSG_DISCONNECT メッセージで応答できることを保証することです.
byte SSH_MSG_NEWKEYS