メインコンテンツまでスキップ

6. Binary Packet Protocol (バイナリパケットプロトコル)

6. Binary Packet Protocol (バイナリパケットプロトコル)

各パケットは次の形式です.

      uint32    packet_length
byte padding_length
byte[n1] payload; n1 = packet_length - padding_length - 1
byte[n2] random padding; n2 = padding_length
byte[m] mac (Message Authentication Code - MAC); m = mac_length
packet_length
The length of the packet in bytes, not including 'mac' or the
'packet_length' field itself.
padding_length
Length of 'random padding' (bytes).
payload
The useful contents of the packet. If compression has been
negotiated, this field is compressed. Initially, compression
MUST be "none".
random padding
Arbitrary-length padding, such that the total length of
(packet_length || padding_length || payload || random padding)
is a multiple of the cipher block size or 8, whichever is
larger. There MUST be at least four bytes of padding. The
padding SHOULD consist of random bytes. The maximum amount of
padding is 255 bytes.
mac
Message Authentication Code. If message authentication has
been negotiated, this field contains the MAC bytes. Initially,
the MAC algorithm MUST be "none".

'packet_length', 'padding_length', 'payload', 'random padding' の連結の長さは, 暗号ブロックサイズ (cipher block size) または 8 のいずれか大きい方の倍数でなければなりません (MUST). この制約はストリーム暗号を使用する場合でも強制されなければなりません (MUST). 'packet_length' フィールドも暗号化されるため, パケットの送受信時に特別な注意が必要です。また, 可変量の 'random padding' を挿入することは, トラフィック解析 (traffic analysis) に対抗するのに役立つ場合があります。

パケットの最小サイズは 16 バイト (または暗号ブロックサイズのうち大きい方) プラス 'mac' です。実装は, パケットの最初の 8 バイト (または暗号ブロックサイズのうち大きい方) を受信した後に長さを復号すべきです (SHOULD).

6.1. Maximum Packet Length (最大パケット長)

すべての実装は, 非圧縮ペイロード長が 32768 バイト以下, かつ総パケットサイズが 35000 バイト以下 ('packet_length', 'padding_length', 'payload', 'random padding', 'mac' を含む) のパケットを処理できなければなりません (MUST). 35000 バイトの上限は, 上記の非圧縮長より大きい任意に選んだ値です。実装は, 必要な場合により長いパケットをサポートすべきです (SHOULD). 例えば, 実装が非常に大量の証明書を送りたい場合, 識別文字列が相手がそれらを処理できることを示しているなら, より大きなパケットを送信してもよいです (MAY). ただし, 実装はサービス拒否 (denial of service) やバッファオーバーフロー攻撃を避けるため, パケット長が妥当であることを確認すべきです (SHOULD).

6.2. Compression (圧縮)

圧縮がネゴシエートされている場合, 'payload' フィールド (それのみ) がネゴシエートされたアルゴリズムで圧縮されます。'packet_length' フィールドと 'mac' は圧縮されたペイロードから計算されます。暗号化は圧縮の後に行われます。

圧縮はメソッドに応じてステートフル (stateful) であってもよいです (MAY). 圧縮は各方向で独立していなければなりません (MUST), 実装は各方向でアルゴリズムを独立して選択できなければなりません (MUST). ただし実務上は, 両方向で同じ圧縮メソッドを用いることが推奨されます (RECOMMENDED).

現在定義されている圧縮メソッドは次のとおりです.

      none     REQUIRED        no compression
zlib OPTIONAL ZLIB (LZ77) compression

"zlib" 圧縮は [RFC1950] および [RFC1951] で説明されています。圧縮コンテキストは各鍵交換の後に初期化され, パケット間で引き継がれ, 各パケットの終わりでは部分フラッシュ (partial flush) のみが行われます。部分フラッシュとは, 現在の圧縮ブロックを終了しすべてのデータを出力することを意味します。現在のブロックが格納ブロック (stored block) でない場合, 現在のブロックの end-of-block コードの先頭からパケットペイロードの末尾までに少なくとも 8 ビットがあることを保証するため, 現在のブロックの後に 1 つ以上の空ブロックが追加されます。

追加のメソッドは [SSH-ARCH] および [SSH-NUMBERS] で指定されるとおりに定義されてもよいです。

6.3. Encryption (暗号化)

暗号アルゴリズムと鍵は鍵交換中にネゴシエートされます。暗号化が有効な場合, 各パケットのパケット長, パディング長, ペイロード, パディングフィールドは, 指定されたアルゴリズムで暗号化されなければなりません (MUST).

一方向に送信されるすべてのパケット内の暗号化データは, 単一のデータストリームとして扱うべきです (SHOULD). 例えば, 初期化ベクトル (initialization vector) は 1 つのパケットの末尾から次のパケットの先頭へ渡すべきです (SHOULD). すべての暗号は, 実効鍵長 (effective key length) が 128 ビット以上の鍵を使用すべきです (SHOULD).

各方向の暗号は互いに独立して動作しなければなりません (MUST). 実装は, ローカルポリシーで複数のアルゴリズムが許可されている場合, 各方向のアルゴリズムを独立して選択できなければなりません (MUST). ただし実務上は, 両方向で同じアルゴリズムを用いることが推奨されます (RECOMMENDED).

現在定義されている暗号は次のとおりです.

      3des-cbc         REQUIRED          three-key 3DES in CBC mode
blowfish-cbc OPTIONAL Blowfish in CBC mode
twofish256-cbc OPTIONAL Twofish in CBC mode,
with a 256-bit key
twofish-cbc OPTIONAL alias for "twofish256-cbc"
(this is being retained
for historical reasons)
twofish192-cbc OPTIONAL Twofish with a 192-bit key
twofish128-cbc OPTIONAL Twofish with a 128-bit key
aes256-cbc OPTIONAL AES in CBC mode,
with a 256-bit key
aes192-cbc OPTIONAL AES with a 192-bit key
aes128-cbc RECOMMENDED AES with a 128-bit key
serpent256-cbc OPTIONAL Serpent in CBC mode, with
a 256-bit key
serpent192-cbc OPTIONAL Serpent with a 192-bit key
serpent128-cbc OPTIONAL Serpent with a 128-bit key
arcfour OPTIONAL the ARCFOUR stream cipher
with a 128-bit key
idea-cbc OPTIONAL IDEA in CBC mode
cast128-cbc OPTIONAL CAST-128 in CBC mode
none OPTIONAL no encryption; NOT RECOMMENDED

"3des-cbc" 暗号は 3 鍵トリプル DES (encrypt-decrypt-encrypt) で, 鍵の最初の 8 バイトが最初の暗号化に, 次の 8 バイトが復号に, その次の 8 バイトが最終暗号化に使用されます。これには 24 バイトの鍵データが必要です (実際に使用されるのは 168 ビット). CBC モードを実装するには, アウターチェーン (outer chaining) を使用しなければなりません (MUST) (つまり初期化ベクトルは 1 つだけ). これは 8 バイトブロックのブロック暗号です。このアルゴリズムは [FIPS-46-3] で定義されています。このアルゴリズムの実効鍵長は 112 ビットに過ぎないため ([SCHNEIER]), SSH の暗号アルゴリズムは 128 ビット以上の鍵を使うべきという仕様を満たしません。しかし歴史的な理由によりこのアルゴリズムは依然として必須 (REQUIRED) です。本書作成時点で知られている実装はほぼすべてがこのアルゴリズムをサポートしており, 相互運用の基本アルゴリズムとして広く使われています。将来, より強度の高い別のアルゴリズムが普及し "3des-cbc" が別の STANDARDS ACTION により非推奨になることが期待されます。

"blowfish-cbc" 暗号は 128 ビット鍵の Blowfish を CBC モードで使うものです ([SCHNEIER]). 8 バイトブロックのブロック暗号です。

"twofish-cbc" または "twofish256-cbc" 暗号は [TWOFISH] で説明されるとおり 256 ビット鍵の Twofish を CBC モードで使うものです。16 バイトブロックのブロック暗号です。

"twofish192-cbc" 暗号は上記と同様ですが 192 ビット鍵です。

"twofish128-cbc" 暗号は上記と同様ですが 128 ビット鍵です。

"aes256-cbc" 暗号は AES (Advanced Encryption Standard, 高度暗号化標準) [FIPS-197] を CBC モードで使うもので, 256 ビット鍵を使います。

"aes192-cbc" 暗号は上記と同様ですが 192 ビット鍵です。

"aes128-cbc" 暗号は上記と同様ですが 128 ビット鍵です。

"serpent256-cbc" 暗号は Serpent AES 提出物で説明されるとおり 256 ビット鍵の CBC モードです。

"serpent192-cbc" 暗号は上記と同様ですが 192 ビット鍵です。

"serpent128-cbc" 暗号は上記と同様ですが 128 ビット鍵です。

"arcfour" 暗号は 128 ビット鍵の Arcfour ストリーム暗号です。Arcfour 暗号は RC4 暗号と互換と考えられています ([SCHNEIER]). Arcfour (および RC4) は弱い鍵の問題があり, 注意して使用すべきです。

"idea-cbc" 暗号は IDEA 暗号を CBC モードで使うものです ([SCHNEIER]).

"cast128-cbc" 暗号は 128 ビット鍵の CAST-128 暗号を CBC モードで使うものです ([RFC2144]).

"none" アルゴリズムは暗号化を行わないことを指定します。このメソッドは機密性保護を提供しないため, 推奨されません (NOT RECOMMENDED). この暗号が選ばれた場合, セキュリティ上の理由で一部の機能 (例: パスワード認証) が無効になることがあります。

追加のメソッドは [SSH-ARCH] および [SSH-NUMBERS] で指定されるとおりに定義されてもよいです。

6.4. Data Integrity (データ完全性)

データ完全性は, 共有秘密, パケットシーケンス番号, パケット内容から計算される MAC を各パケットに含めることで保護されます。

メッセージ認証アルゴリズムと鍵は鍵交換中にネゴシエートされます。初期状態では MAC は効力を持たず, その長さはゼロでなければなりません (MUST). 鍵交換後, 選択された MAC アルゴリズムの 'mac' は, 暗号化の前に次のパケットデータの連結から計算されます.

      mac = MAC(key, sequence_number || unencrypted_packet)

ここで unencrypted_packet は 'mac' を除くパケット全体 (長さフィールド, 'payload', 'random padding'), sequence_number は uint32 として表される暗黙のパケットシーケンス番号です。sequence_number は最初のパケットでゼロに初期化され, すべてのパケットの後にインクリメントされます (暗号化または MAC の使用の有無にかかわらず). 後から鍵やアルゴリズムが再ネゴシエートされてもリセットされません。2^32 パケットごとにゼロにラップアラウンドします。パケットの sequence_number 自体はワイヤ上に送信されるパケットには含まれません。

各方向の MAC アルゴリズムは独立して動作しなければなりません (MUST), 実装は両方向でアルゴリズムを独立して選べなければなりません (MUST). ただし実務上は, 両方向で同じアルゴリズムを用いることが推奨されます (RECOMMENDED).

MAC アルゴリズムから得られる 'mac' の値は, パケットの最後の部分として暗号化せずに送信されなければなりません (MUST). 'mac' のバイト数は選ばれたアルゴリズムに依存します。

現在定義されている MAC アルゴリズムは次のとおりです.

      hmac-sha1    REQUIRED        HMAC-SHA1 (digest length = key
length = 20)
hmac-sha1-96 RECOMMENDED first 96 bits of HMAC-SHA1 (digest
length = 12, key length = 20)
hmac-md5 OPTIONAL HMAC-MD5 (digest length = key
length = 16)
hmac-md5-96 OPTIONAL first 96 bits of HMAC-MD5 (digest
length = 12, key length = 16)
none OPTIONAL no MAC; NOT RECOMMENDED

"hmac-" アルゴリズムは [RFC2104] で説明されています。"-n" MAC は結果値の先頭 n ビットのみを使用します。

SHA-1 は [FIPS-180-2], MD5 は [RFC1321] で説明されています。

追加のメソッドは [SSH-ARCH] および [SSH-NUMBERS] で指定されるとおりに定義されてもよいです。

6.5. Key Exchange Methods (鍵交換メソッド)

鍵交換メソッドは, 暗号化と認証用の一回限りのセッション鍵をどのように生成し, サーバー認証をどのように行うかを指定します。

2 つの必須 (REQUIRED) 鍵交換メソッドが定義されています.

      diffie-hellman-group1-sha1 REQUIRED
diffie-hellman-group14-sha1 REQUIRED

これらのメソッドはセクション 8 で説明されています。

追加のメソッドは [SSH-NUMBERS] で指定されるとおりに定義されてもよいです。名前 "diffie-hellman-group1-sha1" は [RFC2409] で定義される Oakley グループを用いる鍵交換メソッドに使用されます。SSH は Oakley [RFC2412] および IKE とは論理的に区別された独自のグループ識別子空間を保持しますが, 追加の 1 グループについてはワーキンググループが [RFC3526] で割り当てられた番号を採用し, 2 番目に定義されたグループの名前として diffie-hellman-group14-sha1 を用いています。実装はこれらの名前を不透明な識別子として扱い, SSH が用いるグループと IKE 用に定義されたグループの間に関係があると仮定すべきではありません。

6.6. Public Key Algorithms (公開鍵アルゴリズム)

このプロトコルは, ほぼ任意の公開鍵形式, エンコーディング, アルゴリズム (署名および/または暗号化) で動作するよう設計されています。

公開鍵型を定義する側面がいくつかあります.

  • 鍵形式 (key format): 鍵のエンコード方法と証明書の表現方法. このプロトコルの鍵 blob には鍵に加えて証明書が含まれてもよいです (MAY).

  • 署名および/または暗号アルゴリズム. 一部の鍵型は署名と暗号の両方をサポートしない場合があります。鍵の用途はポリシー表明 (例: 証明書内) によっても制限され得ます。この場合, 異なるポリシー選択肢には異なる鍵型を定義すべきです (SHOULD).

  • 署名および/または暗号化データのエンコーディング. パディング, バイト順, データ形式などに限りません.

現在定義されている公開鍵および/または証明書形式は次のとおりです.

ssh-dss           REQUIRED     sign   Raw DSS Key
ssh-rsa RECOMMENDED sign Raw RSA Key
pgp-sign-rsa OPTIONAL sign OpenPGP certificates (RSA key)
pgp-sign-dss OPTIONAL sign OpenPGP certificates (DSS key)

追加の鍵型は [SSH-ARCH] および [SSH-NUMBERS] で指定されるとおりに定義されてもよいです。

鍵型は (アルゴリズムネゴシエートまたは他のソースから) 常に明示的に分かっていなければなりません (MUST). 通常鍵 blob に含まれません。

証明書と公開鍵は次のようにエンコードされます.

      string    certificate or public key format identifier
byte[n] key/certificate data

証明書部分は長さゼロの文字列でもよいですが, 公開鍵は必須です。これは認証に用いられる公開鍵です。証明書 blob に含まれる証明書列は認可 (authorization) の提供に利用できます。

署名形式識別子を明示的に指定しない公開鍵/証明書形式は, 署名識別子として公開鍵/証明書形式識別子を使用しなければなりません (MUST).

署名は次のようにエンコードされます.

      string    signature format identifier (as specified by the
public key/certificate format)
byte[n] signature blob in format specific encoding.

"ssh-dss" 鍵形式は次の固有エンコーディングを持ちます.

      string    "ssh-dss"
mpint p
mpint q
mpint g
mpint y

ここで 'p', 'q', 'g', 'y' パラメータが署名鍵 blob を構成します。

この鍵形式での署名と検証は, SHA-1 ハッシュ [FIPS-180-2] を用いたデジタル署名標準 (Digital Signature Standard) [FIPS-186-2] に従って行われます。

得られる署名は次のようにエンコードされます.

      string    "ssh-dss"
string dss_signature_blob

'dss_signature_blob' の値は, r の後に s が続く文字列としてエンコードされます (これらは 160 ビット整数で, 長さやパディングなし, 符号なし, ネットワークバイト順).

"ssh-rsa" 鍵形式は次の固有エンコーディングを持ちます.

      string    "ssh-rsa"
mpint e
mpint n

ここで 'e' と 'n' パラメータが署名鍵 blob を構成します。

この鍵形式での署名と検証は, SHA-1 ハッシュを用いた [RFC3447] の RSASSA-PKCS1-v1_5 方式に従って実行されます。

得られる署名は次のようにエンコードされます.

      string    "ssh-rsa"
string rsa_signature_blob

'rsa_signature_blob' の値は, s を含む文字列としてエンコードされます (整数で, 長さやパディングなし, 符号なし, ネットワークバイト順).

"pgp-sign-rsa" メソッドは, 証明書, 公開鍵, 署名が OpenPGP 互換のバイナリ形式 ([RFC2440]) であることを示します。このメソッドは鍵が RSA 鍵であることを示します。

"pgp-sign-dss" は上記と同様ですが, 鍵が DSS 鍵であることを示します。