Transport Layer Security Working Group Alan O. Freier INTERNET-DRAFT Netscape Communications Expire in six months Philip Karlton Netscape Communications Paul C. Kocher Independent Consultant November 18, 1996 SSL プロトコル バージョン 3.0 このメモの位置付け このドキュメントはインターネットドラフトである。インターネットドラフトは、 Internet Engineering Task Force(IETF)とそのエリア、そしてそのワーキング グループにおいて作成中のドキュメントのことである。その他のグループが、 作成中のドキュメントをインターネットドラフトとして配布することも認められ ている。 インターネットドラフトは最大6ヶ月間有効で、その後アップデートや置き換え をすることができる。もしくは、他のドキュメントによりいつでも無効にする ことができる。インターネットドラフトを参考文献として引用すること、もし くは "work in progress" 以上の扱いで引用するのは適切ではない。 インターネットドラフトの現在のステータスは、インターネットドラフトの ミラーサイトds.internic.net (US東海岸)、nic.nordu.net(ヨーロッパ)、 ftp.isi.edu (US西海岸)、munnari.oz.au (太平洋岸)にある、1id-abstracts.txt のリストを参照のこと。 要旨 本ドキュメントでは、Secure Sockets Layerのバージョン3.0 (SSL V3.0)プロト コルを規定する。SSLプロトコルは、インターネット上で通信プライバシーを 提供する。本プロトコルを使用することにより、クライアント/サーバアプリ ケーションは、盗聴、改竄、またはメッセージ偽造を防ぐように設計された 方法を使用して通信を行うことが出来る。 目次 このメモの位置付け 1 要旨 1 目次 2 1. はじめに 4 2. 目的 4 3. このドキュメントの目的 5 4. 表記言語 5 4.1 基本ブロックサイズ 5 4.2 その他 6 4.3 ベクトル 6 4.4 数値 7 4.5 列挙 7 4.6 構造体 8 4.6.1 バリエーション 8 4.7 暗号属性 9 4.8 定数 10 5. SSLプロトコル 10 5.1 セションとコネクションのステータス 10 5.2 レコード層 12 5.2.1 フラグメンテーション 12 5.2.2 圧縮と展開 13 5.2.3 レコード送受信中の保護とCipherSpec 13 5.2.3.1 Nullまたは標準ストリーム暗号 14 5.2.3.2 CBCブロック暗号 15 5.3 ChangeCipherSpecプロトコル 16 5.4 アラートプロトコル 16 5.4.1 終了アラート 17 5.4.2 エラーアラート 17 5.5 ハンドシェイクプロトコル概要 18 5.6 ハンドシェイクプロトコル 20 5.6.1 Helloメッセージ 21 5.6.1.1 HelloRequestメッセージ 21 5.6.1.2 ClientHelloメッセージ 21 5.6.1.3 ServerHelloメッセージ 24 5.6.2 ServerCertificateメッセージ 25 5.6.3 ServerKeyExchangeメッセージ 25 5.6.4 CertificateRequestメッセージ 27 5.6.5 ServerHelloDoneメッセージ 27 5.6.6 ClientCertificateメッセージ 28 5.6.7 ClientKeyExchangeメッセージ 28 5.6.7.1 RSAを使用したEncryptedPreMasterSecretメッセージ 28 5.6.7.2 FORTEZZA鍵交換メッセージ 29 5.6.7.3 ClientDiffieHellmanPublic値 30 5.6.8 CertificateVerifyメッセージ 30 5.6.9 Finishedメッセージ 31 5.7 アプリケーションデータプロトコル 32 6. 暗号計算 32 6.1 非対称暗号計算 32 6.1.1 RSA 32 6.1.2 Diffie-Hellman 33 6.1.3 FORTEZZA 33 6.2 対称暗号計算とCipherSpec 33 6.2.1 マスターシークレット 33 6.2.2 マスターシークレットからの鍵とMACシークレット生成 33 6.2.2.1 輸出可能な暗号の鍵生成例 35 A. プロトコル定数値 36 A.1 予約されているポート番号 36 A.1.1 レコード層 36 A.2 ChangeCipherSpecメッセージ 37 A.3 アラートメッセージ 37 A.4 ハンドシェイクプロトコル 37 A.4.1 各種Helloメッセージ 38 A.4.2 サーバ認証と各種鍵交換メッセージ 39 A.5 クライアント認証と各種鍵交換メッセージ 40 A.5.1 ハンドシェイク完了メッセージ 41 A.6 CipherSuite 41 A.7 CipherSpec 42 B. 用語集 44 C. 暗号スイートの定義 47 D. 実装上の注意 49 D.1 一時的RSA鍵 49 D.2 乱数生成とその種 49 D.3 証明書と認証 50 D.4 暗号スイート 50 D.5 FORTEZZA 50 D.5.1 FORTEZZAハードウエアの使用に関する注記 50 D.5.2 FORTEZZA の暗号スイート 51 D.5.3 FORTEZZA におけるセション再利用 51 E. バージョン2.0との下位互換 52 E.1 バージョン2のClientHello 52 E.2 なりすましによるバージョンロールバック攻撃の回避 53 F. セキュリティ解析 55 F.1 ハンドシェイクプロトコル 55 F.1.1 認証と鍵交換 55 F.1.1.1 匿名鍵交換 55 F.1.1.2 RSA鍵交換と認証 56 F.1.1.3 認証を伴うDiffie-Hellman鍵交換 57 F.1.1.4 FORTEZZA 57 F.1.2 バージョンロールバック攻撃 57 F.1.3 ハンドシェイクプロトコルに対する攻撃の検出 58 F.1.4 セションの再利用 58 F.1.5 MD5とSHA 58 F.2 アプリケーションデータの保護 59 F.3 最終注記 59 G. 特許声明 60 参考文献 61 著者 62 1. はじめに SSLプロトコルの主な目的は、通信を行う2つのアプリケーション間に、通信プラ イバシーと信頼性を提供することである。プロトコルは2つの層から構成されて いる。信頼のおける伝送プロトコル(例えば、TCP [TCP])のすぐ上、最も低い レベルに位置するのがSSLレコードプロトコルである。SSLレコードプロトコルは、 より上位に位置するさまざまなプロトコルのカプセル化を行う。カプセル化される プロトコルの1つであるSSLハンドシェイクプロトコルでは、アプリケーション プロトコルの最初のデータを送信または受信する前に、サーバとクライアントの 相互認証、暗号化アルゴリズムと暗号鍵のネゴシエーションを行うことができる。 SSLの利点の1つは、アプリケーションプロトコルから独立していることである。 SSLプロトコルを透過的なものとした、より上位のプロトコルを形成すること ができる。SSLプロトコルにより、次の3つの基本的特性をもつコネクション セキュリティが提供される。 - コネクションはプライベートである。最初に行われるハンドシェイクにより 秘密鍵を決定した後、暗号化が行われる。対称暗号がデータ暗号化に使用され る(例えば、DES [DES]、RC4 [RC4]など)。 - コネクションの両端のアイデンティティは、非対称すなわち公開鍵暗号 (例えば、RSA [RSA]、DSS [DSS]など) を使用して認証することができる。 - コネクションは信頼できる。メッセージ送受信が行われる際には、鍵付き MACを使用したメッセージの保全チェックが行われる。MACを計算するため に、安全なハッシュ関数(例えば SHA、MD5など)が使用される。 2. 目的 SSLプロトコルバージョン3の目的を、重要な順に示す。 1. 暗号セキュリティ: SSLは、2つのパーティー間で安全なコネクションを 確立するのに使用される。 2. 共同利用性: それぞれのプログラマは、互いのコードに関する知識を必要 とすることなく、暗号パラメータを問題なく交換することができるSSL 3.0 アプリケーションを、個別に開発することができる。 注: これは、すべてのSSLのインスタンスが(同じアプリケーションドメイン であったとしても)コネクションに成功するということではない。例えば、 サーバがある特別なハードウエアトークンをサポートしており、そして クライアントにはそのようなトークンにアクセスする手段がない場合、 コネクションは確立しないであろう。 3. 拡張性: SSLは、新しい公開鍵暗号方式と大量暗号方式を、必要なときに組み 込むことのできるフレームワークの提供を行っている。また、これにより さらに次の2つの目標を達成することが出来る。それは新しいプロトコルの 作成(そして、新しい弱点を招くという危険)を防ぐこと、そして完全に新しい セキュリティライブラリを実装する必要性を避けることである。 4. 相対的な効率: 暗号化処理、特に公開鍵暗号処理は、CPU負荷が高いと いう傾向がある。そのため、SSLプロトコルではオプショナルで、ゼロから 確立する必要のあるコネクションの数を減少させるために、セションの キャッシングを行うという手法を導入した。さらに、ネットワーク通信量 を減少させるための配慮も行っている。 3. このドキュメントの目的 SSLプロトコルバージョン3.0規定は主として、プロトコルを実装しようとして いる人と、その暗号分析を行おうとする人を対象として書かれている。この規格書 はこれを念頭に書かれており、またそれらの2つのグループの必要性を反映する ように意図されている。これらの理由から、アルゴリズムに依存する多くのデータ 構造と多くの規則を、(付録だけでなく)本文にも含めており、より簡単に参照する ことができるようになっている。 このドキュメントでは、サービスの定義や、インターフェースの定義に関する 詳細については述べていない。しかし、ポリシーに関する分野の一部をカバー している。それは堅固なセキュリティを維持するのに必要であるからである。 4. 表記言語 このドキュメントでは、データフォーマットを、コンピュータの内部表現に 依存しない一般的な表現で扱う。以下に示されるような、非常に基本的で、 かつ幾分カジュアルに定義されたプレゼンテーション構文を使用する。構文には その元になっている構造がいくつか存在する。構文は、プログラミング言語"C" の構文と、XDR [XDR]の構文とその目的に類似しているが、あまりに多くを類似 させるのは危険である。このプレゼンテーション言語の目的は、SSLのみを説明 することであり、その目的を超えた適用を行うことではない。 4.1 基本ブロックサイズ すべてのデータ項目は、明確に定義される。基本的なデータブロックサイズは 1バイト(すなわち 8ビット)である。多重バイトで構成されるデータ項目は、 バイトを連鎖させたもので、左から右、先端から下部へバイトデータを連鎖させる。 バイトストリームから多重バイト項目(例えば1つの数値)を形成するには、(C記法 を使用して)次のように行われる。 value = (byte[0] << 8*(n-1)) | (byte[1] << 8*(n-2)) | ... | byte[n-1]; この多重バイトにおけるバイト順序は、通常のネットワークバイト順序、すな わちビックエンディアン形式である。 4.2 その他 コメントは"/*"で始まり、"*/"で終わる。 オプショナルコメントは、"[[ ]]"の、2重括弧でくくられる。 解析の行われないデータを含む1バイトのエンティティを、opaque型とする。 4.3 ベクトル ベクトル(1次元配列)は、単一データ要素のストリームである。ベクトルのサイズは、 本ドキュメントで指定されるものもあれば、実行時まで不定な状態であるものもある。 どちらの場合でも、宣言される長さはそのベクトルのバイト数であり、要素数では ない。T型の固定長ベクトルを持つ新しい T' 型を指定するための構文は、以下の ようなものである。 T T'[n]; ここでT'は、データストリーム上でnバイトを占有する。nはTのサイズの整数倍 である。エンコードされたストリームには、ベクトル長データは含まれない。 以下の例では、Datumは、連続した3バイトで定義されるもので、このプロトコル では解析が行われない。一方Dataは、3つの連続したDatumで定義されるもので、 合計9バイトを使用する。 opaque Datum[3]; /* 解析の行われない3バイトベクトル */ Datum Data[9]; /* 3つの連続した3バイトのベクトル */ 可変長ベクトルは、表記を使用して、規定上の範囲を指定する ことにより定義される。これをエンコードしたときには、その長さを示すデータが、 ベクトルのコンテンツの前に付加される。このときには、ベクトルにおいて 指定された最大(ceiling)の長さを保持するために必要なバイト長が確保される。 実際の長さがゼロである可変長ベクトルを、空ベクトルと呼ぶ。 T T'; 以下の例では、mandatoryは、opaque型をもつ300から400バイトのベクトルである。 空にはならない。ベクトルの実際の長さを格納するフィールドは2バイトすなわち uint16を使用する。これは値400を格納するのに十分である(第4.4章を参照)。 一方longerは、最大800バイトまでのデータ、またはuint16型をもつ最大400個の データを表す。これは空ベクトルになってもよい。そのエンコードにおいては、 ベクトルの前に、実際の長さを表す2バイトのフィールドが含まれる。 opaque mandatory<300..400>; /* データ長を格納するフィールドは2バイトである。空であって はならない */ uint16 longer<0..800>; /* ゼロから400までの、16ビット符号なし整数 */ 4.4 数値 基本的な数値データ型は、符号なしバイト(uint8)である。それより大きい数値 データ型はすべて、第4.1章で示されるように、固定長バイトを連鎖させること により形成される。それらにもまた符号はない。 以下の数値型がすでに定義 されている。 uint8 uint16[2]; uint8 uint24[3]; uint8 uint32[4]; uint8 uint64[8]; 4.5 列挙 列挙と呼ばれる、断続的な値をもつデータ型が使用される。列挙型のフィールド には、その定義内において宣言された値のみが割り当てられる。それぞれの定義 同士は、異なる型をもつ。同じ型をもつ列挙同士のみが代入、比較される。 列挙におけるすべての要素には、以下の例で示されるように値が割り当てられな ければならない。列挙におけるそれぞれの要素の順番は問われないため、どの ような値をどのような順序で割り当てても構わない。 enum { e1(v1), e2(v2), ... , en(vn), [[(n)]] } Te; 列挙においては、定義されている序数の最大値を表すのに必要なメモリ量を バイトストリームとして占有する。以下の定義では、Color型フィールドとして 1バイトが使用される。 enum { red(3), blue(5), white(7) } Color; ある値をタグなしで指定することにより、型サイズの定義を強制することが できる。以下の例では、Tasteはデータストリームとして2バイトを使用するが、 割り当てられている値は1、2または4だけである。 enum { sweet(1), sour(2), bitter(4), (32000) } Taste; 列挙における各要素の名前は、定義された型の中のみで有効である。最初の 例では、列挙の2番目の要素に対する正確な参照方法は、Color.blueである。 ただし代入される値のターゲットが明白であれば、必ずしもこのように指定 する必要はない。 Color color = Color.blue; /* 十分な指定。文法的に正確 */ Color color = blue; /* これは正しい。型が明白。 */ 内部でのみ使用され、一般的な表記に変換されることのない列挙に関しては、 数値情報を省略してもよい。 enum { low, medium, high } Amount; 4.6 構造体 構造体は、基本的なデータ型から構成される。それぞれの定義では、新しく、 そして唯一の型を宣言する。定義構文はC言語に似たものである。 struct { T1 f1; T2 f2; ... Tn fn; } [[T]]; 構造体内のフィールドは、列挙において利用可能な構文に似た構文を使用し、 型名を使用することで指定することが出来る。例えばT.f2は、先の宣言における 2番目のフィールドを参照する。構造体の定義はネストしてもよい。 4.6.1 バリエーション 構造体では、その環境で利用できる情報に基づいたバリエーションを持つことが 出来る。このときのセレクタは、その構造体で定義しているバリエーションを 定義するための列挙型でなければならない。selectで宣言されている列挙型に 含まれるすべての要素に対して、case文による処理が表記されていなければなら ない。構造体のバリエーション部分には、参照のためにラベルを付与してもよい。 どのバリエーションが実行時に選択されるかのメカニズムについては、ここで 使用している言語では規定されない。 struct { T1 f1; T2 f2; .... Tn fn; select (E) { case e1: Te1; case e2: Te2; .... case en: Ten; } [[fv]]; } [[Tv]]; 例: enum { apple, orange } VariantTag; struct { uint16 number; opaque string<0..10>; /* 可変長 */ } V1; struct { uint32 number; opaque string[10]; /* 固定長 */ } V2; struct { select (VariantTag) { /* セレクタの値が含まれる */ case apple: V1; /* バリエーションの型, tag = apple */ case orange: V2; /* バリエーションの型, tag = orange */ } variant_body; /* バリエーションのラベル(オプショナル) */ } VariantRecord; 構造体のバリエーションは、型の前にセレクタのための値を指定することに よって、定義(固定)することが出来る。例えば、 orange VariantRecord は、V2型のバリエーションを持つ、VariantRecordの宣言となる。 4.7 暗号属性 4つの暗号処理、すなわちデジタル署名、ストリーム暗号、ブロック暗号、公開鍵 暗号ではそれぞれ、データをデジタル的に署名し、ストリーム的に暗号化し、 ブロックごとに暗号化し、公開鍵で暗号化する。あるフィールドに対する暗号処理 は、そのフィールドの型宣言の前に、適切なキーワードを付与することによって 指定される。暗号化鍵は、カレントのセションステータスによって決定される (第5.1章を参照のこと)。 デジタル署名においては、署名アルゴリズムへの入力として、一方向ハッシュ 関数の出力を使用する。RSA署名においては、2つのハッシュ値(1つはSHA、もう 1つはMD5)をもつ、36バイトの構造体に署名する(私有鍵により暗号化される)。 DSSにおいては、SHAによりハッシュされた20バイトのデータが、さらにハッシュ 処理されることなく、デジタル署名アルゴリズム(DSA)に直接渡される。 ストリーム暗号では、平文は、暗号的に安全な鍵付き擬似乱数発生器により 生成された、平文と同じ量の出力と、排他的OR処理される。 ブロック暗号では、それぞれの平文ブロックは、1つの暗号文ブロックに暗号化 される。平文(すなわち送信されるデータ)を、必要なブロックサイズ(通常は 64ビット)に正確に分割することは通常出来そうにないため、ブロックサイズに 満たないブロックには、ある決まったパターンのデータ、通常0、を付加する。 公開鍵暗号では、"落とし戸"となるシークレットを利用した一方向関数を使用 して、送信するデータを暗号化する。ある鍵ペアのうちの公開鍵を使用して暗号 化されたデータは、対応する私有鍵を使用してのみ、復号することができる。 また逆も同様である。例えば次の例では、 stream-ciphered struct { uint8 field1; uint8 field2; digitally-signed opaque hash[20]; } UserType; hashの内容が、そのまま署名アルゴリズムへ入力される。そして、構造体全体 がストリーム暗号で暗号化される。 4.8 定数 必要な型を宣言し値をそれに割当てることにより、型をもつ定数を定義すること ができる。特定の型(opaque、可変長ベクトル、およびopaqueを含む構造体)に 値を割り当てることはできない。複数の要素を持つ構造体またはベクトルでは、 フィールドを省略することはできない。 例: struct { uint8 f1; uint8 f2; } Example1; Example1 ex1 = {1, 4};/* f1 = 1, f2 = 4 の割り当て */ 5. SSLプロトコル SSLは、複数の層から構成されている。各層のメッセージは、データ長フィールド、 メッセージ情報フィールド、そしてコンテンツから構成されている。SSLは、 上位層から渡されたメッセージを受け取り、データを処理しやすいブロックへ 分解し、任意でデータを圧縮し、MACを適用し、暗号化し、結果を下位レベル層 に渡す。また下位レベル層から受け取ったデータを復号し、検証し、展開し、 組み立て直して、上位レベルのクライアントに渡す。 5.1 セションとコネクションのステータス SSLセションはステータスをもつ。クライアントとサーバ間でのステータスの 合意は、SSLハンドシェイクプロトコルによって行われる。その結果、両者の ステータスは全く同じではないものの、それぞれのプロトコルステータス間 では、まったく問題なく処理することが可能となる。論理的には、ステータス は2つある。1つはカレントの処理ステータス、そしてもう1つは(ハンドシェ イクプロトコル中の)未定ステータスである。さらに、読み込みと書き出し ステータスは別々に維持される。クライアントまたはサーバがChangeCipherSpec メッセージを受信したときには、未定読み込みステータスをカレントの読み込み ステータスにコピーする。クライアントまたはサーバがChangeCipherSpecメッ セージを送信したときには、未定書き出しステータスをカレントの書き出し ステータスにコピーする。ハンドシェイクネゴシエーションが完了したとき には、クライアントとサーバはChangeCipherSpecメッセージを交換し(第5.3節 を参照)、新規に合意された暗号スペックを使用して通信が行われる。 SSLセションには、複数の安全なコネクションが存在してもよい。さらにパー ティー間においては、複数のセションを同時に使用してもよい。 セションステータスには、以下の要素が含まれている。 セション識別子 アクティブセションステータスもしくは再利用可能 セションステータスを識別するために、サーバに よって選択される任意のバイト列。 ピア証明書 ピアのX509v3 [X509]証明書。ステータスにおける この要素は空でもよい。 圧縮方式 データを圧縮するためのアルゴリズム。暗号化の前に 適用される。 暗号スペック 大量暗号化アルゴリズム(例えばnull、DESなど)と、 MACアルゴリズム(例えばMD5やSHAなど)を特定するもの。 また、hash_sizeなどの暗号属性の定義も行う。(正式 な定義に関しては付録 A.7を参照。) マスターシークレット クライアントとサーバの間で共有される48バイトの シークレット。 再利用可能性 新しいコネクションを開始するのに、そのセションを 利用することができるかどうかを示すフラグ。 コネクションステータスには、以下の要素が含まれている。 サーバ乱数とクライアント乱数 それぞれのコネクションにおいて、サーバまたはクライ アントによって選択されたバイト列。 サーバ書き出しMACシークレット サーバによって書き出されるデータに対して行われる MAC演算のためのシークレット。 クライアント書き出しMACシークレット クライアントによって書き出されるデータに対して行われる MAC演算のためのシークレット。 サーバ書き出し鍵 サーバがデータを暗号化し、クライアントがそれを復号 するために使用する、大量暗号アルゴリズムの鍵。 クライアント書き出し鍵 クライアントがデータを暗号化し、サーバがそれを復号 するために使用する、大量暗号アルゴリズムの鍵。 初期ベクトル ブロック暗号がCBCモードで使用されるときには、 それぞれの鍵に対して初期ベクトル(IV)が維持される。 このフィールドはSSLハンドシェイクプロトコルにより 初期化される。以後、それぞれのレコードの最後の 暗号ブロックが保存され、その次のレコードの処理に 使用される。 シーケンス番号 それぞれのパーティーでは、それぞれのコネクション に対する読み込み、書き出し用の番号は別々に維持 される。パーティーがChangeCipherSpecメッセージを 送信または受信したときには、適切なシーケンス番号 が0にセットされる。シーケンス番号は、uint64型で あり、2^64-1を超えない。 5.2 レコード層 SSLレコード層は、 上位レベルの層から、任意サイズの空でないブロックデータ を受け取る。このデータは解析されない。 5.2.1 フラグメンテーション レコード層では、情報ブロックを、2^14バイト以下のSSLPlaintextレコード データにフラグメントする。クライアントメッセージの境界はレコード層では 保持されない(すなわち、同じContentTypeを持つ複数のクライアントメッセージ は、1つのSSLPlaintextレコードとして結合されるかもしれない)。 struct { uint8 major, minor; } ProtocolVersion; enum { change_cipher_spec(20), alert(21), handshake(22), application_data(23), (255) } ContentType; struct { ContentType type; ProtocolVersion version; uint16 length; opaque fragment[SSLPlaintext.length]; } SSLPlaintext; type フラグメントされたデータを処理する上位のプロトコル。 version 使用されるプロトコルのバージョン。 このドキュメントでは SSLバージョン3.0を記述している(付録 A.1.1を参照)。 length 次のSSLPlaintext.fragmentの長さ(単位バイト)。長さは 2^14を 超えない。 fragment アプリケーションデータ。 このデータは透過で、typeフィールドで 指定されている上位プロトコルによって処理されるよう、独立した ブロックとして処理される。 注: 異なるSSLレコード層コンテンツタイプを持つデータが割り込んでいても よい。アプリケーションデータは一般に、転送に際しては他のコンテンツ タイプよりも優先度が低い。 5.2.2 圧縮と展開 すべてのレコードは、カレントのセションステータスで定義されている圧縮 アルゴリズムを使用して圧縮される。常に、アクティブ状態の圧縮アルゴリズム が存在する。しかし、初期化時にはCompressionMethod.nullとして定義される。 圧縮アルゴリズムにより、SSLPlaintext構造体はSSLCompressed構造体に変換 される。圧縮関数では、CipherSpecが変更されたときには、そのステータス情報 を消去する。 注: CipherSpecは、第5.1節で記述されているセションステータスの一部で ある。CipherSpecのフィールドへの参照は、プレゼンテーション構文を 使用して、このドキュメント全体を通じで行われている。CipherSpecの より完全な記述は、付録A.7で示されている。 圧縮においては、ロスがあってはならず、その長さは1024バイト以上増加しては ならない。展開関数においてSSLCompressed.fragmentを展開したとき、その長さ が2^14バイトを超えた場合は、fatalレベルの decompression failureアラート (第5.4.2節)で応答しなければならない。 struct { ContentType type; /* SSLPlaintext.type に同じ */ ProtocolVersion version;/* SSLPlaintext.version に同じ */ uint16 length; opaque fragment[SSLCompressed.length]; } SSLCompressed; length 次のSSLCompressed.fragmentの長さ(単位バイト)。 長さは、2^14 + 1024を超えない。 fragment SSLPlaintext.fragmentを圧縮したもの。 注: CompressionMethod.null 演算が、唯一の演算である。他に代わるものは ない(付録 A.4.1を参照)。 実装上の注意: 展開を行う関数は、メッセージ処理により内部バッファのオーバー フローを起こすことがないことを保証する責任がある。 5.2.3 レコード送受信中の保護とCipherSpec すべてのレコードは、カレントのCipherSpecにおいて定義されている暗号化と MACアルゴリズムにより保護されている。常に、アクティブなCipherSpecが存在 する。しかし、最初はSSL_NULL_WITH_NULL_NULLである。これにはセキュリティ 機能はない。 ハンドシェイクが完了すると、2つのパーティーはシークレットを共有する。 これはレコードの暗号化と、コンテンツに対する鍵付きメッセージ認証コード (MAC)の計算に使用される。暗号化とMAC演算に使用される方法はCipherSpec により定義され、CipherSpec.cipher_typeにより制限される。暗号化とMAC関数 により、SSLCompressed構造体はSSLCiphertext構造体へ変換される。復号関数 では、この逆の処理を行う。転送に際しては、シーケンス番号を含んでいるため、 紛失、繰り返し、超過メッセージを検出することができる。 struct { ContentType type; ProtocolVersion version; uint16 length; select (CipherSpec.cipher_type) { case stream: GenericStreamCipher; case block: GenericBlockCipher; } fragment; } SSLCiphertext; type typeフィールドは、SSLCompressed.typeと同じ。 version versionフィールドは、SSLCompressed.versionと同じ。 length 次のSSLCiphertext.fragmentの長さ(単位バイト)。長さは、 2^14 + 2048 を超えない。 fragment SSLCompressed.fragmentを、MAC付きで暗号化したもの。 5.2.3.1 Nullまたは標準ストリーム暗号 ストリーム暗号(ただしBulkCipherAlgorithm.nullを含む。付録A.7を参照)は、 SSLCompressed.fragment構造体からSSLCiphertext.fragment構造体への変換、 またはその逆変換を行う。 stream-ciphered struct { opaque content[SSLCompressed.length]; opaque MAC[CipherSpec.hash_size]; } GenericStreamCipher; MACは次のように生成される。 hash(MAC_write_secret + pad_2 + hash(MAC_write_secret + pad_1 + seq_num + SSLCompressed.type + SSLCompressed.length + SSLCompressed.fragment)); ここで、"+"は連鎖を意味する。 pad_1 文字0x36が、MD5では48回、SHAでは40回繰り返されたもの。 pad_2 文字0x5cが、MD5では48回、SHAでは40回繰り返されたもの。 seq_num このメッセージのシーケンス番号。 hash 暗号スイートから得られたハッシュアルゴリズム。 MACは、暗号化の前に計算されることに注意。ストリーム暗号では、MACを含む 全体のブロックを暗号化する。(RC4などの)同期ベクトルを使用しないストリーム 暗号では、ある1つのレコードの最後におけるストリーム暗号ステータスはその まま、その後のパケット処理に使用される。もしCipherSuiteが SSL_NULL_WITH_NULL_NULLであるならば、暗号化処理は、恒等処理として行われる (すなわち、データは暗号化されず、MACが使用されないのでMACサイズはゼロで ある)。SSLCiphertext.lengthはSSLCompressed.lengthとCipherSpec.hash_size の和である。 5.2.3.2 CBCブロック暗号 (RC2やDESなどの)ブロック暗号の処理では、暗号化関数とMAC関数により、 SSLCompressed.fragment構造体はSSLCiphertext.fragment構造体への変換、 またはその逆変換が行われる。 block-ciphered struct { opaque content[SSLCompressed.length]; opaque MAC[CipherSpec.hash_size]; uint8 padding[GenericBlockCipher.padding_length]; uint8 padding_length; } GenericBlockCipher; MACは第5.2.3.1節で記述されるように生成される。 padding paddingは、平文の長さがブロック暗号のブロック長の整数 倍になるようにするために、データに追加されるものである。 padding_length paddingの長さは、暗号ブロックの長さよりも小さく、 0になってもよい。パディング長は、GenericBlockCipher 構造体の全サイズが、その暗号におけるブロック長の整数倍 になるようにすべきである。 暗号化されたデータの長さ(SSLCiphertext.length)は、SSLCompressed.length、 CipherSpec.hash_size、およびpadding_lengthの合計よりさらに1バイト大きい 値である。 注: CBCモードでは、最初のレコードのための初期ベクトル(IV)は、ハンド シェイクプロトコルにより提供される。それに続くレコードのIVは、 前のレコードの最後の暗号ブロックである。 5.3 ChangeCipherSpecプロトコル ChangeCipherSpecプロトコルは、暗号処理の変更を通知するためのものである。 プロトコルは、ただ一つのメッセージから構成されている。このメッセージは、 カレントの(未定ではない)CipherSpecのもとで暗号化、圧縮が行われる。メッ セージは値1をもつ1バイトから構成されている。 struct { enum { change_cipher_spec(1), (255) } type; } ChangeCipherSpec; ChangeCipherSpecメッセージは、クライアントとサーバの両方によって送信され るもので、メッセージを受信したパーティーに対し、この後に続くデータは、 新たにネゴシエーションされたCipherSpecと鍵のもとに保護されていることを 通知する。このメッセージを受信することにより、受信した側では、読み込み 未定ステータスを、読み込みカレントステータスにすぐにコピーする。クライ アントは、ハンドシェイクのClientKeyExchangeメッセージもしくは(送信した場合 には)CertificateVerifyメッセージに続いてChangeCipherSpecメッセージを 送信する。サーバでは、クライアントから受信したClientKeyExchangeメッセージ を正しく処理した後、このメッセージを送信する。予期されない ChangeCipherSpecメッセージを受信した場合には、unexpected_messageアラート を返信すべきである(第5.4.2節参照)。以前のセションを再利用した場合には、 ChangeCipherSpecメッセージは、Helloメッセージの後に送信される。 5.4 アラートプロトコル SSLレコード層によってサポートされているコンテンツタイプのひとつに、アラート (警告)タイプがある。アラートメッセージは、アラートの重大度とその内容を 相手に通知するものである。fatal(致命的)レベルを持つアラートメッセージでは、 コネクションは即座に切断される。この場合、そのセションにおける他のコネクション は継続してもよいが、セション識別子は無効化される。これは失敗したセション を使用して新しいコネクションを確立するのを防ぐためである。他のメッセージ 同様、アラートメッセージはカレントのコネクションステータスのもとで暗号化と 圧縮が行われる。 enum { warning(1), fatal(2), (255) } AlertLevel; enum { close_notify(0), unexpected_message(10), bad_record_mac(20), decompression_failure(30), handshake_failure(40), no_certificate(41), bad_certificate(42), unsupported_certificate(43), certificate_revoked(44), certificate_expired(45), certificate_unknown(46), illegal_parameter (47) (255) } AlertDescription; struct { AlertLevel level; AlertDescription description; } Alert; 5.4.1 終了アラート クライアントとサーバは、トランケーション攻撃を避けるために、コネクション を終了しようとしているという情報を共有しなければならない。どちらのパー ティーから終了メッセージの交換を始めてもよい。 close_notify このメッセージは、メッセージの送信者がその受信者に対し、 このコネクションではこれ以上メッセージを送信しないこと を通知するために使用される。warning(警告)レベルを もつ適切なclose_notifyメッセージなしにコネクションが 終了したときには、そのセションは再利用不可となる。 どちらのパーティからでも、close_notifyを送信することによるコネクションの 終了を始めてもよい。終了アラートを受信した後に受信したデータは無視される。 どちらのパーティーも、コネクションの書き出し側を閉じる前には、close_notify を送信する必要がある。他方のパーティーは、自分自身のclose_notifyで応答し、 すぐにコネクションを閉じ、書き出していないデータを破棄する必要がある。 最初にコネクションの終了を始めた側は、close_notifyの応答を待ってから読み 出し側を閉じる必要はない。 注:コネクションの終了処理では、その通信を終了する前に、未送信データが 転送処理されるものと仮定している。 5.4.2 エラーアラート SSLハンドシェイクプロトコルにおけるエラー処理は非常に簡単である。エラー が検出されたとき、それを検出したパーティーは、もう片方のパーティーにメッ セージを送信する。fatalレベルのAlertメッセージの送信または受信があると、 双方のパーティーはすぐにコネクションを閉じる。サーバとクライアントは、 失敗したコネクションに関するすべてのセション識別子、鍵、およびシーク レットを忘れなければならない。 以下のエラーアラートが定義されている。 unexpected_message 不適当なメッセージを受信した。このアラートは 常にfatalである。適切な実装間での通信において は使用されることはない。 bad_record_mac このアラートは、不正確なMACをもつデータを受信 したときに返される。このメッセージは常にfatal である。 decompression_failure データの展開を行う関数が不適当な入力(例えば、 展開したデータが長さ制限を超過した)を受け取った。 このメッセージは常にfatalである。 handshake_failure handshake_failureメッセージを受信したときは、 メッセージの送信者は、与えられた利用可能なオプ ションでは、受理可能なセキュリティパラメータ のネゴシエーションができなかったことを示して いる。これはfatalエラーである。 no_certificate 適切な証明書がなかった場合に、CertificateRequest メッセージのレスポンスとしてこのアラートが送信 される。 bad_certificate 証明書が不正であった。これには、正しく確かめられ なかった署名が含まれていた、などが挙げられる。 unsupported_certificate 証明書は、サポートされていないタイプのものであった。 certificate_revoked 証明書はその署名者によって無効化されていた。 certificate_expired 証明書はすでに有効期限が切れている、すなわち現在、 有効ではない。 certificate_unknown 証明書処理において、その他の(特定されていない) 問題が発生し、受理できなかった。 illegal_parameter ハンドシェイクにおけるフィールドが、その値の範囲 を超えていた、または他のフィールドと矛盾していた。 これは常にfatalである。 5.5 ハンドシェイクプロトコル概要 セションステータスにおける各暗号パラメータは、SSLハンドシェイクプロトコルに よって生成される。SSLハンドシェイクプロトコルは、SSLレコード層の最上位で処理 されるプロトコルである。SSLクライアントとサーバが最初に通信し始めるときには、 プロトコルバージョン、暗号アルゴリズム選択、そして任意で相互認証、シーク レットを共有するための公開鍵暗号方式、について合意が行われる。これらの処理は ハンドシェイクプロトコルによって実現されるが、簡単に述べると、次のようになる。 クライアントはClientHelloメッセージを送信する。これに対しサーバはServerHello メッセージで応答するか、fatalエラーの発生によりコネクション確立に失敗する。 このClientHelloとServerHelloメッセージを使用することにより、クライアントと サーバ間での、セキュリティ処理能力を決定する。さらにプロトコルバージョン、 セションID、暗号スイート、圧縮アルゴリズムの各属性を確立する。そして2つの 乱数が生成され、交換される。これは、ClientHello.random とServerHello.random である。 Helloメッセージに続き、サーバは自身の証明書を送信する。ただしこれは認証処理 が行われる場合である。さらに、ServerKeyExchangeメッセージを送信する。ただし これは送信が必要な場合(すなわち、サーバが証明書を保持していない、または サーバの証明書が署名のみ可能なものである場合)である。サーバが認証される場合 には、サーバはクライアントへ証明書を要求してもよい。ただしこれは選択された 暗号スイートに関して適切な場合である。そしてサーバはServerHelloDoneメッ セージを送信することで、ハンドシェイクにおけるHelloメッセージフェーズが終了した ことを示す。サーバはその後、クライアントからのレスポンスを待つ。サーバが CertificateRequestメッセージを送信しているならば、クライアントはCertificate メッセージもしくはno_certificateアラートを送信しなければならない。そして ClientKeyExchangeメッセージが送信されるが、その内容はClientHelloと ServerHelloの間で選択された公開鍵アルゴリズムに依存する。もしクライアント が署名能力をもつ証明書を送信しているならば、デジタル的に署名された CertificateVerifyメッセージを送信し、証明書の検証を行う。 ここで、ChangeCipherSpecメッセージがクライアントから送信される。そして クライアントは、未定状態の暗号スペックを、カレントの暗号スペックにコピー する。クライアントはすぐに、新しいアルゴリズム、鍵、そしてシークレットを 使用してFinishedメッセージを送信する。それに応じ、サーバは自身の ChangeCipherSpecメッセージを送信し、未定状態の暗号スペックをカレントに 移行し、新しい暗号スペックを使用してFinishedメッセージを送信する。この 時点でハンドシェイクが完了し、クライアントとサーバはアプリケーション層の データの交換を開始する(下記のフローチャートを参照)。 クライアント サーバ ClientHello --------> ServerHello Certificate* ServerKeyExchange* CertificateRequest* <-------- ServerHelloDone Certificate* ClientKeyExchange CertificateVerify* [ChangeCipherSpec] Finished --------> [ChangeCipherSpec] <-------- Finished Application Data <-------> Application Data * は、オプショナルなもの、または常に送信されるわけではない、状況 依存のメッセージ。 注: パイプラインの停止を避けるために、ChangeCipherSpecは、独立したSSL プロトコルコンテンツタイプであり、実際にはSSLハンドシェイクメッ セージではない。 クライアントとサーバが以前のセションを再利用する、または(新しいセキュ リティパラメータをネゴシエーションする代わりに)カレントのセションを複製 するときには、メッセージフローは以下のようになる。 クライアントは、再利用するセションのセションIDを含めたClientHelloを 送信する。サーバはセションキャッシュをチェックする。もし同じものが見つ かり、指定されたセションステータスのもとでコネクションを再確立しようと する場合には、サーバはそのセションID値を含めたServerHelloメッセージを 送信する。ここで、クライアントとサーバの双方は、ChangeCipherSpecメッ セージを送信し、すぐにFinishedメッセージへ移行しなければならない。再確立 が完了すると、クライアントとサーバは、アプリケーション層のデータ交換を 開始する(下記のフローチャートを参照)。もしセションIDに一致したものが 見つからない場合には、サーバは新しいセションIDを生成し、SSLクライアント との間で完全なハンドシェイクを実行する。 クライアント サーバ ClientHello --------> ServerHello [change cipher spec] <-------- Finished change cipher spec Finished --------> Application Data <-------> Application Data それぞれのメッセージの内容と意味は、以下の章で詳細に示される。 5.6 ハンドシェイクプロトコル SSLハンドシェイクプロトコルは、SSLレコードプロトコルの上位クライアント として定義されたものの中のひとつである。このプロトコルは、セションの セキュリティ属性をネゴシエーションするのに使用される。ハンドシェイク メッセージはSSLレコード層に渡され、そこで1つ以上のSSLPlaintext構造体に カプセル化され、カレントのアクティブセションステータスを使用して処理され、 送信される。 enum { hello_request(0), client_hello(1), server_hello(2), certificate(11), server_key_exchange (12), certificate_request(13), server_hello_done(14), certificate_verify(15), client_key_exchange(16), finished(20), (255) } HandshakeType; struct { HandshakeType msg_type; /* handshake type */ uint24 length; /* bytes in message */ select (HandshakeType) { case hello_request: HelloRequest; case client_hello: ClientHello; case server_hello: ServerHello; case certificate: Certificate; case server_key_exchange: ServerKeyExchange; case certificate_request: CertificateRequest; case server_hello_done: ServerHelloDone; case certificate_verify: CertificateVerify; case client_key_exchange: ClientKeyExchange; case finished: Finished; } body; } Handshake; ハンドシェイクプロトコルメッセージは、送信されなければならない順番で説明 していく。予期されない順番でハンドシェイクメッセージが送信されると、fatal エラーとされる。 5.6.1 Helloメッセージ Helloフェーズのメッセージは、クライアントとサーバの間で、それぞれが可能な セキュリティ処理能力に関する情報を交換するのに使用される。新しいセション を開始するときには、CipherSpecにおける暗号化、ハッシュ、および圧縮アルゴ リズムはnullに初期化される。カレントのCipherSpecは、再ネゴシエーション メッセージに適用される。 5.6.1.1 HelloRequestメッセージ HelloRequestメッセージは、サーバがいつでも送信することが出来る。しかし ハンドシェイクプロトコルがすでに実行中であるときには、このメッセージは クライアントによって無視される。本メッセージは、クライアントは都合のよい ときにClientHelloメッセージを送信することにより新たなネゴシエーション プロセスを開始するべきである、ということを通知するものである。 注: ハンドシェイクメッセージは、アプリケーションデータよりも優先されて 送信されることが意図されているため、アプリケーションデータメッセージ の最大長の転送時間内またはその倍の時間内に、ネゴシエーションが開始 されることが期待される。 HelloRequestメッセージを送信した後は、サーバはその後のハンドシェイクネゴシ エーションが完了するまで、リクエストを繰り返すべきでない。クライアントが ハンドシェイクネゴシエーション中にHelloRequestメッセージを受信したときには、 メッセージを単純に無視するべきである。 HelloRequestメッセージの構造は以下で示される。 struct { } HelloRequest; 5.6.1.2 ClientHelloメッセージ クライアントが最初にサーバに接続するときには、その最初のメッセージと してClientHelloメッセージを送信することが必要である。クライアントはまた、 HelloRequestメッセージのレスポンスとしてClientHelloを送信することができる。 また現存するコネクションにおけるセキュリティパラメータの再ネゴシエーション を行うために、クライアントから送信することも出来る。ClientHelloメッセージ にはRandom構造体が含まれているが、これはプロトコル処理の後の方で使用される。 struct { uint32 gmt_unix_time; opaque random_bytes[28]; } Random; gmt_unix_time 送信者の内部クロックにおける標準UNIX32ビット フォーマットの現在時間と日付。基本的なSSLプロト コルにおいては、クロックは正しく設定されている 必要はない。ただし、より上位の層であるアプリ ケーションプロトコルにより、追加条件を定義 してもよい。 random_bytes 安全な乱数生成器により生成された28バイトの乱数。 ClientHelloメッセージには、可変長のセション識別子が含まれる。これが 空でないとき、その値は、クライアントが再利用しようとするセキュリティ パラメータの含まれている、以前と同じクライアントとサーバの間でのセション を識別する。セション識別子は、以前のコネクション、そのコネクション、 または他のアクティブなコネクションからのものであってもよい。そのコネク ションのセション識別子を含める場合には、コネクションのRandom構造体と その派生値をアップデートすることができるため、これはクライアントがそれ のみを望んでいるときに有用である。また他のアクティブなコネクションを 含めることにより、完全なハンドシェイクプロトコルを繰り返さずに、複数の 独立したせキュリティコネクションを確立することができる。SessionIDの実際 の内容はサーバによって定義される。 opaque SessionID<0..32>; 警告:サーバはセション識別子に秘密情報を含めてはならない。さもないと、 偽のセション識別子を含むコンテンツにより、セキュリティが侵害 されることになる。 CipherSuiteリストは、ClientHelloメッセージにおいてクライアントから サーバへ送信されるもので、クライアントがサポートしている暗号アルゴ リズムを組合わせたものである。これはクライアントの好みの順で(好みの ものが最初)指定されている。それぞれのCipherSuiteには、鍵交換アルゴ リズムとCipherSpecが定義されている。サーバは1つの暗号スイートを選択 するが、もし選択できるものが提示されていない場合、handshake_failure アラートを返してコネクションを終了する。 uint8 CipherSuite[2]; /* 暗号スイートの選択肢 */ ClientHelloには、クライアントによってサポートされている圧縮アルゴリズム のリストが含まれる。これは、クライアントの好みの順番で指定されている。 サーバが、クライアントによって指定されたどのアルゴリズムもサポートして いない場合には、セション確立に失敗する。 enum { null(0), (255) } CompressionMethod; 問題点: どの圧縮方式をサポートするかは、現在調査中である。 ClientHelloメッセージの構造は以下のようである。 struct { ProtocolVersion client_version; Random random; SessionID session_id; CipherSuite cipher_suites<2..2^16-1>; CompressionMethod compression_methods<1..2^8-1>; } ClientHello; client_version クライアントがこのセションで通信しようとしている SSLのバージョン。これはクライアントがサポートする最新 のもの(最高のもの)であるべきである。本仕様書の 本バージョンでは、バージョンは3.0になる。(下位 互換性についての詳細は付録Eを参照。) random クライアントが生成したRandom構造体。 session_id クライアントがこのコネクションで使用しようとして いるセションID。session_idが利用可能でない場合、 またはクライアントが新しいセキュリティパラメータ を生成しようとする場合には、このフィールドは空で ある。 cipher_suites クライアントによってサポートされている暗号オプ ションのリスト。これはクライアントの好みの順で 並べられる。もしsession_idフィールドが空でない ならば(すなわちセション再利用リクエストを意味 する場合)、このベクトルには少なくとも、その セションのcipher_suiteが含まれていなければなら ない。この値は付録A.6で定義される。 compression_methods クライアントによってサポートされている圧縮アルゴ リズムのリスト。これはクライアントの好みの順で 並べられる。もしsession_idフィールドが空でない ならば(すなわちセション再利用リクエストを意味 する場合)、そのセションのcompression_methodを 含まなければならない。すべての実装において CompressionMethod.nullをサポートしなければなら ない。 ClientHelloメッセージを送信した後、クライアントはServerHelloメッセージの 受信を待つ。HelloRequestメッセージを除く、他のハンドシェイクメッセージが サーバから返されたときには、fatalエラーとして処理される。 実装上の注意: Finishedメッセージを送信する前に、アプリケーションデータ を送信してはならない。有効なFinishedメッセージを受信 するまでは、転送されるアプリケーションデータは安全では ないことがわかっている。ただしそのコネクションが、null ではない暗号を使用しているのであれば、この絶対的な制限 事項は緩和される。 上位互換性に関する注記: 上位互換性のために、ClientHelloメッセージの圧縮アルゴ リズムの後に拡張データを含めることができる。このデータ はハンドシェイクのハッシュに含まれなければならないが、 その他の場合では無視されなければならない。 5.6.1.3 ServerHelloメッセージ サーバは、ClientHelloメッセージを処理し、handshake_failure アラート もしくはServerHelloメッセージで応答する。 struct { ProtocolVersion server_version; Random random; SessionID session_id; CipherSuite cipher_suite; CompressionMethod compression_method; } ServerHello; server_version このフィールドは、ClientHelloによりクライアントから 提供されている値以下で、かつサーバでサポートして いる最大のものとなる。本仕様の本バージョンでは、 バージョンは3.0である(下位互換性の詳細に関しては、 付録Eを参照)。 random これはサーバにより生成され、ClientHello.randomと は異なる(そして独立である)必要がある。 session_id このコネクションに関するセション識別子。もし ClientHello.session_idが空でなければ、サーバは、 一致するIDをキャッシュから探す。もし一致するIDが 見つかり、それに関連するセションステータスを使用 して新規コネクションを確立しようとするときには、 サーバは、クライアントから送信されてきたIDと同じ 値で応答する。これはセションを再利用することを意味 し、両者は直ちにFinishedメッセージへ進まなければ ならない。そうでない場合には、このフィールドには 別の値を入れ、新規セションであることを示す。サーバ はまた、このフィールドを空で返すことも出来る。 これは、セションはキャッシュされず、それゆえ再利用 できないことを示す。 cipher_suite ClientHello.cipher_suitesのリストから、サーバに よって選択された1つの暗号スイート。セションの 再利用においては、このフィールドは再利用された セションステータスから取得された値が格納される。 compression_method ClientHello.compression_methodsのリストから、 サーバによって選択された1つの圧縮アルゴリズム。 セションの再利用においては、このフィールドは 再利用されたセションステータスから取得された値が 格納される。 5.6.2 ServerCertificateメッセージ サーバが認証されるとき(これが通常の場合である)には、サーバはServerHello メッセージの直後に、自身の証明書を送信する。送信される証明書は、選択 された暗号スイートにおける鍵交換アルゴリズムに対して、適切なものでなけれ ばならない。証明書としては一般に、X.509v3証明書が使用される(FORTEZZA(tm) [FOR]の場合には、X.509証明書を修正したものが使用される)。 CertificateRequestメッセージに対するクライアントの応答メッセージにおいても、 同じメッセージ型が使用される。 opaque ASN.1Cert<1..2^24-1>; struct { ASN.1Cert certificate_list<1..2^24-1>; } Certificate; certificate_list X.509v3証明書のシーケンス(チェイン)。送信者の 証明書がリストの最初に存在し、前の証明書を直接に 証明しているCA証明書がそれに続く。 注:PKCS #7 [PKCS7]フォーマットは、証明書ベクトルとしては使用しない。これは PKCS #6 [PKCS6] 拡張証明書が使用されないからである。またPKCS #7では SEQUENCEではなくSETで定義されているため、リストの解析処理が難しい。 5.6.3 ServerKeyExchangeメッセージ ServerKeyExchangeメッセージは、サーバが証明書を保持していない場合や、署名目的 のみ使用可能な証明書(例えば DSS [DSS] 証明書、書名のみ可能な RSA [RSA] 証明書)を保持している場合、もしくは FORTEZZA KEA 鍵交換方式を使用している 場合にのみ、サーバから送信される。このメッセージは、サーバ証明書に Diffie-Hellman [DH1] パラメータが記載されている場合には、使用されない。 注 : 現在の米国輸出法では、米国から輸出したソフトウェアにおいては、512 ビットより長いRSAのモジュラスを鍵交換において使用してはならない ことになっている。このメッセージを送信した場合、512ビットより長い RSA鍵は、512ビット以下の長さを持つ一時的RSA鍵を署名するための、 署名のみ可能な証明書として使用される。 enum { rsa, diffie_hellman, fortezza_kea } KeyExchangeAlgorithm; struct { opaque rsa_modulus<1..2^16-1>; opaque rsa_exponent<1..2^16-1>; } ServerRSAParams; rsa_modulus サーバの一時的RSA鍵のモジュラス。 rsa_exponent サーバの一時的RSA鍵の公開指数。 struct { opaque dh_p<1..2^16-1>; opaque dh_g<1..2^16-1>; opaque dh_Ys<1..2^16-1>; } ServerDHParams; /* 一時的 DH パラメータ */ dh_p Diffie-Hellman演算に使用される素数モジュラス。 dh_g Diffie-Hellman演算に使用されるgenerator。 dh_Ys サーバのDiffie-Hellman公開値(gX mod p)。 struct { opaque r_s [128]; } ServerFortezzaParams; r_s FORTEZZA KEA (Key Exchange Algorithm)用のサーバ乱数。 struct { select (KeyExchangeAlgorithm) { case diffie_hellman: ServerDHParams params; Signature signed_params; case rsa: ServerRSAParams params; Signature signed_params; case fortezza_kea: ServerFortezzaParams params; }; } ServerKeyExchange; params サーバの鍵交換パラメータ。 signed_params 関連するparams値のハッシュに対して適用された 適切な署名。 md5_hash MD5(ClientHello.random + ServerHello.random + ServerParams); sha_hash SHA(ClientHello.random + ServerHello.random + ServerParams); enum { anonymous, rsa, dsa } SignatureAlgorithm; digitally-signed struct { select(SignatureAlgorithm) { case anonymous: struct { }; case rsa: opaque md5_hash[16]; opaque sha_hash[20]; case dsa: opaque sha_hash[20]; }; } Signature; 5.6.4 CertificateRequestメッセージ 匿名ではないサーバは、選択された暗号スイートにおいて適切であるならば、 任意でクライアントに対し証明書を要求することができる。 enum { rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4), rsa_ephemeral_dh(5), dss_ephemeral_dh(6), fortezza_kea(20), (255) } ClientCertificateType; opaque DistinguishedName<1..2^16-1>; struct { ClientCertificateType certificate_types<1..2^8-1>; DistinguishedName certificate_authorities<3..2^16-1>; } CertificateRequest; certificate_types 要求される証明書種別のリスト。これはサーバの好み の順に指定される。 certificate_authorities 受理することのできる認証局のDistinguishedNameの リスト。 注:DistinguishedName は [X509]から導入されている。 注:匿名サーバがクライアント証明書を要求した場合には、fatalレベルの handshake_failure アラートとなる。 5.6.5 ServerHelloDoneメッセージ ServerHelloDoneメッセージはサーバから送信されるもので、ServerHello と、それに関連するメッセージの終了を示す。このメッセージを送信した後、 サーバはクライアントからのレスポンスを待つ。 struct { } ServerHelloDone; ServerHelloDoneメッセージを受信したならば、クライアントは、もしサーバ認証 の必要があるならば、サーバが有効な証明書を提供しているかどうかを検証 するべきである。また、ServerHelloパラメータが受理できるか否かをチェック すべきである。 5.6.6 ClientCertificateメッセージ これは、ServerHelloDoneメッセージを受信した後に、クライアントが送信 することのできる最初のメッセージである。このメッセージは、サーバが 証明書を要求している場合にのみ送信される。もし適切な証明書がないならば、 クライアントは、no_certificateアラートを送信するべきである。このアラート はワーニングレベルであるが、もしクライアント認証が必要であるならば、 サーバはfatalレベルのhandshake_failureアラートで応答する。ClientCertificateの 送信には、第5.6.2節に定義されるCertificate構造体を使用する。 注:クライアントのDiffie-Hellman証明書は、サーバが指定したDiffie-Hellman パラメータに合致していなければならない。 5.6.7 ClientKeyExchangeメッセージ メッセージは、どの公開鍵交換アルゴリズムを選択するかに依存する。第5.6.3節の KeyExchangeAlgorithmの定義を参照のこと。 struct { select (KeyExchangeAlgorithm) { case rsa: EncryptedPreMasterSecret; case diffie_hellman: ClientDiffieHellmanPublic; case fortezza_kea: FortezzaKeys; } exchange_keys; } ClientKeyExchange; 適切なレコード構造体を選択するための情報は、未定セションステータスにある (第5.1節を参照)。 5.6.7.1 RSAを使用したEncryptedPreMasterSecretメッセージ 鍵交換と認証方式としてRSAが使用されているならば、クライアントは48 バイトのpremaster_secretを生成し、サーバ証明書から取得した公開鍵、 またはServerKeyExchangeメッセージにて提供される一時的RSA鍵を使用して 暗号化する。その結果をEncryptedPreMasterSecretメッセージに含め送信 する。 struct { ProtocolVersion client_version; opaque random[46]; } PreMasterSecret; client_version クライアントがサポートしている、最新のバージョン。 これはバージョンロールバック攻撃を検出するのに 使用される。 random 安全に生成された46バイトの乱数。 struct { public-key-encrypted PreMasterSecret pre_master_secret; } EncryptedPreMasterSecret; pre_master_secret この乱数値はクライアントによって生成され、 master_secretを生成するのに使用される。これは 第6.1節で定義される。 5.6.7.2 FORTEZZA鍵交換メッセージ FORTEZZAを使用した場合、クライアントはFORTEZZA鍵交換アルゴリズム(Key Exchange Algorithm (KEA))により、トークン暗号化鍵(Token Encryption Key (TEK))を得る。クライアントのKEA計算では、サーバ証明書における公開鍵と、 クライアントのトークンにおける私有パラメータが使用される。クライアント は、サーバが自身の私有パラメータを使用してTEKを生成するのに必要となる 公開パラメータを送信する。クライアントはセション鍵を生成し、それをTEK を使用してラップし、その結果をサーバに送信する。クライアントはセション 鍵とTEKのためのIVを生成し、それらも送信する。クライアントはランダムな 48バイトのプレマスターシークレットを生成し、それをTEKを使用して暗号化し、 その結果を送信する。 struct { opaque y_c<0..128>; opaque r_c[128]; opaque y_signature[40]; opaque wrapped_client_write_key[12]; opaque wrapped_server_write_key[12]; opaque client_write_iv[24]; opaque server_write_iv[24]; opaque master_secret_iv[24]; block-ciphered opaque encrypted_pre_master_secret[48]; } FortezzaKeys; y_signature y_signatureはKEA公開鍵をクライアントのDSS 私有鍵により署名した際の署名データである。 y_c KEA計算で使用されるクライアントのYc値(すなわち公開鍵)。 クライアントが証明書を送信しており、かつそのKEA 公開鍵が適切なものである場合、この値は空でなければ ならない。なぜならば、この値はすでに証明書に含ま れているためである。もしクライアントが適切な公開 鍵のない証明書を送信している場合にはこのy_cが使用 され、y_signatureはクライアントのDSS私有鍵でKEA公開鍵 を署名したものである。この値を使用する場合には、 これは64ビットから128ビットの間でなければならない。 r_c KEA計算に使用する、クライアントのRc値 wrapped_client_write_key TEKによりラップされた、クライアントの書き出し鍵 wrapped_server_write_key TEKによりラップされた、サーバの書き出し鍵 client_write_iv クライアント書き出し鍵用のIV server_write_iv サーバ書き出し鍵用のIV master_secret_iv プレマスターシークレットを暗号化するのに使用される TEK用のIV pre_master_secret 乱数値。クライアントによって生成され、マスター シークレットを生成するのに使用される。これは 第6.1節で規定されている。上記の構造体は、TEK を使用して暗号化される。 5.6.7.3 ClientDiffieHellmanPublic値 この構造体は、クライアントのDiffie-Hellman公開値(Yc)が、クライアントの 証明書に含まれていなかった場合に、それを送信するものである。Ycに使用 されるエンコード方式は、列挙型のPublicValueEncodingによって決定される。 enum { implicit, explicit } PublicValueEncoding; implicit クライアント証明書に、既にDiffie-Hellman公開値が 記載されているならば、Ycはimplicit(内在)であり、 再送する必要はない。 explicit Ycを送信する必要がある。 struct { select (PublicValueEncoding) { case implicit: struct { }; case explicit: opaque dh_Yc<1..2^16-1>; } dh_public; } ClientDiffieHellmanPublic; dh_Yc クライアントのDiffie-Hellman公開値(Yc)。 5.6.8 CertificateVerifyメッセージ このメッセージは、クライアント証明書の検証を行うのに使用される。この メッセージは、署名可能なクライアント証明書(すなわち、固定Diffie-Hellman パラメータを含んた証明書以外のすべての証明書)が送信された後にのみ送信 される。 struct { Signature signature; } CertificateVerify; CertificateVerify.signature.md5_hash MD5(master_secret + pad_2 + MD5(handshake_messages + master_secret + pad_1)); Certificate.signature.sha_hash SHA(master_secret + pad_2 + SHA(handshake_messages + master_secret + pad_1)); pad_1 これは第5.2.3.1節で定義されたpad_1と同じ。 pad_2 これは第5.2.3.1節で定義されたpad_2と同じ。 ここでhandshake_messagesは、ClientHelloメッセージから現在までの、この メッセージを除く、すべてのハンドシェイクメッセージを表す。 5.6.9 Finishedメッセージ Finishedメッセージは、常にChangeCipherSpecメッセージの直後に送信され、 鍵交換と認証処理が成功したことを確認する。Finishedメッセージは、これ までにネゴシエーションされたアルゴリズム、鍵、およびシークレットで保護 される最初のメッセージである。Finishedメッセージの受信通知は必要ない。 パーティーは、Finishedメッセージを送信した直後に、暗号化されたデータの 送信を開始してもよい。Finishedメッセージの受信者は、その内容が正しいこと を確認しなければならない。 enum { client(0x434C4E54), server(0x53525652) } Sender; struct { opaque md5_hash[16]; opaque sha_hash[20]; } Finished; md5_hash MD5(master_secret + pad2 + MD5(handshake_messages + Sender + master_secret + pad1)); sha_hash SHA(master_secret + pad2 + SHA(handshake_messages + Sender + master_secret + pad1)); handshake_messages このメッセージ以外の、ここまでのすべてのハンド シェイクメッセージのすべてのデータである。この データは、ハンドシェイク層のみで見ることのでき るデータのみであり、レコード層のヘッダデータは 含まれない。 もし、ハンドシェイクの適切な時点において、Finishedメッセージが ChangeCipherSpecメッセージよりも先であったならば、それはfatalエラー である。 サーバによって送信されるFinishedメッセージに含まれるハッシュには、 Sender.serverを組み込む。また、クライアントによって送信されるものには Sender.clientを組み込む。ここでhandshake_messagesは、ClientHelloメッ セージから始まり、このFinishedメッセージを除く、すべてのハンドシェイク メッセージが含まれる。これは、(送信された場合には)CertificateVerify メッセージも含むため、第5.6.8節のhandshake_messagesとは異なるものと なる。 注:ChangeCipherSpecメッセージはハンドシェイクメッセージではない。その ためハッシュ計算には含めない。 5.7 アプリケーションデータプロトコル アプリケーションデータメッセージは、カレントのコネクションステータスに 基づいて分割され、圧縮され、暗号化されて、レコード層によって送信される。 メッセージは、レコード層では透過データとして扱われる。 6. 暗号計算 鍵交換、認証、暗号化、MACアルゴリズムは、サーバによって選択された cipher_suiteによって決定され、ServerHelloメッセージにおいて明示される。 6.1 非対称暗号計算 パーティーを認証し、共有鍵と共有シークレットを生成するために、ハンドシェイク プロトコルにおいて非対称アルゴリズムが使用される。 Diffie-Hellman、RSA、FORTEZZAにおいては、pre_master_secretをmaster_secret へ変換するのに、同一のアルゴリズムが使用される。master_secretが計算されると、 pre_master_secretはメモリ上から削除されるべきである。 master_secret = MD5(pre_master_secret + SHA('A' + pre_master_secret + ClientHello.random + ServerHello.random)) + MD5(pre_master_secret + SHA('BB' + pre_master_secret + ClientHello.random + ServerHello.random)) + MD5(pre_master_secret + SHA('CCC' + pre_master_secret + ClientHello.random + ServerHello.random)); 6.1.1 RSA RSAがサーバ認証と鍵交換に使用されるとき、48バイトのpre_master_secretが クライアントによって生成され、サーバの公開鍵で暗号化されて、サーバに 送信される。サーバは、自身の私有鍵を使用してpre_master_secretを復号する。 そして両方のパーティーは、上記のような方法により、pre_master_secretを master_secretに変換する。 RSAデジタル署名は、PKCS #1 [PKCS1]ブロック型1を使用して実行される。 RSA公開鍵暗号処理は、PKCS #1ブロック型2を使用して実行される。 6.1.2 Diffie-Hellman 従来のDiffie-Hellman計算が実行される。ネゴシエーションされた鍵(Z) はpre_master_secretとして使用され、上記のような方法でmaster_secretに 変換される。 注: Diffie-Hellmanパラメータはサーバによって指定される。そのパラメータ は一時的(ephemeral)なもの、もしくはサーバ証明書に含まれるものの どちらでもよい。 6.1.3 FORTEZZA ランダムな48バイトのpre_master_secretがTEKとそのIVを使用して暗号化され 送信される。サーバはpre_master_secretを復号し、上記のような方法で master_secretに変換する。暗号化に使用される大量暗号化鍵とIVは、クライアントの トークンから生成され、KeyExchangeメッセージにより交換される。master_secret は、MAC計算のみに使用される。 6.2 対称暗号計算とCipherSpec SSLレコードを暗号化しその保全性を検証するための方法は、カレントのアク ティブCipherSpecによって指定される。典型的な例としては、DESを使用して データを暗号化し、MD5を使用して認証コードを生成するものであろう。SSL ハンドシェイクプロトコルの最初では、暗号化とMACアルゴリズムは SSL_NULL_WITH_NULL_NULLにセットされる。すなわち、メッセージ認証または 暗号化は適用されないことを意味している。ハンドシェイクプロトコルは、 これよりさらに安全なCipherSpecをネゴシエーションし、暗号鍵を生成する ために使用される。 6.2.1 マスターシークレット レコードに対して安全な暗号化または保全検証を実行する前に、クライアントと サーバは、両者しか知らない共有シークレット情報を生成する必要がある。 この値は48バイトで、マスターシークレットと呼ばれる。マスターシークレット は、暗号化とMAC計算に必要な鍵とシークレットを生成するのに使用される。 あるアルゴリズム、例えばFORTEZZAでは、暗号化鍵を生成するための独自の 方法をもつ(FORTEZZAでは、マスターシークレットは、MAC計算のみに使用さ れる)。 6.2.2 マスターシークレットからの鍵とMACシークレット生成 マスターシークレットは、安全なバイト列にハッシュされる。これはカレントの CipherSpecにおいて必要とされるMACシークレット、鍵、輸出不可能な暗号で 使用するIVに割り当てられる(付録 A.7を参照)。CipherSpecでは、クライアント 書き出しMACシークレット、サーバ書き出しMACシークレット、クライアント書き 出し鍵、サーバ書き出し鍵、クライアント書き出しIV、そしてサーバ書き出しIV を必要とする。これらはこの順序で、マスターシークレットから生成される。 使用しない値、例えばKeyExchangeメッセージを使用して交換しているFORTEZZA鍵、 は空である。鍵決定プロセスに対する入力には以下のようなものがある。 opaque MasterSecret[48] ClientHello.random ServerHello.random 鍵とMACシークレットを生成するときには、マスターシークレットをエントロピー ソースとして使用する。そして乱数を使用して、輸出可能な暗号のための、暗号化 されないソルトとIVが作成される。 鍵マテリアルを生成するには、次を計算する。 key_block = MD5(master_secret + SHA(`A' + master_secret + ServerHello.random + ClientHello.random)) + MD5(master_secret + SHA(`BB' + master_secret + ServerHello.random + ClientHello.random)) + MD5(master_secret + SHA(`CCC' + master_secret + ServerHello.random + ClientHello.random)) + [...]; これを十分な出力が得られるまで行う。次に、key_blockは以下の通りに仕切 られる。 client_write_MAC_secret[CipherSpec.hash_size] server_write_MAC_secret[CipherSpec.hash_size] client_write_key[CipherSpec.key_material] server_write_key[CipherSpec.key_material] client_write_IV[CipherSpec.IV_size] /* 輸出のできない暗号の場合 */ server_write_IV[CipherSpec.IV_size] /* 輸出のできない暗号の場合 */ 余分なkey_blockマテリアルは捨てられる。 輸出可能な暗号化アルゴリズム(CipherSpec.is_exportableがtrue)では、 最終的な書き出し鍵を得るために、以下のような追加処理が必要となる。 final_client_write_key = MD5(client_write_key + ClientHello.random + ServerHello.random); final_server_write_key = MD5(server_write_key + ServerHello.random + ClientHello.random); 輸出可能な暗号化アルゴリズムでは、そのIVは乱数メッセージから作成される。 client_write_IV = MD5(ClientHello.random + ServerHello.random); server_write_IV = MD5(ServerHello.random + ClientHello.random); MD5の出力は、下位バイトを切り捨てることにより、適切なサイズに整えられる。 6.2.2.1 輸出可能な暗号の鍵生成例 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5では、2つの暗号化鍵としてそれぞれ5バイト の乱数と、MAC鍵としてそれぞれ16バイト、合計42バイトの鍵マテリアルを必要と する。 MD5は1度に16バイトを出力するため、MD5処理は3回必要となる。MD5の 出力は、最初の出力がゼロから15バイト、2回目の出力が16から31バイト、のように 連鎖されて、48バイトのkey_blockとされる。key_blockはさらに分割され、輸出可能 な暗号化アルゴリズムであるために、書き出し鍵はソルト処理される。 client_write_MAC_secret = key_block[0..15] server_write_MAC_secret = key_block[16..31] client_write_key = key_block[32..36] server_write_key = key_block[37..41] final_client_write_key = MD5(client_write_key + ClientHello.random + ServerHello.random)[0..15]; final_server_write_key = MD5(server_write_key + ServerHello.random + ClientHello.random)[0..15]; client_write_IV = MD5(ClientHello.random + ServerHello.random)[0..7]; server_write_IV = MD5(ServerHello.random + ClientHello.random)[0..7]; 付録 A A. プロトコル定数値 この章では、プロトコルの型と定数について示す。 A.1 予約されているポート番号 現在のところ、SSLはネットワーク技術のベースとしてTCP/IPを使用し実装を 行っている。IANAは、以下のインターネットプロトコル [IP] ポート番号を SSLとの関連で予約している。 443 SSLを使用したハイパーテキスト転送プロトコル(https)の使用のため に予約されている。 465 SSLを使用したシンプルメール転送プロトコル(ssmtp)の使用のため に予約(ただし未定)されている。 563 ネットワークニュース転送プロトコル(snntp)の使用のために予約 (ただし未定)されている。 A.1.1 レコード層 struct { uint8 major, minor; } ProtocolVersion; ProtocolVersion version = { 3,0 }; enum { change_cipher_spec(20), alert(21), handshake(22), application_data(23), (255) } ContentType; struct { ContentType type; ProtocolVersion version; uint16 length; opaque fragment[SSLPlaintext.length]; } SSLPlaintext; struct { ContentType type; ProtocolVersion version; uint16 length; opaque fragment[SSLCompressed.length]; } SSLCompressed; struct { ContentType type; ProtocolVersion version; uint16 length; select (CipherSpec.cipher_type) { case stream: GenericStreamCipher; case block: GenericBlockCipher; } fragment; } SSLCiphertext; stream-ciphered struct { opaque content[SSLCompressed.length]; opaque MAC[CipherSpec.hash_size]; } GenericStreamCipher; block-ciphered struct { opaque content[SSLCompressed.length]; opaque MAC[CipherSpec.hash_size]; uint8 padding[GenericBlockCipher.padding_length]; uint8 padding_length; } GenericBlockCipher; A.2 ChangeCipherSpecメッセージ struct { enum { change_cipher_spec(1), (255) } type; } ChangeCipherSpec; A.3 アラートメッセージ enum { warning(1), fatal(2), (255) } AlertLevel; enum { close_notify(0), unexpected_message(10), bad_record_mac(20), decompression_failure(30), handshake_failure(40), no_certificate(41), bad_certificate(42), unsupported_certificate(43), certificate_revoked(44), certificate_expired(45), certificate_unknown(46), illegal_parameter (47), (255) } AlertDescription; struct { AlertLevel level; AlertDescription description; } Alert; A.4 ハンドシェイクプロトコル enum { hello_request(0), client_hello(1), server_hello(2), certificate(11), server_key_exchange (12), certificate_request(13), server_done(14), certificate_verify(15), client_key_exchange(16), finished(20), (255) } HandshakeType; struct { HandshakeType msg_type; uint24 length; select (HandshakeType) { case hello_request: HelloRequest; case client_hello: ClientHello; case server_hello: ServerHello; case certificate: Certificate; case server_key_exchange: ServerKeyExchange; case certificate_request: CertificateRequest; case server_done: ServerHelloDone; case certificate_verify: CertificateVerify; case client_key_exchange: ClientKeyExchange; case finished: Finished; } body; } Handshake; A.4.1 各種Helloメッセージ struct { } HelloRequest; struct { uint32 gmt_unix_time; opaque random_bytes[28]; } Random; opaque SessionID<0..32>; uint8 CipherSuite[2]; enum { null(0), (255) } CompressionMethod; struct { ProtocolVersion client_version; Random random; SessionID session_id; CipherSuite cipher_suites<0..2^16-1>; CompressionMethod compression_methods<0..2^8-1>; } ClientHello; struct { ProtocolVersion server_version; Random random; SessionID session_id; CipherSuite cipher_suite; CompressionMethod compression_method; } ServerHello; A.4.2 サーバ認証と各種鍵交換メッセージ opaque ASN.1Cert<2^24-1>; struct { ASN.1Cert certificate_list<1..2^24-1>; } Certificate; enum { rsa, diffie_hellman, fortezza_kea } KeyExchangeAlgorithm; struct { opaque RSA_modulus<1..2^16-1>; opaque RSA_exponent<1..2^16-1>; } ServerRSAParams; struct { opaque DH_p<1..2^16-1>; opaque DH_g<1..2^16-1>; opaque DH_Ys<1..2^16-1>; } ServerDHParams; struct { opaque r_s [128] } ServerFortezzaParams struct { select (KeyExchangeAlgorithm) { case diffie_hellman: ServerDHParams params; Signature signed_params; case rsa: ServerRSAParams params; Signature signed_params; case fortezza_kea: ServerFortezzaParams params; }; } ServerKeyExchange; enum { anonymous, rsa, dsa } SignatureAlgorithm; digitally-signed struct { select(SignatureAlgorithm) { case anonymous: struct { }; case rsa: opaque md5_hash[16]; opaque sha_hash[20]; case dsa: opaque sha_hash[20]; }; } Signature; enum { RSA_sign(1), DSS_sign(2), RSA_fixed_DH(3), DSS_fixed_DH(4), RSA_ephemeral_DH(5), DSS_ephemeral_DH(6), FORTEZZA_MISSI(20), (255) } CertificateType; opaque DistinguishedName<1..2^16-1>; struct { CertificateType certificate_types<1..2^8-1>; DistinguishedName certificate_authorities<3..2^16-1>; } CertificateRequest; struct { } ServerHelloDone; A.5 クライアント認証と各種鍵交換メッセージ struct { select (KeyExchangeAlgorithm) { case rsa: EncryptedPreMasterSecret; case diffie_hellman: DiffieHellmanClientPublicValue; case fortezza_kea: FortezzaKeys; } exchange_keys; } ClientKeyExchange; struct { ProtocolVersion client_version; opaque random[46]; } PreMasterSecret; struct { public-key-encrypted PreMasterSecret pre_master_secret; } EncryptedPreMasterSecret; struct { opaque y_c<0..128>; opaque r_c[128]; opaque y_signature[40]; opaque wrapped_client_write_key[12]; opaque wrapped_server_write_key[12]; opaque client_write_iv[24]; opaque server_write_iv[24]; opaque master_secret_iv[24]; opaque encrypted_preMasterSecret[48]; } FortezzaKeys; enum { implicit, explicit } PublicValueEncoding; struct { select (PublicValueEncoding) { case implicit: struct {}; case explicit: opaque DH_Yc<1..2^16-1>; } dh_public; } ClientDiffieHellmanPublic; struct { Signature signature; } CertificateVerify; A.5.1 ハンドシェイク完了メッセージ struct { opaque md5_hash[16]; opaque sha_hash[20]; } Finished; A.6 CipherSuite 以下では、ClientHelloとServerHelloメッセージで使用されるCipherSuite コードを定義する。 またそれぞれのCipherSuiteは、SSLバージョン3.0でサポートされる暗号仕様を 定義する。 CipherSuite SSL_NULL_WITH_NULL_NULL = { 0x00,0x00 }; 以下のCipherSuite定義では、鍵交換に使用することのできるRSA証明書をサーバが 提供する必要がある。 サーバは、CertificateRequestメッセージにおいて、 RSAまたはDSSのどちらかの、署名可能な証明書を要求することができる。 CipherSuite SSL_RSA_WITH_NULL_MD5 = { 0x00,0x01 }; CipherSuite SSL_RSA_WITH_NULL_SHA = { 0x00,0x02 }; CipherSuite SSL_RSA_EXPORT_WITH_RC4_40_MD5 = { 0x00,0x03 }; CipherSuite SSL_RSA_WITH_RC4_128_MD5 = { 0x00,0x04 }; CipherSuite SSL_RSA_WITH_RC4_128_SHA = { 0x00,0x05 }; CipherSuite SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = { 0x00,0x06 }; CipherSuite SSL_RSA_WITH_IDEA_CBC_SHA = { 0x00,0x07 }; CipherSuite SSL_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x08 }; CipherSuite SSL_RSA_WITH_DES_CBC_SHA = { 0x00,0x09 }; CipherSuite SSL_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00,0x0A }; 以下のCipherSuite定義は、サーバにより認証された(または任意で、クライ アントにより認証された)Diffie-Hellmanに使用される。DHは、認証局(CA)に よって署名されたサーバ証明書に含まれているDiffie-Hellmanパラメータを 使用した暗号スイートを示すものである。DHEは、CAによって署名されたDSS またはRSA証明書により署名されたDiffie-Hellmanパラメータを使用した一時的 Diffie-Hellmanを示すものである。使用される署名アルゴリズムは、DHまたは DHEパラメータの後に指定される。すべての場合において、クライアントは サーバ証明書と同じ型の証明書を保持していなければならず、またサーバにより 選択されたDiffie-Hellmanパラメータを使用しなければならない。 CipherSuite SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x0B }; CipherSuite SSL_DH_DSS_WITH_DES_CBC_SHA = { 0x00,0x0C }; CipherSuite SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA = { 0x00,0x0D }; CipherSuite SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x0E }; CipherSuite SSL_DH_RSA_WITH_DES_CBC_SHA = { 0x00,0x0F }; CipherSuite SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00,0x10 }; CipherSuite SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x11 }; CipherSuite SSL_DHE_DSS_WITH_DES_CBC_SHA = { 0x00,0x12 }; CipherSuite SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA = { 0x00,0x13 }; CipherSuite SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x14 }; CipherSuite SSL_DHE_RSA_WITH_DES_CBC_SHA = { 0x00,0x15 }; CipherSuite SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00,0x16 }; 以下の暗号スイートは、どちら側のパーティーも認証されることのない、完全に 匿名なDiffie-Hellman通信に使用される。このモードは、なりすまし攻撃を受け やすいため、推奨されないことに注意。 CipherSuite SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 = { 0x00,0x17 }; CipherSuite SSL_DH_anon_WITH_RC4_128_MD5 = { 0x00,0x18 }; CipherSuite SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x19 }; CipherSuite SSL_DH_anon_WITH_DES_CBC_SHA = { 0x00,0x1A }; CipherSuite SSL_DH_anon_WITH_3DES_EDE_CBC_SHA = { 0x00,0x1B }; 最後の暗号スイートは、FORTEZZAトークン用である。 CipherSuite SSL_FORTEZZA_KEA_WITH_NULL_SHA = { 0X00,0X1C }; CipherSuite SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA = { 0x00,0x1D }; CipherSuite SSL_FORTEZZA_KEA_WITH_RC4_128_SHA = { 0x00,0x1E }; 注:最初のバイトが0xFFであるすべての暗号スイートは、プライベートなものと されており、ローカルまたは実験的アルゴリズムを定義するのに使用する ことができる。そのような暗号スイートの共同利用は、そのローカルにお ける問題である。 注:暗号スイートの追加登録は、2つの独立したエンティティからの公証された 手紙を受理した場合のみに、その実装の考慮を行う。Netscape Communications Corp. は、公的な標準機関がSSLの管理を行うまで、 一時的な管理事務を行う。 A.7 CipherSpec 暗号スイートはCipherSpecを識別する。これらの構造体は、SSLセションステータス の一部である。CipherSpecには以下のものが含まれる。 enum { stream, block } CipherType; enum { true, false } IsExportable; enum { null, rc4, rc2, des, 3des, des40, fortezza } BulkCipherAlgorithm; enum { null, md5, sha } MACAlgorithm; struct { BulkCipherAlgorithm bulk_cipher_algorithm; MACAlgorithm mac_algorithm; CipherType cipher_type; IsExportable is_exportable uint8 hash_size; uint8 key_material; uint8 IV_size; } CipherSpec; 付録 B B. 用語集 アプリケーションプロトコル アプリケーションプロトコルは通常、トランス ポート層(例えば、TCP/IP)のすぐ上位の層にある プロトコルである。 例えば、HTTP、TELNET、FTP、 SMTPなどが挙げられる。 非対称暗号 公開鍵暗号の項を参照。 認証 認証とは、あるエンティティが、他のエンティティ のアイデンティティを決定する能力である。 ブロック暗号 ブロック暗号は、平文に対し、ブロックと呼ばれる ビットのグループ単位で処理を行うアルゴリズムで ある。ブロックサイズは通常64ビットである。 大量暗号 大量のデータを暗号化するのに使用される対称暗号 アルゴリズム。 暗号ブロックチェーン(cipher block chaining: CBC) CBCとは、ブロック暗号で暗号化されるすべての平文 ブロックが、1つ前の暗号文ブロック(最初のブロック の場合は初期ベクトル)と、排他的OR処理される モードのことである。 証明書 (ISO認証フレームワークとして知られている)X.509 プロトコルの一部として、証明書は信用のおける 認証局によって割り当てられ、パーティーのアイ デンティティを検証し、また公開鍵を提供する。 クライアント サーバに対してコネクションを開始するアプリケー ションエンティティ。 クライアント書き出し鍵 データを暗号化するためにクライアントが使用 する鍵。 クライアント書き出しMACシークレット データを認証するためにクライアントが使用する シークレットデータ。 コネクション コネクションは、適切なサービスを提供する、(OSI 階層モデル定義においての)トランスポート(転送) のことである。SSLにおいては、そのようなコネク ションはピアツーピア関係をもつ。コネクションは 一時的である。すべてのコネクションは、1つの セションと関連づけられる。 データ暗号化標準(Data Encryption Standard:DES) DESは非常に広く使用されている対称暗号アルゴ リズムである。DESはブロック暗号である。 デジタル署名標準(Digital Signature Standard :DSS) デジタル署名アルゴリズム(Digital Signing Algorithm:DSA)を含むデジタル署名規格で、National Institute of Standards and Technology により 承認され、1994年5月に米国商務省より発行された、 NIST FIPS PUB 186、「デジタル署名標準」で定義 される。 デジタル署名 デジタル署名は、公開鍵暗号と一方向ハッシュ関数 を使用して、認証が可能であり、また偽造、否認が 困難であるような、データの署名を作成すること である。 FORTEZZA 暗号化とデジタル署名の両方を提供するPCMCIA カード。 ハンドシェイク トランザクションのパラメータを確立するために、 クライアントとサーバの間で行われる初期ネゴシ エーション。 初期ベクトル(Initialization Vector : IV) ブロック暗号がCBCモードで使用されるときには、 暗号化が行われる前に、初期ベクトルと最初の平文 ブロックとで排他的OR処理が行われる。 IDEA Xuejia LaiとJames Masseyによって設計された、 64ビットブロック暗号。 メッセージ認証コード(Message Authentication Code : MAC) メッセージ認証コードは、メッセージとシークレット データから計算された一方向ハッシュである。 メッセージの改竄を検出するのがその目的である。 マスターシークレット 暗号化鍵、MACシークレット、IVを生成するための、 安全なシークレットデータ。 MD5 MD5 [7] は安全なハッシュ関数で、任意長のデータ ストリームを固定長のダイジェストに変換する。 公開鍵暗号 2個の鍵を使用する暗号技術の1分野。公開鍵で暗号化 されたメッセージは、関連する私有鍵でのみ復号する ことができる。逆に、私有鍵により署名されたメッ セージは、公開鍵を使用して検証することができる。 一方向ハッシュ関数 任意量のデータを固定長ハッシュに変換する一方向 変換。逆変換や、衝突を発見するのは困難である。 MD5とSHAが一方向ハッシュ関数の例として挙げ られる。 RC2, RC4 RSA Data Security, Incの保持している大量暗号 方式(アルゴリズムが公開されていないためよい参考 文献が存在しないが、しかし[RSADSI]を参照のこと)。 RC2はブロック暗号で、RC4はストリーム暗号である。 RSA 非常に広く使用されている公開鍵アルゴリズム暗号 で、暗号化、デジタル署名のどちらにも使用する ことができる。 ソルト 秘密ではない乱数データで、輸出可能な暗号化鍵を、 事前計算攻撃に対抗できるようにするために使用 される。 サーバ サーバとは、クライアントからのコネクション リクエストに応答するアプリケーションエンティティ である。サーバは受動的であり、クライアントから のリクエストを待つ。 セション SSLセションは、クライアントとサーバとの関連付け である。セションはハンドシェイクプロトコルに よって生成される。セションでは、1つの暗号セキュ リティパラメータセットを定義する。このパラメータ は複数のコネクションにより共有することができる。 セションは、それぞれのコネクションにおいて新しい セキュリティパラメータをネゴシエーションする、 という高負荷処理を避けるのに使用される。 セション識別子 セション識別子は、サーバによって生成される値で、 特定のセションを識別するためのものである。 サーバ書き出し鍵 データを暗号化するためにサーバが使用する鍵。 サーバ書き出しMACシークレット データを認証するためにサーバが使用するシーク レットデータ。 SHA(Secure Hash Algorithm) FIPS PUB 180-1で定義されている。これは20バイト のデータを出力する [SHA]。 ストリーム暗号 暗号化鍵を、暗号的に強度な鍵ストリームに変換 する暗号化アルゴリズム。その後平文と排他的OR 処理を行う。 対称暗号 大量暗号の項を参照。 付録 C C. 暗号スイートの定義 暗号スイート 輸出可能 鍵交換 暗号 ハッシュ SSL_NULL_WITH_NULL_NULL * NULL NULL NULL SSL_RSA_WITH_NULL_MD5 * RSA NULL MD5 SSL_RSA_WITH_NULL_SHA * RSA NULL SHA SSL_RSA_EXPORT_WITH_RC4_40_MD5 * RSA_EXPORT RC4_40 MD5 SSL_RSA_WITH_RC4_128_MD5 RSA RC4_128 MD5 SSL_RSA_WITH_RC4_128_SHA RSA RC4_128 SHA SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 * RSA_EXPORT RC2_CBC_40 MD5 SSL_RSA_WITH_IDEA_CBC_SHA RSA IDEA_CBC SHA SSL_RSA_EXPORT_WITH_DES40_CBC_SHA * RSA_EXPORT DES40_CBC SHA SSL_RSA_WITH_DES_CBC_SHA RSA DES_CBC SHA SSL_RSA_WITH_3DES_EDE_CBC_SHA RSA 3DES_EDE_CBC SHA SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA * DH_DSS_EXPORT DES40_CBC SHA SSL_DH_DSS_WITH_DES_CBC_SHA DH_DSS DES_CBC SHA SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA DH_DSS 3DES_EDE_CBC SHA SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA * DH_RSA_EXPORT DES40_CBC SHA SSL_DH_RSA_WITH_DES_CBC_SHA DH_RSA DES_CBC SHA SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA DH_RSA 3DES_EDE_CBC SHA SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA * DHE_DSS_EXPORT DES40_CBC SHA SSL_DHE_DSS_WITH_DES_CBC_SHA DHE_DSS DES_CBC SHA SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA DHE_DSS 3DES_EDE_CBC SHA SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA * DHE_RSA_EXPORT DES40_CBC SHA SSL_DHE_RSA_WITH_DES_CBC_SHA DHE_RSA DES_CBC SHA SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA DHE_RSA 3DES_EDE_CBC SHA SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 * DH_anon_EXPORT RC4_40 MD5 SSL_DH_anon_WITH_RC4_128_MD5 DH_anon RC4_128 MD5 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA DH_anon DES40_CBC SHA SSL_DH_anon_WITH_DES_CBC_SHA DH_anon DES_CBC SHA SSL_DH_anon_WITH_3DES_EDE_CBC_SHA DH_anon 3DES_EDE_CBC SHA SSL_FORTEZZA_KEA_WITH_NULL_SHA FORTEZZA_KEA NULL SHA SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA FORTEZZA_KEA FORTEZZA_CBC SHA SSL_FORTEZZA_KEA_WITH_RC4_128_SHA FORTEZZA_KEA RC4_128 SHA * は、IsExportableがtrueであることを示す。 鍵交換 アルゴリズム 説明 鍵サイズ制限 DHE_DSS DSS署名を使用した一時的DH なし DHE_DSS_EXPORT DSS署名を使用した一時的DH DH = 512ビット DHE_RSA RSA署名を使用した一時的DH なし DHE_RSA_EXPORT RSA署名を使用した一時的DH DH = 512ビット RSA = なし DH_anon 匿名DH、署名なし なし DH_anon_EXPORT 匿名DH、署名なし DH = 512ビット DH_DSS DSSベースの証明書を使用したDH なし DH_DSS_EXPORT DSSベースの証明書を使用したDH DH = 512ビット DH_RSA RSAベースの証明書を使用したDH なし DH_RSA_EXPORT RSAベースの証明書を使用したDH DH = 512ビット RSA = なし FORTEZZA_KEA FORTEZZA KEA。詳細は非公開。 N/A NULL 鍵交換なし N/A RSA RSA鍵交換 なし RSA_EXPORT RSA鍵交換 RSA = 512ビット 鍵サイズ制限 鍵サイズ制限により、輸出可能な暗号スイートを使用 して行う暗号化処理において法律上適用が可能な、 最大の公開鍵サイズが決定される。 鍵 拡張鍵 輸出 マテリ マテリ 有効鍵 IV ブロック 暗号 型 可能 アル アル ビット サイズ サイズ NULL Stream * 0 0 0 0 N/A FORTEZZA_CBC Block NA(**) 12(**) 96(**) 20(**) 8 IDEA_CBC Block 16 16 128 8 8 RC2_CBC_40 Block * 5 16 40 8 8 RC4_40 Stream * 5 16 40 0 N/A RC4_128 Stream 16 16 128 0 N/A DES40_CBC Block * 5 8 40 8 8 DES_CBC Block 8 8 56 8 8 3DES_EDE_CBC Block 24 24 168 8 8 * は、IsExportableがtrueであることを示す。 ** FORTEZZA では、鍵とIVの生成に独自のアルゴリズムを使用する。 鍵マテリアル 書き出し鍵を生成するのに使用されるkey_blockの バイト数。 拡張鍵マテリアル 実際に暗号化アルゴリズムに提供されるバイト数。 有効鍵ビット 暗号化ルーチンに提供される鍵マテリアルの内の エントロピー量。 ハッシュ ハッシュ パディング 関数 サイズ サイズ NULL 0 0 MD5 16 48 SHA 20 40 付録 D D. 実装上の注意 SSLプロトコルでは、多くの一般的なセキュリティミスを防ぐことはできない。 この章では、実装者のためのさまざまな推奨事項を示す。 D.1 一時的RSA鍵 米国の輸出制限では、暗号化処理に使用可能なRSA鍵は512ビットまでに制限され ているが、署名処理に使用可能なRSA鍵の長さには制限を設けていない。証明書 では、512ビットより長いビット長が必要となる場合がある。なぜならば、512 ビットのRSA鍵では、高額のトランザクションや、長期のセキュリティを必要と するアプリケーションでは、十分に安全であるとは言えないからである。また ある証明書では、署名目的のみと指定されている場合がある。この場合、鍵交換 においてこの証明書を使用することはできない。 証明書に記載されている公開鍵が暗号化処理に使用できない場合には、サーバ は一時的RSA鍵に署名し、その鍵を交換する。輸出可能なアプリケーションにお いては、一時的RSA鍵は、許容される最大の長さ(すなわち、512ビット)である べきである。 512ビットのRSA鍵はそれほど安全ではないので、一時的RSA鍵は ときどき変更するべきである。 典型的な電子商取引アプリケーションにおい ては、その鍵は一日ごと、または500トランザクションごと、できればそれ以上 の頻度で変更することを提案する。多くのトランザクションに対して、同じ 一時的鍵を使用することが出来るが、この鍵は、使用されるごとに署名されな ければならないということに注意すべきである。 RSA鍵生成処理には、かなりの時間を要する。多くの場合、鍵生成タスクは、 低い優先度をもつプロセスに対して割り当てられる。新しい鍵が生成された ときには、これまでの一時的鍵を新しいものと取り替えることができる。 D.2 乱数生成とその種 SSLでは、暗号的に安全な擬似乱数生成器(pseudorandom number generator:PRNG) が必要である。PRNGの設計と種の生成は、十分に注意すべきである。セキュア ハッシュで最も有名なのはMD5とSHAであるが、これに基づくPRNGは許容すること ができる。しかし、乱数発生器ステータスのサイズより高いセキュリティを提供 することはできない。 (例えば、MD5ベースのPRNGは通常、128ビットステータス を提供する。) 生成する種の量を推定するために、それぞれの種バイトにおいて予測すること のできない情報のビット数を加える。例えば、PCと互換性のある18.2Hzのタイマ から取得されたキーストロークタイミング値により、カウンタ値の全サイズが 16ビット以上であっても、1または2ビットの安全なビットが取得できる。 それゆえ、128ビットPRNGに対する種を生成するには、100個程度のそのような タイマ値が必要となることになる。 警告: RSAREFと、バージョン3.0より前のBSAFEの種関数は、順序非依存である。 例えば、種関数を1000回呼び出し、1度に1個、1000個の種ビットが提供 されるとき、PRNGは種データにおける種ビットの、0または1の数のみに 依存するステータスで終了する(すなわち、1001個の終了ステータスが 存在する)。BSAFEまたはRSAREFを使用しているアプリケーションでは、 適切な種処理がされていることに特に注意を払わなければならない。 D.3 証明書と認証 実装においては、証明書の有効性について検証する責任があり、また一般に、 証明書失効メッセージをサポートするべきである。 証明書が信用のおける認証局に よって適切に署名されていることを、常に確認するべきである。信用のおけるCAの 選択と追加については、十分に気をつけるべきである。ユーザに対し、証明書に 関する情報と、ルートCAに関する情報を見ることができるようにするべきである。 D.4 暗号スイート SSLでは、さまざまな鍵サイズとセキュリティレベルをサポートしている。これ には、セキュリティなし、すなわち最小のセキュリティ提供も含まれる。適切な 実装においてはおそらく、それほど多くの暗号スイートをサポートしないであろう。 例えば、40ビットの暗号化では容易に解読されてしまうので、高いセキュリティ が要求される実装では40ビットの鍵を認めるべきでない。同様に、匿名Diffie- Hellmanでは、なりすまし攻撃を防ぐことができないので、全く推奨されない。 また、アプリケーションでは最小と最大の鍵サイズを強制するようにするべき である。例えば、512ビットのRSA鍵または署名を含む証明書チェーンは、 高セキュリティアプリケーションにおいては適切ではない。 D.5 FORTEZZA この章では、FORTEZZAハードウエア暗号システムを利用する暗号スイートの実装 の詳細について記述する。 D.5.1 FORTEZZAハードウエアの使用に関する注記 FORTEZZAハードウエアの使用に関するすべての問題点に対する完全な説明は、 このドキュメントの範囲外である。しかし、SSLに関して記述する必要のある 特別な要件がいくつか存在する。 SSLは完全に2重化されているプロトコルであるので、2つの暗号ステータスを 維持しなければならない。2つのステータスとは、1つは読み込み、もう1つは 書き出しステータスである。またFORTEZZAカードにおいて、暗号ステータスが 失われてしまう多くの状況が存在する。これらの理由のため、カレントの暗号 ステータスはある1つのレコードの処理後に保存し、次のレコードの処理の前に ロードすることが推奨される。 クライアントがTEKを生成した後、クライアントはさらに2つのMEKを生成する。 1つは読み込み用、もう1つは書き出し用である。これらの鍵を生成した後、クライ アントは関連するIVを生成し、そして暗号ステータスを保存しなければならない。 クライアントはまた、TEKを使用してIVを生成し、プレマスターシークレットを 暗号化する。これらの3つのIVすべてと、ラップされた鍵、そして暗号化された プレマスターシークレットは、ClientKeyExchangeメッセージによりサーバに送信 される。この時点で、TEKは必要なくなり、そして捨てられる。 サーバ側では、マスターIVとTEKを使用してプレマスターシークレットを復号 する。またラップされたMEKをカードにロードする。サーバは2つのIVをロード し、IVが鍵と一致するか否かを検証する。しかしカードでは、IVをロードした 後には暗号化をすることができないため、サーバは書き出し鍵用の新規IVを生成 しなければならない。このIVは後に捨てられる。 最初の暗号化すべきレコードを暗号化したとき(そしてこのレコードを処 理したときのみ)に、サーバはランダムな8バイトのデータをフラグメントの 最初に追加する。これらの8バイトは暗号化の後、クライアントによって捨て られる。この目的は、異なったIVを使用しているクライアントとサーバの間で、 ステータスの同期をとることである。 D.5.2 FORTEZZA の暗号スイート 5) FORTEZZA_NULL_WITH_NULL_SHA: 完全なFORTEZZA鍵交換を行う。これには、サーバ書き出し鍵、クライアント 書き出し鍵とIVの送信が含まれる。 D.5.3 FORTEZZA におけるセション再利用 FORTEZZAのセション再利用には、2つの可能性がある。 1) FORTEZZAのセション再利用を行わない。 2) 以前にネゴシエーションされた鍵とIVを使用してセションを再利用する。 FORTEZZAのセション再利用を行わない: FORTEZZAセションの再利用を行わないクライアントは、ClientHelloメッセージ において、以前のFORTEZZAセションで使用されたセションIDを送信しない。 FORTEZZAセションの再利用を行わないサーバは、ネゴシエーションされた セションにおいてFORTEZZAを使用する場合には、ServerHelloメッセージ において以前のセションIDを送信しない。 セションを再利用する: FORTEZZA鍵交換が完了していないセションでは、再利用することはできない (すなわち、再利用を行おうとするセションがRSA/RC4を使用しており、 再ネゴシエーションの結果FORTEZZAを使用しようとする場合には、FORTEZZAを 再利用することはできない)。FORTEZZAセションを再利用したい場合には、 そのセションの最初の鍵交換におけるMEKとIVを保存しておき、そのセションを 使用した新規コネクションではそれを使用しなければならない。これは推奨 されないが、可能である。 付録 E E. バージョン2.0との下位互換 SSLバージョン2.0をサポートしているSSLバージョン3.0クライアントは、バー ジョン2.0 の ClientHelloメッセージを送信しなければならない[SSL-2]。バー ジョン3.0サーバは、どちらのClientHelloも受理するべきである。バージョン 2.0の仕様と異なっている点は、バージョンの値が3であることを特定する能力と、 CipherSpecで指定される暗号タイプがより多いことだけである。 警告:バージョン2.0のClientHelloメッセージを送信する機能は、迅速に廃止 されるだろう。実装者はできるだけ早く、アップデートするための あらゆる努力をするべきである。バージョン3.0では、より新しい バージョンにアップデートするための、より良いメカニズムを提供 している。 以下の暗号仕様は、SSLバージョン2.0から引き継がれたものである。これらは 鍵交換と認証において、RSAを使用するものと仮定している。 V2CipherSpec SSL_RC4_128_WITH_MD5 = { 0x01,0x00,0x80 }; V2CipherSpec SSL_RC4_128_EXPORT40_WITH_MD5 = { 0x02,0x00,0x80 }; V2CipherSpec SSL_RC2_CBC_128_CBC_WITH_MD5 = { 0x03,0x00,0x80 }; V2CipherSpec SSL_RC2_CBC_128_CBC_EXPORT40_WITH_MD5 = { 0x04,0x00,0x80 }; V2CipherSpec SSL_IDEA_128_CBC_WITH_MD5 = { 0x05,0x00,0x80 }; V2CipherSpec SSL_DES_64_CBC_WITH_MD5 = { 0x06,0x00,0x40 }; V2CipherSpec SSL_DES_192_EDE3_CBC_WITH_MD5 = { 0x07,0x00,0xC0 }; バージョン3.0において導入された暗号仕様は、以下の構文を使用することに より、バージョン2.0のClientHelloメッセージに含めることができる。最初の バイトがゼロであるV2CipherSpecの要素は、バージョン2.0サーバによって無視 される。上記のV2CipherSpecsを送信するクライアントはまた、バージョン3.0 における同等の値を含めるべきである(付録 A.6を参照)。 V2CipherSpec (see Version 3.0 name) = { 0x00, CipherSuite }; E.1 バージョン2のClientHello バージョン2.0のClientHelloメッセージは、本ドキュメントでのプレゼンテー ションモデルを使用して、以下のように表される。真の定義は、SSLバージョン 2.0仕様書に記載されている。 uint8 V2CipherSpec[3]; struct { unit8 msg_type; Version version; uint16 cipher_spec_length; uint16 session_id_length; uint16 challenge_length; V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length]; opaque session_id[V2ClientHello.session_id_length]; Random challenge; } V2ClientHello; msg_type このフィールドは、versionフィールドと関連して、 バージョン2のClientHelloメッセージであることを 示す。この値は1であるべきである。 version クライアントによってサポートされた最も高いプロ トコルバージョン(これはProtocolVersion.versionに 等しい。付録 A.1.1を参照)。 cipher_spec_length cipher_specsフィールドの長さ。ゼロであってはならず、 V2CipherSpecの長さ(3)の倍数でなければならない。 session_id_length このフィールドの値は0または16でなければならない。 もし0であれば、クライアントは新規セションを生成 していることを示す。もし16であれば、session_id フィールドには16バイトのセション識別子が格納される。 challenge_length サーバ認証のために、クライアントがサーバへ送信する challengeのバイト長。これは32でなければならない。 cipher_specs クライアントが使用を望んでいる、また使用可能な すべてのCipherSpecのリストを表す。ここには少なく とも、サーバが受理可能な1つのCipherSpecがなければ ならない。 session_id もしこのフィールドの長さが0でなければ、ここには クライアントが再利用したいと望んでいるセション 識別子が格納される。 challenge サーバを認証するための、サーバへの、サーバのための クライアントchallengeで、(おおよそ)任意長の乱数 である。バージョン3.0サーバは本バージョン3.0プロト コル規定に従い、challengeデータをClientHello.random データに変更する(必要であれば、0をパディングする)。 challengeの長さが32バイトよりも長いときは、後ろの 32バイトのみを使用する。V3サーバが、16バイト未満の challengeデータを含むV2のClientHelloを拒絶すること は認められる(ただし必要というわけではない)。 注: SSL3.0のセションの再利用リクエストでは、SSL3.0のClientHelloを使用 すべきである。 E.2 なりすましによるバージョンロールバック攻撃の回避 SSLバージョン3.0クライアントがバージョン2.0との互換モードになった場合には、 クライアントは特別な PKCS #1 ブロックフォーマットを使用する。これを行う ことにより、バージョン3.0サーバは、バージョン3.0が実行可能なクライアント との間でのバージョン2.0セションを拒否することができる。 バージョン3.0クライアントがバージョン2.0との互換モードであるときには、 CLIENT-MASTER-KEYメッセージのENCRYPTED-KEY-DATAフィールドをRSAにより暗号化 する際に、PKCSパディング(パディングの最後のNULLを含まない)における右側 (最下位)の8つのランダムバイトを0x03にセットする(他のパディングバイトは ランダムである)。ENCRYPTED-KEY-DATAフィールドを復号した後、SSL3.0を サポートするサーバでは、それら8つのパディングバイトが0x03であればエラーと すべきである。バージョン2.0をサポートするサーバがこの方法によるパディング ブロックを受信したときには、通常通りの処理が行われる。 付録 F F. セキュリティ解析 SSLプロトコルは、安全ではないチャネル上で通信するクライアントとサーバとの 間で、安全なコネクションを確立するように設計されている。このドキュメント では、さまざまな伝統的仮定を行っている。これらの仮定には、攻撃者がかなりの コンピュータリソースを持っており、プロトコルの外からはシークレット情報を 得ることができないという仮定が含まれている。攻撃者は、通信チャネル上を 送信されるメッセージを捕獲し、変更し、削除し、再送し、その他みだりにいじり まわす能力を持っていると仮定している。この付録では、SSLがさまざまな攻撃に 耐えるためにどのように設計されているのかを概説する。 F.1 ハンドシェイクプロトコル ハンドシェイクプロトコルは、CipherSpecを選択し、マスターシークレットを 生成する。そしてこれらにより、安全なセションに関する主要な暗号パラメータ が生成される。ハンドシェイクプロトコルはまた、信用のおける認証局によって 署名された証明書を持つパーティー間での認証を、任意で行うことができる。 F.1.1 認証と鍵交換 SSLは3つの認証モードをサポートしている: 双方の認証、サーバ認証と認証 されないクライアント、および完全な匿名である。サーバが認証されるときは、 そのチャネルはなりすまし攻撃に対しては安全であるが、完全な匿名セション では性質上そのような攻撃にさらされやすい。匿名サーバはクライアントを認証 することはできない。なぜならば、CertificateVerifyメッセージにおけるクライ アント署名では、その署名とそのサーバを結びつけるサーバ証明書が必要である からである。もしサーバが認証されるときは、サーバからのCertificateメッセージ は、信用のおける認証局へ通じる、有効な認証局チェーンを提供していなければ ならない。同様に、認証されるクライアントは、サーバで受理することのできる 証明書を提示しなければならない。それぞれのパーティーでは、相手の証明書が有効 であり、期間が切れていないか、または取り消されていないか、ということを 確認する責任がある。 鍵交換プロセスの一般的な目的は、攻撃者との間ではなく、通信を行っている パーティーとの間でのみ、pre_master_secretを生成することである。 pre_master_secretは、master_secretを生成するのに使用される(第6.1章を参照)。 master_secretは、Finishedメッセージ、暗号化鍵、MACシークレットを生成する ために必要である(第5.6.9節、第6.2.2節を参照)。正しいFinishedメッセージを 送信することにより、2つのパーティーは、正確なpre_master_secretを知っ ていることを確認する。 F.1.1.1 匿名鍵交換 鍵交換においてRSA、Diffie-Hellman、またはFORTEZZAを使用することで、完全に 匿名なセションを確立することができる。匿名RSAでは、クライアントは ServerKeyExchangeメッセージから抽出された、認証のされていないサーバの 公開鍵を使用してpre_master_secretを暗号化する。処理結果は、ClientKeyExchange メッセージで送信される。盗聴者はサーバの私有鍵を知らないため、盗聴者が pre_master_secretを復号することは不可能である。 Diffie-HellmanまたはFORTEZZAでは、サーバの公開パラメータはServerKeyExchange メッセージに含まれ、クライアントのパラメータはClientKeyExchangeメッセージで送信 される。私有値を知らない盗聴者は、Diffie-Hellman結果(すなわち pre_master_secret)またはFORTEZZAトークン暗号鍵(TEK)を知ることは出来ない。 警告:完全に匿名なコネクションでは、受動的な盗聴者に対する保護しか提供 されない。改竄の行われない独立したチャネルを使用してFinishedメッ セージが攻撃者により置きかえられてはいないことを確認しない限り、 能動的ななりすまし攻撃の懸念がある環境では、サーバ認証が必要と なる。 F.1.1.2 RSA鍵交換と認証 RSAでは、鍵交換とサーバ認証には関連がある。公開鍵はサーバ証明書に含まれ ているものか、またはServerKeyExchangeメッセージで送信される一時的RSA 鍵である。一時的RSA鍵を使用した場合には、それらはサーバのRSAまたはDSS 証明書により署名される。署名には、カレントのClientHello.randomが含まれる。 そのため、古い署名や古い一時的鍵は再利用できない。サーバは1つの一時的RSA 鍵を、複数のネゴシエーションセションに使用することが出来る。 注:一時的RSA鍵オプションは、サーバでは長いビット長をもつ証明書が必要で あるが、鍵交換処理においては政府により規制された鍵長制限に従わなければ ならない場合に有効である。 サーバ証明書の検証後、クライアントはpre_master_secretをサーバの公開鍵 で暗号化する。pre_master_secretを復号し、それにより正しいFinishedメッ セージを生成することにより、サーバはサーバ証明書に対応する私有鍵を 知っていることを実証する。 鍵交換方式としてRSAを使用した際には、クライアントはCertificateVerify メッセージ(第5.6.8節参照)により認証される。クライアントは、master_secret とこれまでのすべてのハンドシェイクメッセージから得られた値に対して署名 を行う。これらのハンドシェイクメッセージには、ServerCertificateと ServerHello.randomが含まれる。ServerCertificateは、署名とサーバを関連 付けるものである。ServerHello.randomは、署名とカレントのハンドシェイク プロセスを関連付けるものである。 F.1.1.3 認証を伴うDiffie-Hellman鍵交換 Diffie-Hellman鍵交換を使用する場合には、サーバは固定Diffie-Hellman パラメータを含む証明書を提供するか、またはServerKeyExchangeメッセージに より、DSSまたはRSA証明書により署名された一時的Diffie-Hellmanパラメータを 送信する。一時的パラメータは、署名される前にhello.random値と共にハッシュ される。これは攻撃者が古いパラメータを再利用しないようにするためである。 どちらの場合でも、クライアントは証明書または署名を確認し、パラメータが サーバのものであることを検証することができる。 もしクライアントが固定Diffie-Hellmanパラメータを含む証明書を所有している ならば、その証明書には鍵交換に必要な情報がすべて含まれている。この場合 クライアントとサーバは、同じDiffie-Hellman値(すなわちpre_master_secret) を、通信するごとに生成することになる。pre_master_secretが必要以上に長く メモリ上に残ることを防ぐために、出来るだけ早くmaster_secretへ変換する 必要がある。クライアントのDiffie-Hellmanパラメータは、鍵交換を行うために、 サーバにより提供されるパラメータとの互換性が必要である。 もしクライアントが標準DSSまたはRSA証明書を所有している、もしくはクライ アントが認証されないならば、クライアントはClientKeyExchangeメッセージに おいて、サーバに対し一時的パラメータを送信する。そしてオプショナルで、 自身を認証するために、CertificateVerifyメッセージを使用する。 F.1.1.4 FORTEZZA FORTEZZAの設計は機密事項であるが、プロトコルレベルでは、証明書内に公開値 が固定されているDiffie-Hellmanに類似している。鍵交換プロセスの結果は トークン暗号化鍵(token encryption key:TEK)であり、これはデータ暗号化鍵、 クライアント書き出し鍵、サーバ書き出し鍵、そしてマスターシークレット 暗号化鍵をラップするのに使用される。データ暗号化鍵はpre_master_secret からは作成されない。それはトークン外からは、ラップされていない鍵はアク セスできないからである。暗号化されたpre_master_secretは、ClientKeyExchange メッセージによりサーバに送信される。 F.1.2 バージョンロールバック攻撃 SSLバージョン3.0では、SSLバージョン2.0からのかなりの改良を含んでいるため、 攻撃者は、バージョン3.0の実行可能なクライアントとサーバを、バージョン2.0 に戻すようにさせるかもしれない。この攻撃は、2つのバージョン3.0の実行可能 なパーティーがSSL2.0ハンドシェイクを使用している場合のみに起こりうる。 ランダムではない、PKCS #1のブロック型2メッセージパディングを使用した解決 方法はエレガントではないが、これはバージョン3.0をサポートしているサーバ が攻撃を検出することの出来る、適度に安全な方法を提供する。この解決方法は、 アプリケーションが指定した待ち時間を過ぎるまでに、鍵に対してブルート フォース攻撃を行い、(通常のパディングを行った)同じ鍵を含む新しい ENCRYPTED-KEY-DATAメッセージに交換する攻撃者に対しては安全ではない。この 種の攻撃を懸念するパーティーでは、とにかく40ビットの暗号鍵を使用すべき ではない。PKCSパディングにおいての最後の8バイトのパディングを変更しても、 セキュリティには影響しない。なぜならば、これは入力ブロックサイズが8バイト 増加した、ということと本質的に同等であるからである。 F.1.3 ハンドシェイクプロトコルに対する攻撃の検出 攻撃者は、通常パーティーが選択する暗号アルゴリズムとは異なった暗号を 選択するように、ハンドシェイク処理に対して影響を及ぼそうとするかもしれ ない。多くの実装では、40ビットの輸出可能な暗号をサポートしており、また いくつかの実装ではNULL暗号とMACアルゴリズムのサポートさえ行うかもしれ ないため、この攻撃には特別の関心を払う必要がある。 この攻撃を行うためには、攻撃者は積極的に1つ以上のハンドシェイクメッセージを 変更しなければならない。もしこのようなことが発生した場合、クライアントと サーバは、ハンドシェイクメッセージのハッシュ値として異なった値を求めること になる。その結果、パーティーはお互いのFinishedメッセージを受理することはない。 master_secretがなければ、攻撃者はFishiedメッセージを修正することができない ので、その攻撃は発見されるであろう。 F.1.4 セションの再利用 セションを再利用することによってコネクションが確立されるとき、新しい ClientHello.randomとServerHello.random値は、セションのmaster_secretと 共にハッシュされる。もしmaster_secretが危険にさらされてなく、また暗号化 鍵とMACシークレットを生成するために使用されるハッシュ処理が安全であれば、 コネクションは安全で、以前のコネクションから独立している。攻撃者は、 安全なハッシュ処理(SHAとMD5の両方を使用する)を破ることなしに、既知の 暗号化鍵またはMACシークレットを使用して、master_secretを危険にさらす ことはできない。 クライアントとサーバの両方が合意しない場合、セションを再利用することは できない。どちらかのパーティーが、セションが危険にさらされている、もしく は証明書の有効期間が切れた、または取り消されたと考えたときには、完全な ハンドシェイクを強行するべきである。セションIDの生存時間は、最大でも 24時間であることを提案する。なぜならば、master_secretを入手した攻撃者は 対応するセションIDの有効期限が切れるまで、危険にさらされているパーティー を装うことができるからである。比較的安全でない環境で実行されるアプリケー ションでは、セションIDを静的な記憶装置に書き込むべきではない。 F.1.5 MD5とSHA SSLでは、ハッシュ関数を非常に保守的に使用する。可能なところでは、ある 1つのアルゴリズムに非壊滅的な欠点があっても、プロトコル全体を壊さない ことを確実にするために、MD5とSHAの両方をタンデムに使用する。 F.2 アプリケーションデータの保護 master_secretは、ClientHello.randomとServerHello.randomと共にハッシュ され、それぞれのコネクションにおいて使用される唯一のデータ暗号化鍵とMAC シークレットが作成される。FORTEZZA暗号化鍵はトークンにより生成される。 master_secretから生成されるわけではない。 送信データは、送信される前にMACにより保護される。メッセージ再送または メッセージ修正攻撃を防ぐために、MACはMACシークレット、シーケンス番号、 メッセージ長、メッセージコンテンツ、そして2つの固定文字列から計算される。 メッセージタイプフィールドは、あるSSLレコード層クライアントへのメッセージ が、他へリダイレクトされないことを確実にするのに必要である。シーケンス 番号を使用することにより、メッセージの削除または再要求を行おうとする試み は確実に検出できる。シーケンス番号は64ビットであるので、オーバーフロー することはほとんどない。ある1つのパーティーからのメッセージを、他方の パーティーの出力メッセージの中に挿入することはできない。なぜならば、 パーティーは独立したMACシークレットを使用しているからである。同様に、 サーバ書き出し鍵とクライアント書き出し鍵は独立しているため、ストリーム 暗号鍵は一度だけしか使用されない。 攻撃者が暗号化鍵を解読したならば、その鍵で暗号化されるすべてのメッセージ は解読される。同様に、MAC鍵が危険にさらされた場合には、メッセージ変更攻撃 が可能となる。MACは暗号化されるため、メッセージ変更攻撃は一般に、MACを 破ることと同時に、暗号化アルゴリズムを解読することが必要となる。 注:MACシークレットは暗号化鍵よりも大きくしてもよいので、暗号化鍵が解読 されたとしても、メッセージは改竄に対する耐性を持っている。 F.3 最終注記 SSLが安全なコネクションを提供できるようにするためには、クライアントと サーバの両方のシステム、鍵、およびアプリケーションは安全でなければなら ない。さらに、実装においてセキュリティエラーがあってはならない。 システムは、サポートしている最も弱い鍵交換アルゴリズム、最も弱い認証 アルゴリズムと同じ程度の強度しか持っていない。そして信頼できる暗号関数 だけが使用されるべきである。短い公開鍵、40ビットの大量暗号化鍵、およ び匿名サーバを使用するときには、十分に注意すべきである。実装者とユーザ は、どの証明書とどの認証局を受け入れるのかを決めるときには、十分に注意 しなければならない。不遜な認証局により、大変な損害を受けることがある。 付録 G G. 特許声明 SSLプロトコルの本バージョンでは、認証と暗号化の際に、特許請求が行われて いる公開鍵暗号技術を使用する。RFC 1310に規定されているインターネット標準 化プロセスでは、提案標準、ドラフト標準、またはインターネット標準としての 仕様が認可される前に、適切な条件の下では、応募者に対しライセンスが利用可能 であるという特許所有者からの文書が必要であるとしている。マサチューセッツ 工科大学は、RSA Data Security,Inc. に対し、アメリカ合衆国において発行 された次の特許への独占的なサブライセンス権を認めている。 Cryptographic Communications System and Method ("RSA"), No. 4,405,829 Leland Stanford Junior Universityの評議委員会は、Caro-Kann Corporationと その関連会社に対し、アメリカ合衆国において発行された次の特許と、関係する すべての国外特許への独占的なサブライセンス権を認めている。 Cryptographic Apparatus and Method ("Diffie-Hellman"), No. 4,200,770 Public Key Cryptographic Apparatus and Method ("Hellman- Merkle"), No. 4,218,582 The Internet Society、Internet Architecture Board、Internet Engineering Steering Groupおよび The Corporation for National Research Initiativesは、 特許、特許アプリケーションの有効性または範囲、保証項目の適切さに関して、 どのような立場も取らない。The Internet Societyと前述の他のグループは、 この規格を実現する際に適用される可能性のあるその他の知的所有権に関しては、 どのような決定も行っていない。これらの事柄に関するさらなる考慮については、 ユーザの自己責任となる。 参考文献 [DH1] W. Diffie and M. E. Hellman, "New Directions in Cryptography," IEEE Transactions on Information Theory, V. IT-22, n. 6, Jun 1977, pp. 74-84. [3DES] W. Tuchman, "Hellman Presents No Shortcut Solutions To DES," IEEE Spectrum, v. 16, n. 7, July 1979, pp40-41. [DES] ANSI X3.106, "American National Standard for Information Systems-Data Link Encryption," American National Standards Institute, 1983. [DSS] NIST FIPS PUB 186, "Digital Signature Standard," National Institute of Standards and Technology, U.S. Department of Commerce, 18 May 1994. [FOR] NSA X22, Document # PD4002103-1.01, "FORTEZZA: Application Implementers Guide," April 6, 1995. [FTP] J. Postel and J. Reynolds, RFC 959: File Transfer Protocol, October 1985. [HTTP] T. Berners-Lee, R. Fielding, H. Frystyk, Hypertext Transfer Protocol -- HTTP/1.0, October, 1995. [IDEA] X. Lai, "On the Design and Security of Block Ciphers," ETH Series in Information Processing, v. 1, Konstanz: Hartung-Gorre Verlag, 1992. [KRAW] H. Krawczyk, IETF Draft: Keyed-MD5 for Message Authentication, November 1995. [MD2] R. Rivest. RFC 1319: The MD2 Message Digest Algorithm. April 1992. [MD5] R. Rivest. RFC 1321: The MD5 Message Digest Algorithm. April 1992. [PKCS1] RSA Laboratories, "PKCS #1: RSA Encryption Standard," version 1.5, November 1993. [PKCS6] RSA Laboratories, "PKCS #6: RSA Extended Certificate Syntax Standard," version 1.5, November 1993. [PKCS7] RSA Laboratories, "PKCS #7: RSA Cryptographic Message Syntax Standard," version 1.5, November 1993. [RSA] R. Rivest, A. Shamir, and L. M. Adleman, "A Method for Obtaining Digital Signatures and Public-Key Cryptosystems," Communications of the ACM, v. 21, n. 2, Feb 1978, pp. 120- 126. [RSADSI] Contact RSA Data Security, Inc., Tel: 415-595-8782 [SCH] B. Schneier. Applied Cryptography: Protocols, Algorithms, and Source Code in C, Published by John Wiley & Sons, Inc. 1994. [SHA] NIST FIPS PUB 180-1, "Secure Hash Standard," National Institute of Standards and Technology, U.S. Department of Commerce, DRAFT, 31 May 1994. [TCP] ISI for DARPA, RFC 793: Transport Control Protocol, September 1981. [TEL] J. Postel and J. Reynolds, RFC 854/5, May, 1993. [X509] CCITT. Recommendation X.509: "The Directory - Authentication Framework". 1988. [XDR] R. Srinivansan, Sun Microsystems, RFC-1832: XDR: External Data Representation Standard, August 1995. 著者 Alan O. Freier Paul C. Kocher Netscape Communications Independent Consultant freier@netscape.com pck@netcom.com Philip L. Karlton Netscape Communications karlton@netscape.com 協力 Martin Abadi Robert Relyea Digital Equipment Corporation Netscape Communications ma@pa.dec.com relyea@netscape.com Taher Elgamal Jim Roskind Netscape Communications Netscape Communications elgamal@netscape.com jar@netscape.com Anil Gangolli Micheal J. Sabin, Ph. D. Netscape Communications Consulting Engineer gangolli@netscape.com msabin@netcom.com Kipp E.B. Hickman Tom Weinstein Netscape Communications Netscape Communications kipp@netscape.com tomw@netscape.com レビュー Robert Baldwin Clyde Monma RSA Data Security, Inc. Bellcore baldwin@rsa.com clyde@bellcore.com George Cox Eric Murray Intel Corporation ericm@lne.com cox@ibeam.jf.intel.com Cheri Dowell Avi Rubin Sun Microsystems Bellcore cheri@eng.sun.com rubin@bellcore.com Stuart Haber Don Stephenson Bellcore Sun Microsystems stuart@bellcore.com don.stephenson@eng.sun.com Burt Kaliski Joe Tardo RSA Data Security, Inc. General Magic burt@rsa.com tardo@genmagic.com このドキュメントに関する、文書による議論は、以下のアドレスまで。 Netscape Communications 466 Ellis Street Mountain View, CA 94043-4042 Attn: Alan Freier 日本語訳 西原 啓輔 2002年1月 訳者は、訳出した文書を利用することにより発生したいかなる損害に対しても 責任を負いません。 本文書には、技術的あるいは翻訳上の誤りがある可能性があります。技術的に 正しい知識を獲得しなければならない場合は、InterNIC/IETFから発行されて いる原文を参照してください。