原文:ftp://ftp.rfc-editor.org/in-notes/rfc1991.txt

2005/02/06 0.1.0 初版
2006/03/05 0.2.0 一年以上ぶりに全体的に見直し。


Network Working Group
Request for Comments: 1991
Category: Informational





D. Atkins
MIT
W. Stallings
Comp-Comm Consulting
P. Zimmermann
Boulder Software Engineering
August 1996

PGPメッセージ交換フォーマット

この文書の位置付け

この文書はインターネットコミュニティのための情報を提供する。この文書はいかなるインターネット標準も規定しない。この文書の配布は無制限である。

目次

1. 導入
2. PGP サービス
2.1 デジタル署名
2.2 秘密保持
2.3 圧縮
2.4 Radix-64 変換
2.4.1 ASCII 装甲フォーマット(ASCII Armor Formats)
3. データ要素フォーマット
3.1 バイト文字列
3.2 整数フィールド
3.3 複合精度フィールド
3.4 文字列フィールド
3.5 時刻フィールド
4. 共通フィールド
4.1 パケット構造フィールド
4.2 数値 ID フィールド
4.3 バージョンフィールド
5. パケット
5.1 概観
5.2 一般的なパケット構造
5.2.1 メッセージ構成要素
5.2.2 署名構成要素
5.2.3 セッション鍵構成要素
6. PGP パケットタイプ
6.1 リテラルデータパケット
6.2 署名パケット
6.2.1 メッセージダイジェスト関連フィールド
6.2.2 公開鍵関連フィールド
6.2.3 RSA 署名
6.2.4 その他のフィールド
6.3 圧縮データパケット
6.4 慣用鍵暗号化データパケット
6.4.1 慣用鍵暗号化タイプバイト
6.5 公開鍵暗合化パケット
6.5.1 RSA 暗号化データ暗号鍵(DEK)
6.6 公開鍵パケット
6.7 ユーザー ID パケット
7. 転送可能公開鍵
8. 謝辞
9. セキュリティ考察
10. 著者のアドレス

1. 導入

PGP (Pretty Good Privacy) は公開鍵と定型的暗号化とを利用して、電子メールメッセージやデータファイルなど向けのセキュリティサービスを提供する。これらのセキュリティサービスには秘密保持やデジタル署名も含まれる。PGP は世界規模のコンピュータコミュニティで広く使用されている。この文書は "PGP ファイル(PGP files)"(PGP を用いて暗号化や署名がなされたメッセージ)の形式を説明する。

PGP は Philip Zimmermann によって作成され、1991 年にバージョン 1.0 として最初のリリースが行われた。それ以降のバージョンは Philip Zimmermann の設計指針の下、ボランティアたちの共同努力によって設計・実装されて来た。PGP と Pretty Good Privacy は Philip Zimmermann の商標である。

この文書は PGP のバージョン 2.x に付いて説明する。具体的には、バージョン 2.6 と 2.7 がこの規約に従う。バージョン 2.3 は若干の差違を持ってこの規約に従う。

PGP3.0 として知られる PGP の新しいリリースが 1995 年に予定されている。最大限可能な範囲で、それはバージョン 2.x と上位互換性を持つだろう。最低でも PGP3.0 はバージョン 2.x で生成された署名とメッセージとを読むことは出来るだろう。

2. PGP サービス

PGP はメッセージとデータファイルの形式とに関連する 4 つのサービス、デジタル署名・秘密保持・圧縮・radix-64 変換を提供する。

2.1 デジタル署名

デジタル署名サービスには、ハッシュコード・メッセージダイジェスト・アルゴリズム・公開鍵暗号アルゴリズムの使用が含まれる。その順序は以下の通り。

通常、署名はメッセージまたは署名されたファイルに固着されるが、必ずしもそうである必要はなく、分離された署名もサポートされている。分離された署名は、それが署名しているメッセージとは別に送信・保存されてもよい。これはいくつかの状況で有用である。ユーザーは送受信された全メッセージの個々の署名のログを保持したいと考えることができる。実行可能プログラムに対しての分離署名は、その後に起こるかもしれないウィルス感染を検出できる。分離された署名はさらに、法律上の契約といった二つ以上のグループが文書に署名しなければならない場合にも利用できる。これは各個人の署名が独立しているので、その文書にだけ適用されるためである。もしそうでなければ、二番目の署名者がその文書と最初の署名との両方に署名するというように繰り返し署名していき、署名をネストさせなければならない。

2.2 秘密保持

転送されるメッセージやローカルに保存するデータファイルを昔ながらの暗号を使用して暗号化することで、PGP は秘密保持を提供する。PGP では従来の鍵は一度だけ使用される。すなわち、メッセージ毎に新しい鍵が 128 ビットの乱数として生成されるのである。一度しか使用されないが故に、セッション鍵はメッセージに付けられて一緒に送信される。鍵を保護するために、鍵は受信者の公開鍵で暗号化される。その一連の手順は以下の通り。

次のようにしてデジタル署名と秘密保持とを同じメッセージに適用することもできる。最初にそのメッセージの署名を作成しメッセージに追加する。次に通常のセッション鍵を使用してメッセージと署名とを暗号化する。最後にセッション鍵を公開鍵で暗号化し、暗号ブロックに追加する。

2.3 圧縮

デフォルトで PGP は、署名の適用後、暗号化の前にメッセージを圧縮する。

2.4 Radix-64 変換

通常 PGP が使用される場合、送信されるブロックの一部が暗号化される。署名サービスのみが使用される場合にはメッセージダイジェストが(送信者の秘密鍵を使って)暗号化される。秘密保持サービスのみを使用する場合にはメッセージと(もしあれば)署名とが(1 回限りの鍵を使って)暗号化される。したがって結果として生成されるブロックの一部または全部は、無作為なバイト(8 ビット)のストリームから構成されることになる。しかしながら多くの電子メールシステムは ASCII テキストから構成されるブロックの使用だけを許可している。この制約に対応するため、PGP は生の 8 ビットバイナリストリームを印刷可能な ASCII 文字ストリームに変換するサービスを提供している。これは ASCII 装甲と呼ばれる。

この目的に使用される仕組みが radix-64 変換である。バイナリデータ 3 バイトが 4 文字の ASCII 文字にマップされる。転送エラーを検出するために CRC も追加される。この ASCII 装甲とも呼ばれる radix-64 変換はバイナリの PGP メッセージのラッパーであり、インターネット電子メールのような非バイナリチャンネルを経由する通信において、バイナリメッセージを保護するために使用される。

以下の表はマッピングの定義である。使用される文字は、大文字・小文字・0〜9 の数字・+・- である。復帰文字や改行文字は変換に使用されず、タブ文字や、メールシステムによって変更されるかもしれない他の文字も使用されない。その結果はメールシステムによって加えられる変更から "免れた(immune)" テキストファイルとなる。

 6ビット           6ビット            6ビット            6ビット
   値    文字符号    値     文字符号    値     文字符号     値    文字符号 
   0        A        16        Q        32        g        48        w
   1        B        17        R        33        h        49        x
   2        C        18        S        34        i        50        y
   3        D        19        T        35        j        51        z
   4        E        20        U        36        k        52        0
   5        F        21        V        37        l        53        1
   6        G        22        W        38        m        54        2
   7        H        23        X        39        n        55        3
   8        I        24        Y        40        o        56        4
   9        J        25        Z        41        p        57        5
   1        K        26        a        42        q        58        6
   11       L        27        b        43        r        59        7
   12       M        28        c        44        s        60        8
   13       N        29        d        45        t        61        9
   14       O        30        e        46        u        62        +
   15       P        31        f        47        v        63        /
                                                         (詰め)      =

任意のファイルを ASCII 装甲に変換するために PGP を使用することも許されている。その場合ファイルを Radix-64 に変換する前に、PGP はそのデータの圧縮を試みる。

2.4.1 ASCII装甲フォーマット

データを ASCII 装甲にエンコードする時にデータの前後に特殊なヘッダを挿入することにより、PGP は後でデータを再構築できる。PGP はこのヘッダを使用して、ASCII 装甲の中にどのような種類のデータがエンコードされているのかを使用者に知らせようとする。

ASCII 装甲は以下のデータを連結することで生成される。

  • 装甲ヘッダ行(データの種別に応じた内容)
  • 装甲ヘッダ
  • 空行
  • ASCII 装甲データ
  • 装甲チェックサム
  • 装甲テール(装甲ヘッダ行に依存する)
  • 装甲ヘッダ行は、ヘッダ行の両サイドを 5 つのダッシュ記号(-)で囲んだ適切なヘッダ行テキストを持つことで構成される。装甲内にエンコードされているデータの種類とエンコード方法とに基づいてヘッダ行のテキストが選択される。ヘッダ行のテキストは以下の文字列を含む。

    BEGIN PGP MESSAGE
    署名されたファイル、または暗号化されたファイル、または圧縮されたファイルに使用される。
    BEGIN PGP PUBLIC KEY BLOCK
    公開鍵の送信時に使用される。
    BEGIN PGP MESSAGE, PART X/Y
    マルチパートメッセージで使用される。Y 個のファイルに分割されており、Y 個の内の X 番目であることを表す

    装甲ヘッダは、使用者や受信側 PGP プログラムにそのメッセージの解読や利用の方法に関する情報を与える文字列の組である。装甲ヘッダはメッセージの一部ではなく、装甲の一部である。したがって通信中に変更される可能性があるため、重要な情報を伝えるために使用するべきものではない。

    装甲ヘッダのフォーマットは RFC-822 ヘッダのエンコード方法である "キー - 値" の組の形式である。PGP は不正な形式の装甲ヘッダを ASCII 装甲の汚染であると見なすべきである。不明なキーは使用者に報告されるべきだが、正しい RFC-822 フォーマットである限り、PGP はメッセージを処理し続けるべきである。現在定義されている装甲ヘッダキーは "Version" と "Comment" であり、それぞれメッセージを解読するための PGP のバージョンとユーザー定義のコメントである。

    装甲チェックサムは 24 ビット の CRC であり、radix-64 により 4 バイトに変換され、その 4 バイトの先頭に等号(=)が付けられる。この CRC は初期値 0xB704CE とジェネレータ 0x864CFB とを使用して計算される。この計算は radix-64 変換後のデータに対してではなく、変換前のデータに対して行われる。CRC 機能に関するさらなる情報は、Joe Cambell 著 "C Programmer's Guide to Serial Communications," の 19 章を参照してほしい。

    "BEGIN" が "END" に置き換わることを除き、装甲テールは装甲ヘッダと同じ構成である。

    3. データ要素フォーマット

    3.1 バイト文字列

    この文書で考慮されている対象は全て "バイト文字列" である。バイト文字列は有限の連続バイトである。長さ M のバイト文字列 X と長さ N のバイト文字列 Y との連結は、長さ M + N のバイト文字列 Z である。ここで Z の最初の M バイトは同じ順序の X のバイトと同一であり、Z の残りの N バイトは同じ順序の Y のバイトと同一である。

    リテラルのバイト文字列は 16 進 4 ビットの対を左から右に空白文字で区切って書かれ、アングルブラケットで囲まれる。例えば <05 ff 07> は、数値 5、255、7 をこの順に持つ長さ 3 バイトのバイト文字列である。この文書ではアングルブラケットの外の数値は全て 10 進で書かれている。

    長さ 0 のバイト文字列は "空(empty)" と呼ばれ、<>と書く。

    3.2 整数フィールド

    用途。整数フィールドは任意の非負の整数を表現できる形式であり、前もってフィールド長が分かっている場合に使用される。

    定義。整数フィールドは任意のバイト文字列であり、radix-256 MSB-first 形式(最上位ビットが先頭に来る形式)で保存される。これは、バイト列 b_0 b_1 ... b_{N-2} b_{N-1}をこの順で持つ長さ N の整数フィールドが以下の値を持つことを意味する。

    b_0 * 256^{N-1} + b_1 * 256^{N-2} + ... + b_{N-2} * 256 + b_{N-1}.

    例。バイト文字列 <00 0D 64 11 00 00> は値 57513410560 を持つ有効な整数フィールドである。バイト文字列 <FF> は値 255 を持つ有効な整数フィールドである。バイト文字列 <00 00> は値 0 を持つ有効な整数フィールドである。空バイト文字列 <> は値 0 を持つ有効な整数フィールドである。

    3.3 複合精度フィールド

    目的。複合精度フィールドは、大き過ぎない非負の整数を表現できる。フィールド長が前もって分かっている必要はない。複合精度フィールドは非常に小さい領域しか消費しないように設計されている(小さい整数には短いフィールドが使われる)。

    定義。複合精度フィールドは以下の二つのフィールドを連結したものである。

    (a) 長さ 2 の整数フィールド 値 B
    (b) 整数フィールド 値 V

    フィールド(b)の長さは[(B+7)/8]である(つまり最大でも (B+7)/8 を超えない)。複合精度フィールドの値は V であると定義される。V は 2^{B-1} と 2^B - 1 の間に含まれなければならない。言い換えると、B は V の有効ビット数と正確に一致しなくてはならない。

    実装は B の取りうる範囲を制限してもよい。実装者は B に許される値の範囲を明文化しなければならない。

    例。バイト文字列 <00 00> は値 0 を持つ有効な複合精度整数である。バイト文字列 <00 03 05> は値 5 を持つ有効な複合精度フィールドである。バイト文字列 <00 03 85> および <00 00 00> は有効な複合精度フィールドではない。前者は <85> が 3 ビットではなく 8 ビットの有効ビットを持つため、後者は第二フィールドが第一フィールドの値で与えれれるデータのバイト数より多いため、無効である。バイト文字列 <00 09 01 ff> は値 511 を持つ有効な複合精度フィールドである。バイト文字列 <01 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 07> は値 2^255 + 7 を持つ有効な複合精度フィールドである。

    3.4 文字列フィールド

    目的。文字列フィールドは 0 から 255 の長さを持つ任意の連続バイトを表す。事前に長さが分かっている必要はない。習慣的に文字列フィールドの内容は、表示される時には ASCII コードに変換される。

    定義。文字列フィールドは以下の内容を持つ。

    (a) 長さ 1 の整数フィールド 値 L
    (b) 長さ L のバイト文字列

    文字列フィールドの内容はフィールド(b)に定義される。

    例。<05 48 45 4c 4c 4f> は、通常 HELLO と表示される有効な文字列フィールドである。<00> は通常空文字として表示される有効な文字列フィールドである。<01 00> は有効な文字列フィールドである。

    3.5 時刻フィールド

    目的。時刻フィールドは 1970 Jan 1 00:00:00 GMT からの経過秒数を表す。これは UNIX 環境での一般的な時刻表現と互換性を持つ。

    定義。時刻フィールドは長さ 4 の整数フィールドである。値 V の時刻フィールドが表す時刻は、1970 Jan 1 00:00:00 GMT を基点として V 秒目から始まる一秒間である。

    4. 共通フィールド

    このセクションでは 2 つ以上のパケットから構成されるフィールドを定義する。

    4.1 パケット構造フィールド

    目的。パケット構造フィールドは異なるタイプのパケットを区別したり、パケット長を表したりする。

    定義。パケット構造フィールドはバイト文字列であり、長さは 1・2・3・5 の何れかである。その先頭バイトは暗号タイプバイト(CTB:cipher type byte)であり、各ビットは 76543210 とラベル付けされ、7 が最上位ビット、0 が最下位ビットである。以下で示す通り、パケット構造フィールドの長さは CTB によって決定する。

    CTB のラベル 76 のビットは以下の表に示す値を持つ。

    10 - 通常の CTB
    11 - 将来の実験的作業のために予約済み
    その他 - 予約済み

    CTB のラベル 5432 のビット("パケットタイプビット")は以下の表に示す値を持つ。

    0001 - 公開鍵暗号化パケット
    0010 - 署名パケット
    0101 - 秘密鍵証明パケット
    0110 - 公開鍵証明パケット
    1000 - 圧縮データパケット
    1001 - 慣用鍵暗号化パケット
    1011 - リテラルデータパケット
    1100 - 鍵リング信頼パケット
    1101 - ユーザー ID パケット
    1110 - コメントパケット (*)
    その他 - 予約済み

    CTB のラベル 10 のビット("パケット長ビット")は以下の表に示す値を持つ。

    00 - パケット長が 1 バイトのフィールド
    01 - パケット長が 2 バイトのフィールド
    10 - パケット長が 4 バイトフィールド
    11 - パケット長が提供されていない。パケット長が不明。

    この表で示されているように、パケット長ビットに応じて、パケット構造フィールドの残りの 1・2・4 バイトまたは 0 バイトが "パケット長フィールド" となる。パケット長フィールドは整数フィールドであり、その整数フィールドの値がパケット長フィールドの値である。

    現在のところ値 11 は圧縮データにおいてのみ使用されている。つまり現状では、圧縮されたデータブロックは例えば <A3 01 . . .> のような形で、ここで <A3>(2 進数 10 1000 11)は不定長パケットを表している。これが最も外側(囲み構造の終わりがファイルである位置)に現れることは決してないが、その適切な解釈は "囲み構造の終わりまで" である。

    (*)の付いたオプションはまだ実装されおらず、PGP2.6.2 がそのパケットタイプを出力することはない。

    4.2 数値 ID フィールド

    目的。整数の ID は、その下位 64 ビットである。鍵のような大きな数値を識別する場合に数値の ID は都合のよい方法であり、数値全体を送信する必要がない。つまり十進数での長さが数百桁、数千桁になるかもしれない数値を、64 ビットの識別子で表現できるということである。ランダムに選ばれた二つの大きな鍵が同じ ID を持つ確率は極端に小さいが、偶然や悪意によって二つの鍵が同じ ID をもつ可能性はある。

    定義。数値 ID フィールドは長さ 8 の整数フィールドである。数値 ID フィールドの値はその整数フィールドの値である。

    4.3 バージョンフィールド

    多くのパケットタイプは、その本体の最初のバイトとしてバージョンフィールドを含む。本体の形式とその意味は、そのバージョン番号に依存する。新しいバージョン番号を持つパケットが将来定義されてもよい。実装が各々のパケットタイプの全てのバージョンをサポートする必要はない。しかしながら実装者は、その実装が各々のパケットタイプのどのバージョンをサポートしているのかを明文化しなければならない。

    現状では各々のパケット形式に対してバージョン番号 2 または 3 が許可されている。新しいバージョンは、おそらく 3 から連続して番号付けされるだろう。下位互換性のために、バージョン N+1 のパケットをサポートしている実装は、バージョン N のパケットもサポートしていることを期待されるだろう。バージョン 255 は実験的な目的のために使用されることが許されている。

    5. パケット

    5.1 概観

    パケットは内部にデータを持つデジタルなエンベロープである。定義により PGP ファイルは 1 つ以上のパケットを連結したものである。また 1 ファイルの中の 1 つ以上のパケットが、暗号・圧縮・radix-64変換を使用した変換の影響を受けてももよい。

    パケットは以下の内容を連結したものである。

    (a) 1 つのパケット構造フィールド
    (b) 長さ N のバイト文字列

    バイト文字列(b)はパケットの "本体" と呼ばれる。パケット構造フィールド(a)内のパケット長フィールドの値は、N すなわち本体の長さと一致しなければならない。

    パケットのその他の特徴はパケットタイプによって決定される。特定のパケットタイプのさらなる詳細に付いては、その定義を参照してほしい。パケット構造の中の CTB パケットタイプビットは常にそのパケットタイプを示す。

    パケットはネストされる(あるデジタルエンベロープの中に別のデジタルエンベロープが存在する)可能性があることに注意してほしい。例えば慣用鍵暗合化パケットは偽装されたパケットを内包しており、それは圧縮データパケットかもしれない。

    5.2 一般的なパケット構造

    PGP ファイルは 3 つの要素、メッセージ部・署名(任意)・セッション鍵部から構成される。

    5.2.1 メッセージ部

    実際のデータを含むメッセージ部は、PGP によって生成された制御情報を含むヘッダと同じように送信・保存される。メッセージ部は単独のリテラルデータパケットから構成される。

    5.2.2 署名部

    署名部はメッセージ部の署名であり、送信側 PGP の公開鍵とメッセージ部のハッシュコードとを使って作られる。署名部は単独の署名パケットから構成される。

    圧縮のデフォルトオプションが選択された場合、リテラルデータパケットと署名パケットとを含むブロックは圧縮され、圧縮データパケットとなる。

    5.2.3 セッション鍵部

    セッション鍵部は、暗号化されたセッション鍵と、セッション鍵を暗号化するために送信者によって使用された受信者の公開鍵の識別子とを含む。セッション鍵部はそのメッセージの受信者用の単独の公開鍵パケットから構成される。

    圧縮が使用される場合、署名パケットとリテラルデータパケットとを圧縮した圧縮データパケットに慣用暗号が適用される。そうでなければ、慣用暗号は署名パケットとリテラルデータパケットとのブロックに適用される。どちらの場合も、その暗号文は慣用鍵暗号化データパケットと呼ばれる。

    6. PGP パケットタイプ

    PGP は以下のタイプのパケットを含む。

    6.1 リテラルデータパケット

    目的。リテラルデータパケットはデジタルエンベロープの最下位レベルの内容である。リテラルデータパケット内部のデータが PGP からそれ以上の変換を加えられることはない。

    定義。リテラルデータパケットは以下のフィールドを連結したものである。

    (a) 1 つのパケット構造フィールド
    (b) モードを表す 1 バイト
    (c) ファイル名を表す 1 つの文字列フィールド
    (d) 1 つの時刻フィールド
    (e) リテラルデータのバイト文字列

    フィールド(b)(c)(d)は、そのデータがどのようにファイルに書かれているかを表している。バイト(b)はバイナリ用の ASCII 文字 b <62> かテキスト用の ASCII 文字 t <74> の何れかである。またバイト(b)は ASCII の 1 の値を取ることもできる。その場合それはマシン固有の変換を表しており、PGP がプラットフォームをまたがってそれを変換する方法は定義されていない。

    フィールド(c)はファイル名を表す。フィールド(d)はファイルが最後に修正された時刻か、データパケットが生成された時刻、または 0 となるべきである。

    署名の形成のためにはリテラルデータパケットのフィールド(e)のみがメッセージダイジェスト機能に渡されることに注意してほしい。他のフィールドを排除することにより、メッセージの前に追加される固着署名と分離署名とが完全に一致することを保証できる。分離署名は、リテラルデータパケットのヘッダフィールドを含まない個々のファイルに基づいて算出される。

    6.2 署名パケット

    目的。ただ 1 つの実体(いわゆる "書き手")だけが署名を生成できる方法で署名はデータに固着される。書き手はまず "公開鍵" K を生成し、それを配布する。書き手は K に対応する特定の個人データを保有する。K を使用してデータを署名パケット(秘密鍵暗号としても知られる)に包むことで、書き手に協同する人だけがデータに署名することができる。誰でも眼鏡越しにエンベロープの中を見たり、その署名が K を使ってデータに固着されたことを確認したりできる。どのような方法ででもデータが変更された場合には、その確認は失敗する。

    署名は別の意味も持つ。例えば署名は、"私がこの文書を書いた" あるいは "私はこの文書を受け取った" ということを意味することもできる。署名パケットは、このような意味の種類を表す "分類" を含んでいる。

    定義。署名パケット(バージョン 2 または 3)は以下のフィールドを連結したものである。

    (a) パケット構造フィールド (2 バイト、3 バイト、5 バイトの何れか)
    (b) バージョン番号 = 2 または 3 (1 バイト)
    (c) MD 計算に含まれる後続データの長さ (1 バイト。値は常に 5)
    (d1) 署名分類 (1 バイト)
    (d2) 署名の時刻印 (4 バイト)
    (e) 署名に使用される鍵 ID (8 バイト)
    (f) 公開鍵暗合方式(PKC)タイプ (1 バイト)
    (g) メッセージダイジェストアルゴリズムタイプ (1 バイト)
    (h) チェックサムとして使用される MD 出力の最初の 2 バイト (2 バイト)
    (i) RSA 署名されたダイジェストを保持する暗号データのバイト文字列

    メッセージダイジェストはファイル全体のバイトと、その後に続くフィールド(d)のバイトとからの影響を受ける。元々は長さ(c)が変更できることを意図していたが、現在では常に定数値 5 を持ち、それが受け入れられる唯一の値であるように思われる。したがってフィールド(d1)(d2)のみが主メッセージと共に署名の中にハッシュされる。

    6.2.1 メッセージダイジェスト関連フィールド

    メッセージダイジェストアルゴリズムはフィールド(g)のメッセージダイジェスト(MD)番号によって指定される。現在のところ以下の MD 番号が定義されている。

    1 - MD5 (出力長 16)
    255 - 実験用

    将来さらに多くの MD 番号が定義されてもよい。実装が全ての MD 番号をサポートする必要はない。実装者は、その実装が理解できる MD 番号を明文化しなければならない。

    メッセージダイジェストアルゴリズムは任意長のバイト文字列を読み込み、上の表で示したような、なんらかの固定長バイト文字列を出力する。

    メッセージダイジェストアルゴリズムへの入力は "主要入力" と "追加入力" とを連結したものである。

    追加入力はフィールド(c)で指定され、後に続くフィールド(d1)(d2)などから取られるバイト数を示す。現状の実装では、この数値には(d1)(d2)のための値である 5 が使用される。追加入力に含まれないフィールドはフィールド(i)による "署名" をされない。

    主要入力は署名分類バイト(d1)によって決定される。バイト(d1)は以下の 16 進数値のひとつであり、それぞれ以下の意味を持つ。

    <00>
    文書署名。バイナリイメージ ("私がこの文書を書いた")
    <01>
    文書署名。標準的なテキスト ("私がこの文書を書いた")
    <10>
    公開鍵パケットおよびユーザー ID パケット。一般証明("この鍵はこのユーザーによって生成されたと私は思うが、それがどれほど確実かは分からない")
    <11>
    公開鍵パケットおよびユーザー ID パケット。人格証明("自分はこのユーザーである、と私に言った人によってこの鍵は生成された") (#)
    <12>
    公開鍵パケットおよびユーザー ID パケット。略式証明("略式証明によってこのユーザーであると私が信じた人によってこの鍵は生成された") (#)
    <13>
    公開鍵パケットおよびユーザー ID パケット。積極的証明("証明写真などの厳しい身元確認によってこのユーザーであると私が信じた人によってこの鍵は生成された") (#)
    <20>
    公開鍵パケット。鍵破棄 ("これは私の鍵であり、私はこれを廃止する")
    <30>
    公開鍵パケットおよびユーザー ID パケット。取り消し("この鍵がこのユーザーに対応するという以前の言明を私は全て撤回する") (*)
    <40>
    時刻印 ("私はこの文書を見た") (*)

    これ以外の意味を持つ署名を扱うために、将来さらに多くの分類番号が定義されてもよい。しかし、バージョン 2 またはバージョン 3 の署名パケットでは上記の番号のみが許される。PGP 2.6.2 ではアスタリスク(*)の付いたパケットは実装されず、ハッシュ(#)の付いたパケットは出力されないことに注意すべきである。

    署名パケットは二つの異なる文脈で使用される。ひとつ(署名タイプ <00> または <01>)は本文(リテラルパケットの内容、または分離ファイルどちらか)の中で使用され、タイプ <10> から <1F> は鍵ファイルの中で、署名する鍵とユーザー ID との後にのみ使用される。タイプ <20> は鍵ファイルの中で署名する鍵の後に使用され、タイプ <30> も鍵/ユーザー ID の組み合わせの後に使用される。タイプ <40> は署名文書の公証人による封印のために、署名の署名として使用されることを意図している。

    メッセージダイジェストアルゴリズムの出力はメッセージダイジェストまたはハッシュコードである。フィールド(i)には、署名者の秘密鍵でメッセージダイジェストを暗号化して生成された暗号文が含まれる。フィールド(h)には、暗号化されていないメッセージダイジェストの先頭 2 バイトが含まれる。この 2 バイトと解読したダイジェストの先頭 2 バイトとを比較することで、メッセージダイジェストの解読に正しい公開鍵が使用されたかどうかを受信者が確認できる。これらの 2 バイトはメッセージの 16 ビットフレームチェックシーケンスとしても役に立つ。

    6.2.2 公開鍵関連フィールド

    書き手の秘密鍵を使用して暗号化されることでメッセージダイジェストは署名される。フィールド(e)はそれに対応する公開鍵の ID である。

    フィールド(f)の公開鍵暗号システム(PKC)番号によって公開鍵暗号アルゴリズムが特定される。現在のところ以下の PKC 番号が定義されている。

    1 - RSA
    255 - 実験用

    将来さらに多くの PKC 番号が定義されてもよい。実装が全ての PKC 番号をサポートする必要はない。実装者は、その実装が理解できる PKC 番号を明文化しなければならない。

    PKC 番号は公開鍵暗号方法と署名方法との両方を識別する。PKC 番号の定義の一部としてこの 2 つの方法は完全に定義される。一部の暗号システムは、暗号のみ、または署名のみに利用できる。将来そのような PKC 番号が定義される場合、それらは適切に番号付けされるだろう。

    6.2.3 RSA 署名

    RSA 署名されたバイト文字列は、メッセージダイジェストを取得し、ASN 構造体を埋め、その後に署名者の RSA 鍵の中のバイト文字列全体を暗号化することで形成される複合精度フィールドである。

    PGP バージョン 2.3 以降は PKCS 形式の署名文字列中に MD を暗号化する。PKCS 形式は以下の通り。

            MSB               .   .   .                          LSB
            0   1   <FF>(nバイト)   0   ASN(18バイト)   MD(16バイト)
    

    ASN 文字列は以下の 18 バイトの 16 進数値である。ASN 文字列の意味については RFC1423 を参照してほしい。

            <30 20 30 0C 06 08 2A 86 48 86 F7 0D 02 05 05 00 04 10>
    

    このバイト文字列全体の長さが係数(modulus)の中のバイト数と同じになるように、このバイト文字列に必要なだけ <FF> のバイト詰めが加えられる。

    6.2.4 その他のフィールド

    時刻印フィールド(d2)は、署名枠の後の日付枠の書式と類似している。典型的には署名パケットが生成された瞬間に近い時刻を表すが、それが必須というわけではなく、手書きで署名する場合と同じようにユーザーが好きな時刻を署名に付けることもできる。

    信頼できる時刻印の生成をアプリケーションが署名に要求する場合、信頼できない時刻印を持つ分離署名は、その署名パケットに別の署名パケットで署名するために信頼できる時刻印公証サービスに提出され、署名の署名が生成される。公証による署名の時刻印は、元の署名の信頼できる "正当な(legal)" 時刻として使用することができる。

    6.3 圧縮データパケット

    目的。圧縮データパケットは、小さい容量の中に安全に内容を押し込んだエンベロープである。

    定義。圧縮データパケットは以下のフィールドを連結したものである。

    (a) パケット構造フィールド
    (b) 圧縮タイプを示す 1 バイト
    (c) 圧縮データのバイト文字列

    バイト文字列(c)は、バイト(b)で示されるアルゴリズムを用いて展開可能なパケットである。典型的には、圧縮されたデータはリテラルデータパケット、またはリテラルデータパケットに連結された署名パケットから構成される。

    圧縮タイプは圧縮データパケットで使用されている圧縮アルゴリズムを表す。現在のところ以下の圧縮番号が定義されている。

    1 - ZIP
    255 - 実験用

    将来さらに多くの圧縮番号が定義されてもよい。実装が全ての圧縮番号(訳注:原文は "every MD number" となっていますが、文脈からいって "every compression number" の間違いなので「圧縮番号」としました)をサポートする必要はない。実装者は、その実装が理解できる圧縮番号を明文化しなければならない。

    6.4 慣用鍵暗号化データパケット

    目的。ワンタイムセッション鍵を使って慣用鍵暗号アルゴリズムでデータブロックを暗号化することで慣用鍵暗号化データパケットは形成される。典型的には、暗号化されるブロックは圧縮データパケットである。

    定義。慣用鍵暗号化データパケットは以下のフィールドを連結したものである。

    (a) パケット構造フィールド
    (b) 暗号データのバイト文字列

    フィールド(b)を形成する暗号化された平文または圧縮された平文には、先頭に 64 ビットの乱数データと 16 ビットの "鍵確認(key check)" が追加される。この乱数は 64 ビットの乱数値を伴う暗号フィードバックチェイン処理(cipher feedback chaining process)の開始に役立つ。つまりこれは、暗号ブロックチェイン暗号法(cipher-block-chaining encryption scheme)のための初期化ベクター(IV)と同じ機能を提供するということである。鍵確認は乱数の最後の 16 ビットと等しい。解読中に、解読されたデータの第 7 バイト・第 8 バイトが第 9 バイト・第 10 バイトと一致するかどうかの比較が行われる。もし一致するなら、解読に使用された慣用セッション鍵は正しいものと見なされる。

    6.4.1 慣用暗号タイプバイト

    目的。慣用暗号タイプバイトは、使用されている慣用暗号アルゴリズムの種類の確認に使用される。さらにこのアルゴリズムタイプバイトは、使用されているアルゴリズムに基いて慣用暗号鍵の長さも定義する。

    定義。慣用暗号タイプバイトは 1 バイトであり、使用されているアルゴリズムを定義する。使用中のアルゴリズムが追加の定義を要求することも許されており、例えば追加の定義として鍵長を要求する場合、サポートされる鍵の長さを明文化することは実装者の責任である。

    1 - IDEA (16-byte key)
    255 - 実験用

    6.5 公開鍵暗号化パケット

    目的。公開鍵暗号化パケットはメッセージのセッション鍵部分のための形式である。このパケットの目的は、受信者へのメッセージを暗号化するためのワンタイムセッション鍵を安全な方法で運ぶことである。受信者だけがセッション鍵を復元できるように、受信者の公開鍵でセッション鍵を暗号化することでこれは実現される。

    定義。公開鍵暗号化パケット(バージョン 2 または 3)は以下のフィールドを連結したものである。

    (a) パケット構造フィールド
    (b) バージョン番号 2 または 3 を表す 1 バイト
    (c) 鍵の ID を示す数値 ID フィールド
    (d) PKC 番号を表す 1 バイト
    (e) 暗号化データ(DEK)のバイト文字列

    バイト文字列(e)はセッション鍵の値を表し、バイト(d)で識別される暗号システムに従って読み手の公開鍵 K を使って暗号化される。

    フィールド(c)の値は公開鍵 K の ID である。

    このパケットが確実に K を識別するわけではないことに注意してほしい。二つの鍵は偶然や悪意によって同じ ID を持つかもしれない。通常はそのパケットを生成するのに鍵 K が使われた文脈から明らかだろうが、明らかではない場合もありうる。そのような場合、フィールド(c)が役に立つ。例えば、複数の鍵を生成している読み手がメッセージを受けとった場合、フィールド(c)の値と一致する ID を持つ鍵だけを使用してメッセージの解読を試みるべきである。偶然にも同じ ID を持つ鍵を生成していた場合には両方の鍵でメッセージの解読を試みなければならないが、そのような状況が偶然に起こることはとてもありそうにない。

    6.5.1 RSA 暗号化データ暗号鍵(DEK)

    データ暗号鍵(DEK)は RSA 暗号化バイト文字列を持つ複合精度フィールドである。そのバイト文字列は、メッセージの暗号化に使用される秘密鍵を(公開鍵暗号化パケット毎に無作為にバイト詰めして)PKCS エンコードしたものである。

    PGP バージョン 2.3 以降は、以下のフォーマットを使用して DEK を MPI にエンコードする。

         MSB                       .   .   .                       LSB
          0   2   RND(nバイト)   0  ALG(1バイト)  DEK(kバイト)  CSUM(2バイト)
    

    ALG はデータパケットを暗号化するために使用される秘密鍵アルゴリズムを表すアルゴリズムバイトである。DEK は実際のデータ暗号鍵であり、そのサイズは ALG で定義される暗号アルゴリズムに依存する。タイプバイト 1 の IDEA 暗号アルゴリズムの場合、DEK の長さは 16 バイトである。CSUM は DEK の 16 ビットチェックサムであり、このパケットを解読するのに正しい秘密鍵が使用されたことを確認するために使用される。RND は暗号化するのに使用される RSA 秘密鍵のサイズを満たすようにバイト全体を拡張するための無作為なバイト詰めである。

    6.6 公開鍵パケット

    目的。公開鍵パケットは RSA 公開鍵を定義する。

    定義。公開鍵パケットは以下のフィールドを連結したものである。

    (a) パケット構造フィールド (2 バイトまたは 3 バイト)
    (b) バージョン番号 = 2 または 3 (1 バイト)
    (c) 鍵生成の時刻印 (4 バイト)
    (d) 日単位の有効期限 (0 は無期限を意味する) (2 バイト)
    (e) 公開鍵暗号システム(PKC)タイプ (1 バイト)
    (f) RSA 公開剰余 n の MPI
    (g) RSA 公開暗号指数 e の MPI

    有効期限には通常 0 が設定される。

    6.7 ユーザー ID パケット

    目的。ユーザー ID パケットはユーザーを識別し、公開鍵または秘密鍵に対応する。

    定義。ユーザー ID パケットは以下のフィールドを連結したものである。

    (a) パケット構造フィールド (2 バイト)
    (b) ユーザー ID 文字列

    ユーザー ID 文字列には印刷可能 ASCII 文字からなる任意の文字列が許される。しかしながらこのパケットの目的は個人を一意に識別することであるので、一般的な習慣としてはユーザー名の後に電子メールアドレス(アングルブラケットで囲う)を続ける。

    7. 転送可能公開鍵

    PGP ユーザー間で公開鍵が交換されてもよい。転送可能な公開鍵の主な要素は以下の通り。

    (a) 1 つの公開鍵パケット
    (b) 1 つ以上のユーザー ID パケット
    (c) ゼロ個以上の署名パケット

    先頭に公開鍵が置かれる。その後に続くユーザー ID パケットは、この公開鍵の所有者の身分証明を提供する。複数のユーザー ID パケットが存在するなら、それは同じユーザーを識別する複数の方法ということになる。例えばあるユーザーが 2 つ以上の電子メールアドレスを使用している場合、それぞれのアドレスに対してユーザー ID パケットが生成される。それぞれのユーザー ID パケットの直後にゼロ個以上の署名パケットが置かれる。各々の署名パケットは、直前のユーザー ID パケットと最初の公開鍵パケットとに基いて算出される。対応する公開鍵とユーザー ID とを証明するために、この署名が役に立つ。実質的に署名者は、この公開鍵がこのユーザー ID で識別されるユーザーのものであるという彼/彼女の意見を証明していることになる。

    8. 謝辞

    Philip Zimmermann は PGP1.0(PGP2.x の先駆である)の作者である。後のバージョンの PGP の主要部分は Philip Zimmermann による設計指針の下、多くの貢献者を含む国際的な共同努力によって実装されている。

    9. セキュリティ考察

    セキュリティ問題はこの文書全体を通して議論されている。

    10. 著者のアドレス

    Derek Atkins
    12 Rindge Ave. #1R
    Cambridge, MA

    Phone: +1 617 868-4469
    EMail: warlord@MIT.EDU


    William Stallings
    Comp-Comm Consulting
    P. O. Box 2405
    Brewster, MA 02631

    EMail: stallings@ACM.org


    Philip Zimmermann
    Boulder Software Engineering
    3021 Eleventh Street
    Boulder, Colorado 80304 USA

    Phone: +1-303-541-0140
    EMail: prz@acm.org