ネットワーク WG Request for Comments: 2440 分類: Standards Track |
J. Callas Network Associates L. Donnerhacke IN-Root-CA Individual Network e.V. H. Finney Network Associates R. Thayer EIS Corporation 1998年11月 |
本書は、 インターネットコミュニティに対してインターネットスタンダードトラックのプロトコルを定義するとともに、 それを改良するための議論や提言を求めるものである。 このプロトコルの標準化状態およびステータスについては、 「Internet Official Protocol Standards」(STD 1)の最新版を参照すること。 このメモの配布に制限はない。
Copyright (C) The Internet Society (1998). All Rights Reserved.
本書において、多くのタグが定義されているが、 (新機能のための)新しいタグを追加するメカニズムについては解説していない。 伝統的に、IANA(Internet Assigned Numbers Authority)が、将来、 拡張される新しい値の割りあてをコントロールしており、 IANAに使われるために、RFCは、通常、プロセスを定義している。 しかし、このプロトコル内で起きる可能性がある新機能間の微妙な(それほど微妙でない)相互作用と、 全体のセキュリティを著しく低くするような既存の機能が存在する。 それゆえ、本書は、拡張プロセスについては規定していない。 新しいタグの定義(例として新しい暗号アルゴリズム等)を要求する代わりに、 IESGセキュリティエリアディレクターや適切なIETFワークグループに検討してもらうよう転送する必要がある。
本書は、 OpenPGP形式に基づく相互運用可能なアプリケーションの開発のために必要な、 すべての情報を公開するために維持管理されている。 これは、アプリケーションを実装するための細かな手順書ではない。 ここでは、OpenPGP形式についての説明と、 ネットワーク上に流れる形式に準ずるパケットの読み・書き・生成・チェックの方法等についてのみ解説されている。 しかし、実装にあたって、 セキュリティ脆弱性等を避けるために必要な注意点等を解説する。
OpenPGPを実装するソフトウェアは、 強度の高い公開鍵と共通鍵暗号の両方を使って、 電子通信とデータの格納のセキュリティサービスを提供する。 これらのサービスには、守秘性(confidentiality)、 鍵管理(key management)、認証(authentication)、 デジタル署名(digital signatures)が含まれる。 本書では、OpenPGPにおいて使用するメッセージフォーマットの仕様を示す。
本書は、暗号化、復号、署名、鍵管理機能を提供するため、 OpenPGPで使用するメッセージ交換パケット形式の情報を提供する。 これは、RFC 1991 "PGP Message Exchange Formats"を参考に作成されている。
"PGP"、"Pretty Good"および"Pretty Good Privacy"は、 Network Associates, Inc.の登録商標であり、 Network Associates, Inc.より使用許可を得ている。
本書は、"MUST", "SHOULD", "MAY"の用語をRFC 2119に規定されているように使っている。
OpenPGPは、 下記の機能を用いてメッセージおよびデータのインテグリティ(data integrity)を提供する。
また、OpenPGPは、 鍵管理と証明(certificate)サービスも提供するが、それらの多くは、 本書の範囲ではない。
OpenPGPは、守秘性を提供するため、ふたつの暗号アルゴリズムを使用する。 共通鍵暗号と公開鍵暗号である。 公開鍵暗号アルゴリズムの場合、 守秘性の対象となるものを共通鍵暗号で暗号化する。 各共通鍵は、1度だけ使用される。 新しい「セッション鍵」は、乱数として各メッセージごとに生成される。 セッション鍵は、一度しか使用されないので、メッセージと共に送信される。 そのセッション鍵を守るため、それは受信者の公開鍵で暗号化されている。 順序は、下記のとおり。
共通鍵暗号の場合、(2通りあり、ひとつは)暗号化の対象は、 パスフレーズ(または、 他の共有シークレット)から生成される共通鍵で暗号化され、 (もう一方は)上記で説明した(公開鍵暗号アルゴリズムの場合)ような2段階方式を用いて、 セッション鍵の暗号化には共有シークレットを使用する。
デジタル署名、 守秘性機能(暗号化)の両方とも同じメッセージに適用される場合がある。 まず、はじめに、メッセージへの署名が生成され、付け加えられる。 そして、「メッセージ+署名」は、共通鍵であるセッション鍵で暗号化される。 最後に、セッション鍵は、公開鍵で暗号化されて、 暗号ブロックの前に置かれる。
デジタル署名は、ハッシュコードかメッセージダイジェスト方式を使用し、 公開鍵署名方式を使用する。 順序を以下に示す。
OpenPGPの実装は、暗号化の前、 署名の後にメッセージを圧縮してもよい(MAY)。
OpenPGPの暗号化メッセージ・署名証明書・キーの内在形式は、 任意のオクテットストリームである。 システムによっては、 プリンタブル(Printable)な7bitを含むブロックのみを許可する。 バイナリーデータを送信するとき、 セキュアでないチャネル上でOpenPGPの生のバイナリーオクテットを送信するためには、 それらバイナリーオクテットをプリンタブル形式にエンコードする必要がある。 OpenPGPは、8bitバイナリーオクテットストリームからプリンタブルASCIIキャラクターへの変換を提供する。 それをRadix-64エンコード、もしくはASCII Armorと呼ぶ。
実装は、Radix-64変換を提供する必要がある(SHOULD)。
多くのアプリケーション、特にメッセージアプリケーションは、 OpenPGP-MIME文書(RFC 2015)で解説されている機能をもつことが望ましい。 OpenPGPを実装しようとするメッセージアプリケーションは、 OpenPGP-MIMEを実装する必要がある(SHOULD)。
OpenPGPは、 暗号化と署名の両方を使用するアプリケーションを前提に設計されているが、 署名のみの実装によって解決される問題も、いくつか存在する。 この仕様においては暗号化と署名の両方が必須とされているが、 暗号の部分を省略した実装が存在することは意味のあることである。
この章では、OpenPGP で使用されるデータ要素について解説する。
スカラー数は、Unsigned(符号なし)で、常にbig-endian形式で保存される。 n[k]をk番目のオクテットとすると、2オクテットのスカラーの値は、 ((n[0]<<8)+n[1])となる。 また、4オクテットのスカラーの値は、 ((n[0]<<24)+(n[1]<<16)+(n[2]<<8)+n[3])となる。
MPI (Multi-Precision Integer)は、符号無し整数(unsigned integer)であり、 暗号の計算等に使用する大きな整数に適用される。
MPIは、ふたつの部分から成る。 整数(*訳注:原文ではMPIと表しているが、 厳密には整数を指す)の長さをビットで表した2オクテットのスカラーと、 その後に整数を表すオクテットの文字列が並ぶ。
これらのオクテットは、big-endian数を形成する。 big-endian数は、 適切な長さをbig-endian数で表したものを前に置くことによってMPIになることができる。
例:
(全ての数字は16進数表記)
オクテットの文字列[00 01 01]は、1という値でMPIを形成する。 文字列[00 09 01 FF]は、511という値でMPIを形成する。
追加規則:
MPIのサイズは、((MPI.length + 7) /8) + 2オクテットとなる。
MPIの長さは、最上位のゼロでないビットから数える。 MPIフォームとして[00 02 01]は、(MPIとして)正しくなく、 [00 01 01]とする必要がある。
鍵IDは、鍵の識別をする8オクテットのスカラーで形成される。 実装は、鍵IDが固有であることを仮定してはいけない(SHOULD NOT)。 後述する「拡充された鍵のフォーマット」の章では、 鍵IDがどのように形成されるかについて解説する。
テキストに使用するデフォルトのキャラクターセットは、 Unicode [ISO10646]をエンコードしたUTF-8 [RFC2279]である。
時刻フィールドは、 <1 January 1970 UTC>の深夜00:00から経過した時間を秒単位で表しており、 unsignedの4オクテット数で表される。
String-to-key(S2K)識別子は、 パスフレーズの文字列を暗号化/復号用共通鍵へ変換するのに使用される。 それらは、2箇所に使われている。 現在のところ、 秘密鍵リング内にある秘密鍵の秘密な部分を暗号化するときと、 パスフレーズを共通鍵暗号メッセージ用の共通鍵(*訳注:セッション鍵)へ変換するときに使用される。
現在のところ、S2K識別子には、下記の3種類がある。
Simple S2Kでは、文字列をハッシュして直接鍵データをつくり出す。 ハッシュの手順について以下に示す。
Octet 0: 0x00 Octet 1: hash algorithm (ハッシュアルゴリズム)
Simple S2Kは、パスフレーズをハッシュしてセッション鍵を生成する。 この方法は、 セッション鍵のサイズ(使用する暗号アルゴリズムに依存)とハッシュアルゴリズムの出力サイズに依存する。 ハッシュサイズがセッション鍵のサイズより大きい場合、 ハッシュの上位(左側からの)オクテットをセッション鍵として使用する。
ハッシュサイズがセッション鍵のサイズよりも小さい場合、 鍵データ作成に必要な量の複数のハッシュコンテクストが作成される。 これらは、0、1、2、...個のゼロのオクテットでプレロードされる(つまり、 1回目のインスタンスは、プレロードをもたず、2回目のインスタンスは、 1オクテットのゼロがプレロードされ、3回目のインスタンスは、 2オクテットのゼロがプレロードされ...となる)。
データがハッシュされるとき、データは、 各ハッシュコンテクストへ個々に与えられる。 コンテクストは、別々に初期化されるので、 それぞれが異なるハッシュ値を出力する。 いったん、パスフレーズがハッシュされた後、複数のハッシュ出力値は、 左から連結され、最も左のハッシュ値を先頭に必要量を鍵データとし、 右側の残った余分なオクテットは、破棄される。
Salted S2Kは、 辞書攻撃(Dictionary Attack)を防ぐためにS2K識別子の中に"Salt(塩)"値(ある任意のデータ)を加えたもので、 パスフレーズと共にハッシュされる。
Octet 0: 0x01 Octet 1: hash algorithm (ハッシュアルゴリズム) Octets 2-9: 8-octet salt value (8オクテットのSalt値)
Salted S2Kは、Simple S2Kとよく似ているが、 ハッシュ関数への入力値はS2K識別子からの8オクテット分のSaltが含まれる点が異なり、 パスフレーズが後ろに続く。
Iterated and Salted S2Kは、Saltとオクテットカウントの両方を含む。 Saltは、パスフレーズと組み合わせられ、 その結果値は繰り返しハッシュされる。 これによって、 攻撃者が辞書攻撃をするためにしなければならない作業が増える。
Octet 0: 0x03 Octet 1: hash algorithm (ハッシュアルゴリズム) Octets 2-9: 8-octet salt value (8 オクテットの Salt値) Octet 10: count, a one-octet, coded value (1オクテットにエンコードされたカウント値)
カウントは下記の公式を使用して1オクテットにエンコードされる。
#define EXPBIAS 6 count = ((Int32)16 + (c & 15)) << ((c %gt;> 4) + EXPBIAS);
上記の公式は、C言語の表記である。 "Int32"とは、32bit整数を示し、変数である。 "c"は、エンコードのカウント(オクテット10)を示している。
Iterated-Salted S2Kは、パスフレーズとSaltデータを複数回ハッシュする。 ハッシュされるオクテットの合計数は、 S2K識別子の中のエンコードされたカウントが示している。 カウント値は、いくつのオクテットがハッシュされるかの数であり、 繰り返しのカウントではない。
はじめに、ひとつ以上のハッシュコンテクストは、 鍵データに必要な量のオクテット数に応じて、 他のS2K方式と同様に初期化される。 そして、Saltとパスフレーズ(Saltの後ろに続く)は、 オクテットカウントに指定された数のオクテットがすべてハッシュされるまで繰り返しハッシュされる。 例外として、 オクテットカウントがSaltとパスフレーズをあわせたサイズより小さい場合、 (あわせたサイズがオクテットカウントより大きくても)そのあわせたもの全体がハッシュされる。 ハッシュ後、データはその他のS2K方式と同様に、 ハッシュコンテクストからアンロードされる。
実装は、Simple-S2K識別子が辞書攻撃に弱いことから、 Salted-S2K識別子もしくはIterated-and-Salted S2K識別子を使用する必要がある。
パスフレーズを秘密データ復号鍵へ変換する方式を示すためにS2K識別子を秘密鍵の中に置くことができる。 PGPの古いバージョンでは、 暗号アルゴリズムを示すオクテットは、秘密データの前におかれ、 それがゼロの場合、秘密データは暗号化していないことを表していた。 パスフレーズを鍵へ変換するときは常にMD5ハッシュ関数が利用されていた。
互換性のため、S2K識別子が使用されるとき、 古いデータ構造の中でハッシュアルゴリズムを示すオクテットであった位置に、 255という特別な値が入る。 その後に1オクテットの(暗号)方式識別子が続き、 上記で示したようにS2K識別子が続く。
それゆえ、秘密データの前につくものは、下記の内のひとつつである。
0: 秘密鍵は暗号化されていない(パスフレーズなし) 255: (暗号)方式オクテットとS2K識別子がつづく Cipher alg: MD5ハッシュを使用したシンプルS2K方式を使用
上記の3つめの選択肢、暗号アルゴリズムID (MD5とIDEAを暗黙に使用)は、 下位互換性確保のために用意されている。 OpenPGPの実装は、それを解釈してもよい(MAY)が、 生成されてはいけない(SHOULD NOT)ので推奨されていない。
秘密データが暗号化されている場合、
秘密データの復号のために上記の後ろに8オクテットのInitial
Vector(初期ベクタ)が続き、その後ろに秘密鍵の値が続く。
(*訳注: 原文では秘密鍵データが暗号化されていない場合のことを特に説明していない。
暗号化していない場合、S2K Usage (0, 255, CipAlg)は、0となり、
そのすぐ後ろに秘密鍵データが暗号化されていない状態で続く。
秘密鍵データ形式の詳細については 5.5.3節を参照)
OpenPGPは、Symmetric-key Encrypted Session Key (ESK)(共通鍵暗号セッション鍵)パケットを作成し、 それをメッセージの前に置くことができる。 これによって、S2K識別子は、パスフレーズの変換に使用され、 Symmetric-Key ESKかPublic-Key ESKを混合したメッセージを作成することも可能となる。 したがって、メッセージがパスフレーズで暗号化されていても、 公開鍵で暗号化されていても、復号できる。
PGP 2.Xは、共通鍵方式でメッセージを暗号化するとき、 必ずSimple String-to-Key変換とIDEAを使用する。 これは、推奨されていないが、 下位互換性のために使用してもよい(MAY)。
この章では、OpenPGPのパケットについて解説する。
OpenPGPメッセージは、複数のレコードから構成され、 それらはパケットと呼ばれる。 パケットは、データの固まりであり、 パケットタグ(Packet Tag)がパケットの意味を指す。 OpenPGPのメッセージ、鍵リング、証明書(Certificate)等は、 複数のパケットで構成される。 それらのパケットは、 さらにOpenPGPパケットを含んでいる場合がある(例えば、 圧縮データパケットを解凍したとき、 さらにその中にOpenPGPパケットが含まれている)。
各パケットは、パケットヘッダとそれに続くパケットボディから成り立つ。 パケットヘッダは、可変長である。
パケットヘッダの最初のオクテットは、 「パケットタグ(Packet Tag)」と呼ばれる。 パケットタグは、ヘッダの形式を定め、パケットの内容を示す。 残りの部分は、パケットの長さを表している。
最有位ビットは、左端のビット(ビット7と呼ぶ)である。 このビットのマスク値は、16進表記で0x80である。
+---------------+ PTag |7 6 5 4 3 2 1 0| +---------------+ Bit 7 -- Always one(常に1) Bit 6 -- New packet format if set (ここが1の場合は新しいフォーマットを意味する)
PGP 2.6.xは、古いパケットフォーマットのみを扱う。 それゆえ、PGPの古いバージョンとの相互運用が必要なソフトウェアは、 古いパケット形式のみを使用する必要がある。 相互運用がそれほど重要でない場合は、 どちらの形式を使用してもかまわない。 古いパケット形式のコンテントタグ(* 4.3節にて後述)は4bit、 新しいパケット形式のコンテントタグは、6bitであることに注意すること。 下位互換性を保つ場合、新しい機能によっては使えない。
古いパケット形式は、下記の構成となる。
Bits 5-2 -- コンテントタグ (content tag) Bits 1-0 -- パケット長の種類 (length-type)
新しいパケット形式は、下記の構成となる。
Bits 5-0 -- コンテントタグ (content tag)
古いパケットフォーマット中にあるパケット長の種類(length-type)の意味を以下に示す。
0 | - | パケット長は1オクテット。ヘッダーは2オクテットの長さとなる。 |
1 | - | パケット長は2オクテット。ヘッダーは3オクテットの長さとなる。 |
2 | - | パケット長は 4 オクテット。ヘッダーは 5 オクテットの長さとなる。 |
3 | - | パケット長は不定。 ヘッダーは1オクテットの長さで、 実装がパケットの長さを判断する必要がある。 仮にパケットがファイルの中にあるとすると、 パケットはファイルの終わりまで続いていることを意味する。 一般的にデータの終わりが文脈上明確である場合を除き、 パケットの長さが不定なものを使用するべきではなく(SHOULD NOT)、 一定の長さを使用するか、 新しいフォーマットのパケットヘッダを使用する方がよりよいとされる。 後述する新しいフォーマットのパケットヘッダでは、 不定長なデータを正確にエンコードするメカニズムを解説する。 |
新しいパケットフォーマットには、 パケットの長さのエンコード方法が4つある。
One-Octet Body Lengthヘッダは、 0から191オクテットまでの長さをエンコードする。 このタイプのレングスヘッダは、 1オクテットの値が192未満であることによって識別できる。 ボディ長は、下記のようになる。
bodyLen = 1st_octet;
Two-Octet Body Lengthヘッダは、 192から8383オクテットまでの長さをエンコードする。 このタイプのレングスヘッダは、 ひとつめのオクテットが192から223の範囲であることから識別できる。 ボディ長は、下記のようになる。
bodyLen = ((1st_octet - 192) << 8) + (2nd_octet) + 192
Five-Octet Body Lengthヘッダは、255の値をもつ1オクテットと、 それに続く4オクテットのスカラー数で構成される。 ボディ長は、下記のようになる。
bodyLen = (2nd_octet << 24) | (3rd_octet << 16) | (4th_octet << 8) | 5th_octet
Partial Body Lengthヘッダは、1オクテットの長さであり、 パケットボディの一部の長さのみをエンコードする。 この長さは、2の累乗で表され、1から1,073,741,824(2の30乗)までとなる。 このタイプのレングスヘッダは、 その中の1オクテットの値が224以上255未満であることから識別できる。 Partial Body Length は、下記のようになる。
partialBodyLen = 1 << (1st_octet & 0x1f);
各Partial Body Lengthヘッダの後ろにパケットボディの一部がつづく。 Partial Body Lengthヘッダは、 後ろに続くその部分のデータの長さを示している。 そして、その他のレングスヘッダ(One-Octet、Two-Octet、 Partialの3種類のいずれか)は、そのデータ部分の後ろに続く。 パケット中の最後のレングスヘッダは、 Partial Body Lengthヘッダにしてはならない(MUST NOT)。 Partial Body Lengthヘッダは、 それ以外の部分でのみ(パケットの最後の部分以外)使用可能である。 (*訳注:要するに、中間の部分は、Partialを使用してもよいが、 最後に来る部分は、 One-OctetかTwo-Octetにしないといけないということらしい。)
下記の例は、新しいパケット形式でのパケットの長さのエンコード方を示す。
長さが100のパケットで、その長さを1オクテットで表した場合、0x64になる。 その後に100オクテットのデータが続く。
長さが1723のパケットで、その長さを2オクテットで表した場合、 0xC5、0xFBになる。 その後ろに、1723 オクテットのデータが続く。
長さが100,000のパケットで、その長さを5オクテットで表した場合、 0xFF、0x00、0x01、0x86、0xA0になる。
この場合、次のようなオクテットストリームとしても表すことができる。:0xEF、 最初の32768オクテット、 0xE1、次の2オクテット、 0xE0、 次の1オクテット、 0xF0、次の65536オクテット、&kt; 0xC5、0xDD、 最後の1693オクテットデータ。 これは、可能な表記例のひとつにすぎず、 データの最後の部分が通常のボディレングスヘッダである限り、 Partial Body Lengthヘッダのサイズは、 多くのバリエーションが可能となる。 なお、最後のボディレングスヘッダは、 ゼロの長さを表すヘッダとなる場合がある。
実装は、 Partial Body Lengthヘッダをデータパケットに利用してもよい(MAY)。 literalデータや圧縮データ、暗号データの部分で可能である。 ひとつ目のPartial Lengthは、 最低512オクテットの長さでなければならない(MUST)。 Partial Body Lengthは、 他のパケットタイプに使用してはならない(MUST NOT)。
上記の説明のすべてにおいて、パケットの長さの合計は、 ヘッダの長さ+ボディの長さであることに注意。
0 | -- | 予約(パケットタグは、この値を使用してはならない。) |
1 | -- | 公開鍵暗号セッション鍵パケット |
2 | -- | 署名パケット |
3 | -- | 共通鍵暗号セッション鍵パケット |
4 | -- | One-Pass 署名パケット |
5 | -- | 秘密鍵パケット |
6 | -- | 公開鍵パケット |
7 | -- | 秘密サブキーパケット |
8 | -- | 圧縮データパケット |
9 | -- | 共通鍵で暗号化されたデータパケット |
10 | -- | マーカーパケット |
11 | -- | リテラルデータパケット |
12 | -- | トラストパケット |
13 | -- | ユーザ ID パケット |
14 | -- | 公開サブキーパケット |
60 to 63 | -- | 秘密 or 試験用の値 |
Public-Key Encrypted Session Keyパケット(公開鍵暗号セッション鍵)には、 メッセージの暗号化に使用したセッション鍵が入る。 ゼロ、もしくは複数のEncrypted Session Keyパケット(共通鍵/公開鍵のどちらか)は、 暗号メッセージが含まれるSymmetrically Encrypted Dataパケットの前に位置する。 メッセージは、セッション鍵で暗号化され、セッション鍵自体は、 暗号化されて ESK (Encrypted Session Key)パケットに保存される。 メッセージを暗号化した各OpenPGPキーのPublic-Key Encrypted Session Keyパケットは、 Symmetrically Encrypted Dataパケットの前に置かれる。 メッセージの受信者は、 受信者の公開鍵で暗号化されたセッション鍵を見つけて、 セッション鍵を復号し、そのセッション鍵でメッセージを復号する。
このパケットのボディは、下記の構成となる。
RSA 暗号化の特定フィールド:
Elgamal暗号化の特定フィールド:
上記の公式にある「m」という値は、 次のようにセッション鍵から引き出される。 まず、セッション鍵の後ろに続くSymmetric Encryption Dataパケットの暗号化方式を示す1オクテットの暗号識別子がセッション鍵の前にPrefixされる。 次に、セッション鍵の前にあるオクテットの合計(暗号識別子を除く、 65536を法とする)を2オクテットのチェックサムとして付加する。 このチェックサムは、PKCS-1ブロックタイプ02 [RFC2313] 形式で埋め込まれ(pad)、上記公式の「m」の値を形成する。
注意) 実装がひとつのセッション鍵について複数のPKESKを形成している場合、 複数の鍵で復号可能なメッセージを形成しており、実装は、 各鍵毎の新しいPKCS-1 Padding(埋め込み)を作成しなければならない(MUST)。
実装は、鍵IDがすべてゼロのものを「ワイルドカード」、 「推測的」鍵IDとして受領もしくは使用することができる。 この場合、受領側の実装は、 すべての秘密鍵を試してセッション鍵を復号できる鍵を探す。 この形式によって、メッセージのトラフィック分析量を軽減している。
Signatureパケット(署名パケット)は、公開鍵とデータの関係を表す。 最も一般的な署名は、ファイルやテキストブロックの署名と、 ユーザIDを証明する署名である。
Signatureパケットにはふたつのバージョンがある。 v3では基本的な署名情報を提供し、 v4ではサブパケットという拡張形式によって、 より多くの署名に関する情報を提供する。 PGP 2.6.xは、v3の署名のみ受け付けることができる。
実装は、v3署名を受け付けなければならない(MUST)。 実装は、v4署名を生成する必要がある(SHOULD)。 実装は、PGP 2.6.xが認識可能なv3署名を生成してもよい(MAY)。
注意) 実装がv3鍵で署名つき暗号メッセージを作成する場合、 v3署名を作成することが合理的である。
署名には多くの意味があり、 それらは署名の中のSignature-Typeオクテットで示される。 それら署名の意味を以下に示す。
v3 の Signature パケットには、下記の項目が含まれる。
この部分は、以下に示すとおり、アルゴリズム特定のものである。
署名されるデータは、ハッシュされ、 次にSignatureパケットの中のSignature TypeとCreation Timeがハッシュされる(追加の5オクテットの部分)。 ハッシュ値の結果は署名アルゴリズムで使用される。 ハッシュ値の上位16bit(最初の2オクテット)は、 Signatureパケットの中に含まれ、 不正な署名を拒否する簡易テストに利用される。
RSA署名方式の特定フィールド:
DSA署名方式の特定フィールド:
署名の計算は、上記で解説した署名データのハッシュに基づいて計算される。 計算の詳細は、DSA署名とRSA署名では異なる。
RSA署名では、ハッシュ値は、 PKCS-1の10.1.2節"Data encoding"の仕様に従ってエンコードされており、 それは、DigestInfoというタイプのASN.1値を作成し、 PKCS-1ブロックタイプ01を利用してpadされる。 [RFC 2313参照]。 これには、ASN.1ストラクチャに文字列としてハッシュ値を挿入する必要がある。 ストラクチャ内にあるオブジェクト識別子(object identifier)は使用するハッシュの種類を識別する。 現在、定義されているハッシュアルゴリズムを16進表記で以下に表す。
- MD2: 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x02 - MD5: 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05 - RIPEMD-160: 0x2B, 0x24, 0x03, 0x02, 0x01 - SHA-1: 0x2B, 0x0E, 0x03, 0x02, 0x1A
ANS.1 OIDは、下記のようになる。
- MD2: 1.2.840.113549.2.2 - MD5: 1.2.840.113549.2.5 - RIPEMD-160: 1.3.36.3.2.1 - SHA-1: 1.3.14.3.2.26
上記の完全なハッシュPrefixは、下記のようになる。
MD2: 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 MD5: 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 RIPEMD-160: 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 SHA-1: 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14
DSA署名は、DSAの元の値(generator value)から求められる群の位数(size of the group)「q」の大きさに合わせて、 160bitサイズのハッシュを使わなければならない(MUST)。 ハッシュ関数の結果は、160bit数として扱われ、 DSA署名アルゴリズム中で直接、使用される。
v4の署名パケットには、下記の項目が含まれる。
署名されるデータは、ハッシュされ、 次にSignatureパケットのバージョン番号からハッシュサブパケットデータ(含まれる)までがハッシュされる。 そのハッシュ値の結果が署名されたものである。 ハッシュ値の左の16bitは、不正な署名を拒絶する簡易テストをするため、 Signatureパケットの中に含まれる。
Signatureサブパケットが構成するふたつのフィールドがある。 ひとつは、Signatureパケットデータ(残りの部分)をハッシュした値であり、 もうひとつは、ハッシュしていない値である。 サブパケットのふたつめのフィールドは、 署名による暗号で守られていないため、 アドバイス的情報のみが含まれる必要がある。
ハッシュ関数から署名に変換する方式は、以降の節で解説する。
サブパケットフィールドは、 0個以上のSignatureサブパケットから構成される。 サブパケットの集合ごとに、 その集合の長さを表す2オクテットのスカラーカウントが前につく。
各サブパケットは、ヘッダとボディで構成される。 ヘッダ部の構成は、下記のようになる。
そして、サブパケット特定のデータがつづく。
長さにはSubpacket Typeオクテットも含まれるが、この長さではない。 長さの形式は、「新しい」パケット形式のレングスヘッダに似ているが、 Partial Body Lengthは使用できない。 Subpacket Lengthは、下記のようになる。
1番目のオクテットが192未満の場合、 lengthOfLength = 1 subpacketLen = 1st_octet 1番目のオクテットが192以上255未満の場合、 lengthOfLength = 2 subpacketLen = ((1st_octet - 192) << 8) + (2nd_octet) + 192 1番目のオクテットが255の場合、 lengthOfLength = 5 subpacket length = [2番目のオクテットからの4オクテットスカラー]
Subpacket Typeのオクテット値は、下記のいずれかになるであろう。
2 = signature creation time (署名作成日時) 3 = signature expiration time (署名有効期間) 4 = exportable certification (エクスポート可能証明) 5 = trust signature (信用度の署名) 6 = regular expression (正規表現) 7 = revocable (無効化可能) 9 = key expiration time (鍵有効期間) 10 = placeholder for backward compatibility (下位互換性のための記入子) 11 = preferred symmetric algorithms (共通鍵暗号アルゴリズム設定) 12 = revocation key (無効化権限のある鍵) 16 = issuer key ID (発行者の鍵ID) 20 = notation data (メモ日付) 21 = preferred hash algorithms (ハッシュアルゴリズムの設定) 22 = preferred compression algorithms (圧縮アルゴリズムの設定) 23 = key server preferences (鍵サーバの設定) 24 = preferred key server (優先鍵サーバ) 25 = primary user id (プライマリユーザID) 26 = policy URL (ポリシーURL) 27 = key flags (鍵フラグ) 28 = signer's user id (署名者のユーザID) 29 = reason for revocation (無効化の理由) 100 to 110 = internal or user-defined (内部もしくはユーザ定義に利用)
実装は、認識できないSubpacket Typeを無視する必要がある(SHOULD)。
Subpacket Typeのビット7は、「Critical(重要)ビット」である。 ビット7が1である場合、それは、 署名評価側(evaluator)にとって重要なサブパケットであることを示す。 Criticalビットが1のサブパケットを受け取った評価側ソフトウェアがそのSubpacket Type を知らない場合、 評価側(evaluator)は、 その署名をエラーと認識する必要がある(SHOULD)。
評価側は、Subpacket Typeを「認識」してもよいが、実装しなくてもよい。 Criticalビットの目的は、 評価側の未知な機能を無視するのではなくエラーとして警告を出し、 評価側に署名者が新しい機能を使用していることを伝えることにある。
実装には「選択設定(preferences)」を実装する必要がある(SHOULD)。
現在、多くのサブパケットが定義されており、 いくつかのサブパケットは署名に、いくつかは、鍵の属性に適用されている。 Self-Signature上に見られるサブパケットは、 鍵自身が発行するユーザID証明書の中に置かれる。 注意として、鍵は、ひとつ以上のユーザIDをもつことが可能であるので、 鍵にはひとつ以上のSelf-Signatureや多種サブパケットを有することが可能となる。
Self-Signatureとは、署名が参照する鍵によって作成されたBinding Signatureである。 Self-Signatureには、次の3種類がある。 :Certification Signature(0x10-0x13タイプ)、 Direct-key Signature(0x1fタイプ)、 Subkey Binding Signature(0x18タイプ)。 Certification Self-Signatureでは、各ユーザIDは、 Self-Signatureをもつ場合があり、したがって、 それぞれのSelf-Signatures内に異なるサブパケットを有する場合もある。 Subkey Binging Signatureでは、各SubkeyはSelf-Signatureをもっている。 Certification Self-Signatureにあるサブパケットは、ユーザ名に適用され、 Subkey Self-Signatureにあるサブパケットは、Subkeyに適用される。 Direct-Key Signature上のサブパケットは、鍵全体に適用される。
OpenPGP実装のソフトウェアは、 Self-Signatureの設定サブパケット(Preference subpackets)をなるべく狭義に解釈する必要がある。 例えば、鍵がふたつのユーザ名、AliceとBobをもっていると仮定する。 Aliceは、共通鍵暗号にCAST5を設定し、Bobは、 IDEAもしくはTriple-DESを設定する。 ソフトウェアがこの鍵をAliceの名前で位置づけた場合、 設定された暗号アルゴリズム(preferred algorithm)は、CAST5である。 同様に、ソフトウェアがこの鍵をBobの名前で位置づけた場合、 設定される暗号アルゴリズムは、IDEAとなる。 鍵が鍵IDで位置づけられた場合は、 鍵のデフォルトユーザIDが設定した暗号アルゴリズムがデフォルトの共通鍵暗号アルゴリズムとなる。
サブパケットは、署名データのハッシュサブパケット部分、 ハッシュしないサブパケット部分のどちらかに有する場合がある。 サブパケットがハッシュしていない場合、 (それは正式な署名の一部ではないことから)その中の情報は信頼がおけるものではない。
(4オクテットのタイムフィールド)
署名が作成された時間
ハッシュされたサブパケットになければならない(MUST)。
(8オクテットの鍵ID)
署名を発行している鍵のOpenPGPキーID
(4オクテットのタイムフィールド)
鍵の有効期間。 これは、鍵作成時間から鍵の期限が切れるまでを秒数で表している。 このフィールドが存在しないか、あるいは、ゼロの値の場合、 鍵が無期限であることを意味する。 これはSelf-Signatureにのみ存在する。
(1オクテット値のシークエンス)
鍵保持者が使用したい共通鍵暗号アルゴリズムIDを示す。 このサブパケット内容は、 優先する暗号アルゴリズムIDを先頭にオクテットで表したリストとなる。 リストされる暗号アルゴリズムのみが受信者のソフトウェアにサポートされていると仮定される。 暗号アルゴリズムIDについては9章を参照すること。 これは、Self-Signatureにのみ存在するサブパケットである。
(1オクテット値の配列)
鍵保持者が受領したいメッセージダイジェスト方式IDを示す。 共通鍵暗号アルゴリズムの設定のように優先するものを先頭にリストされる。 メッセージダイジェスト方式IDについては、 6章を参照。 これは、Self-Signatureにのみ存在するサブパケットである。
(1オクテット値の配列)
鍵保持者が使用したい圧縮アルゴリズムのIDを示す。 共通鍵暗号アルゴリズムの設定のように優先するものを先頭にリストされる。 圧縮アルゴリズムIDについては、6章を参照すること。 このサブパケットが含まれていない場合、ZIPが自動的に設定される。 ゼロのとき、圧縮しない設定である。 (なぜならば)鍵保持者のソフトウェアには圧縮ツールが実装されていない場合があるからである。 これは、Self-Signatureにのみ存在するサブパケットである。
(4オクテットのタイムフィールド)
署名の有効期間。 これは、署名作成時間から期限切れになるまでの時間を秒単位で表す。 これがない場合、もしくはゼロ値の場合、鍵は無期限である。
(1オクテットのエクスポート属性:0は無し、1はエクスポート可能)
このサブパケットは、 「Certification Signatureがエクスポート可能か(署名発行者よりも、 その他のユーザが使用する署名)どうか?」を示す。 パケットボディには「署名がエクスポート可能であるか否か?」を示すブールフラグ(boolean flag)が含まれる。 このパケットが存在しない場合、Certificationは、 Exportable(エクスポート可能)である。 すなわち、フラグが1であることと同じ意味を指す。
エクスポートしないもの、すなわち「Local」Certificationの場合、 Certificationは、 ユーザが使っているプログラム内のみで鍵が有効であることを示すときに作成される。 それゆえ、もうひとりのユーザに鍵を転送するために鍵のコピーを実装が準備するとき(鍵の"Export"プロセス)、 すべてのLocal Certification Signatureは、鍵から削除される。
転送した鍵の受領側は、その鍵を「インポート(import)」し、 同様にすべてのLocal Certificationを削除する。 通常の処理では、そこにはLocal Certification等はなく、 インポートはエクスポートされた鍵(exported key)であると仮定して処理している。 しかし、これが意味をなす場合がある。 例えば、 エクスポートされた鍵に追加してキーデータベースから同じ鍵のインポートをさせる実装の場合、 そのような状況が考えられる。
いくつかの実装(訳注:プログラム)は、 各ユーザについて関心を表さない。 (例: 鍵サーバ等)このような実装は、 それらが取り扱うすべての鍵から常にLocal Certificationを削る。
(1オクテットの無効化可能属性:0は無効化が不可能、1は可能)
署名の失効可能性(Revocability)についての状態。 パケットボディは、「署名が失効可能か否かか?」を示すブールフラグを含む。 Revocableが不可能な署名は、どのようなRevocable Signature も無視する。 それは、 署名者自身が自分の署名を彼の鍵が有効な限り失効できないことを宣言していることを表す。 このパケットが存在しない場合、署名は失効可能である。
(1オクテットの"レベル"(深さ)、1オクテットの信用度(trust amount))
署名者は、鍵が有効(valid)であるだけでなく、 指定レベルにおいて信用する価値(trust worthy)があることを主張している。
レベル0は、通常の有効(valid)な署名と同じ意味をもつ。 レベル1は、署名された鍵が有効なTrusted Introducer(信用する紹介者)であることを意味し、信用の度数は、 パケットボディの2番目のオクテットが示す。
レベル2は、レベル1のトラスト署名(Trust Signature)を発行することにおいて信用されている、すなわち、 「メタ紹介者(Meta Introducer)」を指す。
一般的に、レベルnのトラスト署名は、 鍵がレベルn-1のトラスト署名を発行することにおいて信用する署名である。
信用度(Trust Amuount)の幅は、0~255 であり、 120以上の場合、Complete Trust(完全な信用)を意味する。
実装は、60の値をPartial Trustとし、 120の値をComplete Trustとして発行する必要がある(SHOULD)。
(ヌルで終わる正規表現)
拡張していく信用の有効範囲を制限するため、 (レベル1以上の)Trust Signatureパケットの論理積で使用される。 このパケットの正規表現と一致するユーザIDをもつ鍵による署名のみがTrust Signatureサブパケットにより拡張された信用をもつ。 正規表現は、Henry Spencerの"almost public domain"正規表現パッケージと同じ構文を使用する。 構文の説明については、以降の節において解説する。
(1オクテットのクラス分け、1オクテットのアルゴリズムID (algid)、 20オクテットのフィンガープリント)
指定された鍵にある鍵の失効署名(Revocation Signature)発行権限を与える。 分類オクテットは、必ず0x80でなければならない。 ビットが0x40であるとき、「失効情報は、 取扱に注意を要すること」を意味する。 他のビットセットは、将来の他の権限への拡張に与えられている。 これは、Self-Signature中に見られる。
'sensitive'フラグが設定されている場合、鍵保持者は、 このサブパケットには現実社会の取扱に注意を要する関係を示すプライベートな信用情報が含まれていると考える。 このフラグが設定されているとき、 データが特に必要な場合を除いて(署名を指定の失効者(Revoker)に送信するか、 あるいは、失効者からのRevocation Signatureが伴っているとき等)、 実装は、他のユーザ宛に、 この署名をエクスポートしてはいけない(SHOULD NOT)。 他のエクスポートが必要なサブパケットとの混合を防ぐために、 このサブパケットを別の署名に隔離することが適切な場合もあることに注意。
(4オクテットのフラグ、2オクテットの名前の長さ(M)、 2オクテットの値の長さ(N)、 Mオクテットの名前データ、 Nオクテットの値のデータ)
このサブパケットは、 署名発行者が希望する署名上の「メモ(notation)」である。 メモには名前と値がありそれぞれは文字列のオクテットである。 署名の中には、ひとつ以上のメモを有することがある。 メモは、署名の発行者が注意するすべての拡張に使用可能である。 「フラグ」フィールドは、4オクテットのフラグを有する。
すべての定義していないフラグは、 必ずゼロにしなければならない(MUST)。 定義されたフラグを以下に示す。
1番目のオクテット:0x80 = 人間が解読可能。このメモは、ひとりひとりへのテキストのメモであり、ソフトウェアには関係ない。 その他のオクテット:なし
(Nオクテットのフラグ)
これは、フラグのリストであり、 鍵サーバ上での鍵の取り扱いについての鍵保持者の設定を示す。 すべての定義しないフラグは、ゼロでなければならない(MUST)。
最初のオクテット:0x80 = 修正しない(no-modify) 鍵保持者(key holder)は、この鍵が鍵保持者もしくは鍵サーバの管理 者のみ修正・アップデート可能であることを要求している。
これは、自己署名(Self-Signature)にのみ、在る。
これは、鍵保持者がアップデート用に設定する鍵サーバのURLである。 複数のユーザIDをもつ鍵は、 各ユーザIDごとに鍵サーバの設定ができることに注意すること。 また、これがURLであるので、鍵サーバは、ftp、http、 finger等から検索される鍵のコピーでありえることに注意すること。
(1オクテット、ブーリアン)
これは、ユーザIDのSelf-Signatureの中のフラグで、このユーザIDは、 鍵に対してメインのユーザIDであるか否かを示す。 Primary UserIDと関連づけることによって、 設定の曖昧性を解決するような実装には合理的である。 このフラグをもたない場合、その値は、ゼロを意味する。 複数のユーザIDがPrimaryであるとマークされている場合、実装は、 何らかの方法によって、その曖昧性を解決してもよい。
(文字列)
このサブパケットは、署名が発行されたポリシーを解説する文書のURLを含む。
(文字列のオクテット)
このサブパケットは、鍵の情報をもつバイナリーフラグのリストを含む。 これは、 文字列のオクテットで実装は固定的なサイズを仮定してはならない(MUST NOT)。 これによって、将来的にサイズが大きくなっても適用できるようにしている。 実装の予測よりリストが短い場合、状態を示さないフラグ(unstated flags)は、ゼロと認識される。 定義済みのフラグは、下記のようになる。
1番目のオクテット:
0x01 | - | この鍵は、その他の鍵の証明に使用している場合がある。 |
0x02 | - | この鍵は、データへの署名に使用している場合がある。 |
0x04 | - | この鍵は、通信の暗号化に使用している場合がある。 |
0x08 | - | この鍵は、ストレージの暗号化に使用している場合がある。 |
0x10 | - | この鍵の秘密要素は、secret-sharing(秘密共有)メカニズムによって、分離されている可能性がある。 |
0x80 | - | この鍵の秘密要素は、ひとり以上が所有している場合がある。 |
用法についての注意:
このパケットのフラグは、Self-SignatureもしくはCertifiction Signatureの中に現れる場合がある。 それらは、 「誰がそのステートメントを作成したか?」によって意味が異なる。 (例えば、「データへの署名」フラグを含むCertification Signatureは、証明がデータ署名のためにあると述べている。) また、一方、Self-Signatureの中の「通信の暗号化」フラグは、 与えられた鍵を通信に使用する設定を表している。 しかし、何が「通信(Communication)」を指し、 何が「記憶(Storage)」を指すかの定義は難しい問題である。 そこで、この定義をすべて実装に委ねることとする。 本書の著者は、この争点について特別な意見を特に要求せず、また、 認められた意見は、今後、変化する可能性がある点を認識する。
「Split Key」(0x10)フラグと「Group Key」(0x80)フラグは、 Self-Signatureのみに存在する。 これらのフラグは、Certification Signatureには意味がない。 これらは、Direct-Key Signature (0x1fタイプ)やSubkey Signature (0x18タイプ)、 フラグが適用する鍵に関連のあるものにのみ使用する必要がある(SHOULD)。
このサブパケットによって、鍵保持者は、「署名(行為)の責任をもつのは、 どのユーザIDか?」を表すことができる。 多くの鍵保持者は、ひとつの鍵を複数の用途、例えば、 個人での通信時と同様に仕事上でも使用したりする。 このサブパケットは、そのような鍵保持者に、 どの用途で署名を作成したのかを表すことを可能にする。
(1オクテットの失効(Revocation)コード、Nオクテットの理由の文字列)
このサブパケットは、Key Revocation Signature(鍵の失効署名)とCertification Revocation Signature(証明を失効する署名)の中でのみ使用される。 これは、鍵や証明書が 失効された理由を説明する。
1番目のオクテットは、失効の理由を表した機械可読コードを含む。
0x00 - 理由なし(Key RevocationかCertification Revocations)
0x01 - 鍵は更新された(Key Revocations)
0x02 - 鍵素材の障害(Key Revocations)
0x03 - もう使用されない鍵(Key Revocations)
0x20 - ユーザID情報はもう有効ではない(Certification Revocations)
Revocation Code(失効コード)の後に文字列のオクテットが続き、文字列は、 可読形式(UTF-8)で失効の理由を表す。 その文字列は、ヌルの場合もあり、すなわち長さがゼロである。 サブパケットの長さは、理由の文字列の長さプラス1となる。
共通鍵で暗号化されたESK (Symmetric-Key Encrypted Session Key:暗号化セッション鍵)パケットは、 メッセージの暗号化に使用したセッション鍵を共通鍵暗号で暗号化したものを格納する。 0個以上のESKパケット、かつ/または、Symmetric-Key Encrypted Session Keyパケットは、暗号メッセージを含むSymmetrically Encrypted Data(共通鍵暗号データ)パケットの前に位置する可能性がある。 メッセージは、セッション鍵で暗号化され、セッション鍵は、 暗号化されてEncrypted Session KeyパケットもしくはSymmetric-Key Encrypted Session Keyパケットに格納される。
Symmetrically Encrypted Dataパケットにひとつ以上のSymmetric-Key Encrypted Session Keyパケットが前に位置した場合、各パケットは、 メッセージ復号に使用する可能性があるパスフレーズを指定する。 これによって、メッセージは、複数の公開鍵で暗号化でき、 また複数のパスフレーズで暗号化することも可能となる。 このパケットタイプは、新しく、PGP 2.xやPGP 5.0では生成しない。
このパケットボディは、下記のように構成される。
Encrypted Session Keyが存在しない場合(これはパケットレングスとS2K識別子のサイズに基づいて判断可能)、 パスフレーズに適用したS2K方式はSymmetric-Key Encrypted Session Keyパケットの共通鍵暗号アルゴリズムを使用して、 ファイル復号のためにセッション鍵を作成する。
ESKが存在する場合、パスフレーズに適用したS2K方式の結果は、 IV (Initial Vector)がすべてゼロのCFBモードを利用して、 encrypted session keyフィールドの復号に使用される。 復号結果には、1オクテットの暗号識別子(後ろに続くSymmetrically Encrypted Dataパケットに使用した共通鍵暗号アルゴリズムを示す)が含まれ、 セッション鍵オクテット自身が後ろに続く。
(注意) すべてゼロのIVがこの復号に使用されるため、 S2K識別子は、Salt値(Salted S2KかIterated-Salted S2Kのいずれか)を必ず使わなければならない(MUST)。 Salt値は、 パスフレーズが再利用されても復号鍵は繰り返されないことを保証する。
One-Pass Signatureパケットは、署名データの前に位置し、 受信者が署名を確認するためのハッシュ計算を早めに開始するために十分な情報が含まれる。 これによって、署名パケットはメッセージの後に置かれていてもメッセージ全体への署名を一度(OnePass)で計算できる。 (*訳注:通常、署名は、メッセージの後のみにある)
このパケットボディの構成は、下記のようになっている。
メッセージがひとつ以上のOne-Pass Signatureで構成される場合、 Signatureパケットは、メッセージを括弧に入れる点に注意。 つまり、メッセージの後に来る最初のSignatureパケットは最後のOne-Passパケットと対応づけられ、 最後のSignatureパケットは、 最初のOne-Passパケットと対応づけられている。 (*訳注:要するに入れ子構造(ネスト)である)
Key Materialパケットは、公開鍵と秘密鍵のすべての情報を含む。 このパケット種別には4つの変型(variants)とふたつの主要版(major version)がある。 したがって、この節は、複雑である。
Public Keyパケットは、OpenPGPの鍵(しばしばOpenPGP Certificationと呼ばれる)を形成する連続したパケットの最初に位置する。
Public Subkeyパケット(公開サブキーパケット)(タグ14)は、 Public Keyパケットとまったく同じ形式でサブキーを表している。 ひとつ以上のサブキーは、トップレベルキーと関連がある場合もある。 規則として、トップレベルキーは、署名サービスを提供し、サブキーは、 暗号化サービスを提供する。
(注意) PGP 2.6.xでは、タグ14は、コメントパケットにする予定であった。 以前のPGPは、コメントパケットを発行せず無視したため、このタグは、 再利用されることとなった。 Public Subkeyパケットは、PGP 2.6.xでは認識しないがエラーも出さず、 限られた下位互換性を保つ。
Secret Keyパケットは、Public Keyパケットにあるすべての情報を含む。 その公開鍵素材のみならず、 Public Keyフィールドの後ろに秘密鍵素材等の情報も含まれる。
Secret Subkeyパケット(タグ7)は、 Secret Keyパケットと類似するサブキーであり、まったく同じ形式をもつ。
鍵素材パケットにはふたつのバージョンがある。 v3は、最初にPGP 2.6にて生成されたものである。 v2は、v3のパケットと似た形式であるが、 PGP 2.5以前のバージョンにて生成される。 V2パケットは推奨されず、生成されてはならない(MUST NOT)。 PGP 5.0では、新しいフィールドとセマンティックと共にv4を提供した。 PGP 2.6.xは、 v3より新しい鍵素材パケット(*訳注:v4以上を指す)を認識できない。
OpenPGPの実装は、v4の鍵を作成する必要がある(SHOULD)。 実装は、古いソフトウェアとの相互運用を確実にする目的でv3の鍵を生成してもよい(MAY)。 しかし、注意として、v4鍵は、 v3鍵の中のいくつかのセキュリティ欠陥を訂正している点がある。 これらの点については後述する。 実装は、RSA以外の公開鍵方式でv3鍵を生成してはならない(MUST NOT)。
v3のPublic KeyパケットとPublic Subkeyパケットは、下記のように構成される。
v3鍵には、 下記の3つの弱点があるため下位互換性にのみ使われる必要がある(SHOULD)。
第1に、鍵IDが単に公開モジュールの下位64 bitであるため、 ほかの鍵IDと同じ鍵IDをもつv3の鍵を作ることは比較的簡単である。
第2に、v3の鍵のフィンガープリントは鍵材料をハッシュするが、 その長さをハッシュしていないためにフィンガープリント衝突の機会を増やしている。
第3に、MD5ハッシュ方式にマイナーな欠点があるため、 開発者が他の方式を好んでいる点がある。
鍵IDとフィンガープリントのより完全な議論については、後述する。
v4の形式は、有効期間がない点以外はv3と似ている。 有効期間のサブパケットは、Signatureパケットに移動された。 また、v4の鍵は、 "Enhanced Key Format"の節において後述されるように、 v3の鍵と異なる計算をする。
v4のパケットには下記の項目が含まれる。
Secret KeyとSecret Subkeyパケットには、 Public KeyとPublic Subkeyパケットのすべてのデータが含まれ、 (その後ろに)アルゴリズム特定の秘密鍵データが暗号化された形で追加される。
このパケットには下記の項目が含まれる。
秘密のMPI値は、パスフレーズによって暗号化することができる。 S2K識別子が与えられたとき、パスフレーズの鍵への変換方式を示し、 無い場合、パスフレーズはシンプルMD5ハッシュを採用している。 実装は、S2K識別子を使用する必要がある(SHOULD)。 (なぜならば)シンプルハッシュは、下位互換性のために存在するからである。 MPIの暗号化方式は、Secret Keyパケット中に指定される。
秘密データの暗号化/復号は、 パスフレーズから作成された鍵とパケットからの初期ベクタ(Initial Vector)を使ってCFBモードで行われる。 v3鍵(RSAのみ)では異なるモードが使用される。 v3の鍵では、MPIのビットカウントPrefix(つまり最初の2オクテット)は、 暗号化されない。 MPIのNon-Prefixデータのみが暗号化される。 さらに、CFBブロックの境界(CFB block boundary)は、 MPIデータの開始にあわせられるため、 CFB状態は新しいMPI値ごとに再同期される。
v4の鍵では、より単純な方法が利用される。 すべての秘密のMPI値は、 MPIビットカウントPrefixを含むCFBモードで暗号化される。
アルゴリズム特定部分の後にある16bitのチェックサムは、 MPIのPrefixとデータを含めたアルゴリズム特定オクテットのプレーンテキストの代数合計である(法65536で還元(mod)したもの)。 v3鍵ではチェックサムは暗号化されずに格納される。 v4鍵では、 チェックサムはアルゴリズム特定データのように暗号化されて格納される。 このチェックサムの値は、パスフレーズの正当性確認に使用される。
Compressed Dataパケット(圧縮データパケット)には、 圧縮データが格納される。 一般的に、このパケットは、 暗号化パケットや後ろに続くSignatureやOne-Pass Signatureパケットの中で見受けられ、Literal Dataパケットを含む。
このパケットには、下記の項目が含まれる。:
Compressed Dataパケットのボディは、 いくつかのパケットセットを圧縮したブロックを含む。 メッセージ形成の詳細については、 「パケットの構成」の章を参照。
ZIP-compressedパケット(ZIP圧縮パケット)は、 RFC 1951 DEFLATE形式のブロックで圧縮される。 PGP V2.6は、13bitの圧縮を使用する点に注意すること。 実装でより多くのビットの圧縮を使用する場合、PGP v2.6は、 それを解凍できない。
ZLIB-Compressedパケット(ZLIB圧縮パケット)は、 RFC 1950 ZLIB形式のブロックで圧縮される。
Symmetrically Encrypted Dataパケット(共通鍵暗号データパケット)には、 共通鍵暗号アルゴリズムで暗号化されたデータが格納される。 復号したとき、通常、中にはパケット(しばしばLiteral DataパケットかCompressed Dataパケット)が含まれる。
このパケットボディには下記の項目が含まれる。:
使用される共通鍵暗号アルゴリズムは、 Symmetric-Key Encrypted Dataパケットの前に位置するPublic-KeyかSymmetric-Key Encrypted Session Keyパケットの中で指定される場合がある。 その場合、暗号アルゴリズムオクテットは、 セッション鍵が暗号化される前にセッション鍵にPrefixされる。 このようなパケットがEncrypted Dataパケットの前にない場合は、 パスフレーズのMD5ハッシュをセッション鍵をIDEA共通鍵暗号アルゴリズムを使用する。
データは、 暗号ブロックサイズをCFBシフトサイズとしたCFBモードで暗号化される。 初期ベクタ(IV)は、すべて0とする。 初期ベクタの代わりに、OpenPGPは、 データを暗号化する前に10オクテットの文字列をPrefixする。 最初の8オクテットは、ランダムで、9番目と10番目のオクテットは、 7番目と8番目のオクテットのコピーとなる。 最初の10オクテットを暗号化した後、 暗号ブロックサイズが8オクテット以下ならばCFBステートは再同期(resynchronaiz)される。 暗号テキストの最後の8オクテットの暗号が終わった後、 ブロックの境界は、リセットされる。
ランダムデータ80bit中の16bitの繰り返しビットはメッセージの前に位置し、 それによって、受信者は、セッション鍵の正当性をすぐに確認できる。
PGPの実験バージョンは、 このパケットをLiteralパケットとして使用していたが、 PGPのリリースバージョンは、このタグでLiteralパケットを生成しなかった。 PGP 5.xでは、このパケットは再設定され、 Markerパケットとして確保されている。
このパケットボディには、下記の項目が含まれる。:
このようなパケットは、受信時には無視されなければならない(MUST)。 Markerパケットは、メッセージの前に置かれる場合もあり、 そのメッセージは、PGP 2.6.xにない機能を使用しており、 そのバージョンでメッセージを処理するためには新しいソフトウェアが必要であることを報告する。
Literal Dataパケットには、メッセージボディが入る。 データは、それ以上解釈されない。
パケットボディには、下記の項目が含まれる。:
フィールド値が「b」(0x62)である場合、Literalパケットは、 バイナリーデータを含む。 フィールド値が「t」(0x74)である場合、Literalパケットは、 テキストデータであり、したがってラインの終わりをローカルの形式か、 その他のテキストモードへ変換することが必要になることもある。 また、RFC 1991では、 マシンローカル変換(machine-local conversions)のために「l」を「local」モードと定義している。 この使用法は、今では推奨されていない。
特別な名前である「CONSOLE」がここで使われている場合、メッセージは、 「親展(for your eyes only)」として考えられる。 このアドバイスによって、メッセージは、非常に機密であると考えられ、 受領側の実装は、例えば、データをディスクに保存することを避ける等、 そのメッセージをより注意深く扱うようにする必要がある。
テキストデータは、 <CR><LF>のテキストエンディング(例:通常のネットワーク用行終端子)を使って保存される。 これらは受信側のソフトウェアによって本来の行終端子に変換される必要がある。
トラストパケットは、鍵リングの中でのみ使用され、 通常はエクスポートされない。 トラストパケットは、実装ソフトが扱うその他の信用情報と共に、 どの鍵保持者が信用できる紹介者であるかのユーザ指定データを含む。
トラストパケットは、 他のユーザに送信される出力ストリームに発行されてはいけない(SHOULD NOT)。 ローカル鍵ファイル以外からの入力は、 無視される必要がある(SHOULD)。
UserIDパケットは、鍵保持者の名前やeメールアドレスから成る。 規則によって、 RFC 822形式のメールアドレスを含んでいるが内容に関する制約はない。 ヘッダ中のレングスパケットは、ユーザIDの長さを示す。 それがテキストの場合、UTF-8でエンコードされている。
「はじめに」で定義されたとおり、 OpenPGPのオブジェクトの基本表現は、任意のオクテットストリームであり、 いくつかのシステムではキャラクターセット変換、 データ変換その他に起因する障害に対して免疫性が要求される。
原則として、 安全でないチャネルでの要求事項を満足させるプリンタブル(Printable)エンコードスキームであれば、 OpenPGPの基本データ構造であるバイナリビットストリームを変更しないことから、 十分であると考えられる。 OpenPGPの規格は、確実な相互運用のために、 あるプリンタブルエンコードスキームを指定している。
OpenPGPのRadix-64エンコーディングは、ふたつの部分、 バイナリデータのbase64エンコードとチェックサムから成る。 base64エンコーディングは、MIME base64 content-transfer-encoding 「RFC 2045の6.8節(*訳注:原文[RFC 2231 Section 6.8] を訂正)」と同一である。 OpenPGPの実装には、 バイナリデータを守るためにASCII Armor を使用してもよい(MAY)。
チェックサムは、 24bitのCRCをMIME base64変換と同じ方法で4つのradix-64キャラクタに変換したもので、 等号(=)が前につく。 CRCは、0x864CFB生成と0xB704CEという初期値を使って計算される。 データの累積は、radix-64に変換されたデータ上ではなく、 変換される前のデータ上で行われる。 このアルゴリズムの実装サンプルについては、次節を参照。
チェックサムとその前の等号(=)は、 Base64 エンコードデータの後の最初の行に表れる可能性がある(MAY)。
(CRC-24の根本的理由)24bitというサイズは、 すべてのプリンタブルbase64に適合する。 ゼロ以外の値で初期化をすると、 ゼロ値の初期化より多くのエラーを検出する。
#define CRC24_INIT 0xb704ceL #define CRC24_POLY 0x1864cfbL typedef long crc24; crc24 crc_octets(unsigned char *octets, size_t len) { crc24 crc = CRC24_INIT; int i; while (len--) { crc ^= (*octets++) << 16; for (i = 0; i < 8; i++) { crc <<= 1; if (crc & 0x1000000) crc ^= CRC24_POLY; } } return crc & 0xffffffL; }
OpenPGPがデータをASCII Armorに変換するとき、 後でデータを再構築できるようにデータの前後に特別なヘッダを付加する。 OpenPGPは、ヘッダを使用することによって、 どのような種類のデータがASCII Armorに変換されたのかをユーザに表している。
下記のデータを連結することによってASCII Armorを作成する。
Armorヘッダ行は、 ヘッダラインテキストの両側に5つのダッシュ('-',0x2D)がつくヘッダラインテキストによって構成される。 ヘッダラインテキストは、 Armorにエンコードされたデータタイプとエンコード方法によって選ばれる。 ヘッダラインテキストには下記の文字列が含まれる。
Armorヘッダは、ペアの文字列で、 ユーザやOpenPGP受信用の実装にメッセージのデコード方法や使用法についての情報を与える。 Armorヘッダは、Armorの一部であり、メッセージの一部ではない。 したがって、メッセージに適用される署名から守られてはいない。
Armorヘッダの形式は、キーとバリューが対になった形式で表される。 コロン(':' 0x38)とスペース(0x20)が鍵と値を分けている。 OpenPGPは、適切に形成されてないArmorヘッダをASCII Armorの破損として認識する必要がある。 未知の鍵については、ユーザへ報告するべきであるが、 OpenPGPは、メッセージを処理し続ける必要がある。
現在定義されているArmorヘッダのキーは、下記のとおりである。:
MessageIDは、Multi-Part メッセージでない限り、 在ってはいけない(SHOULD NOT)。 すべてのメッセージで表された場合、純粋なランダム値を含むのではなく、 処理済み(暗号、署名等)メッセージから断定的(deterministic fashion)に計算しなければならない(MUST)。 これによって、MessageIDが変換されて暗号に関する鍵情報の漏洩の手段とならないことを適切な受信者は確定できる。
Armorテイル行(Armor Tail Line)は、 文字列「BEGIN」が「END」に変わることを除いてArmorヘッダ行(Armor Heder Line)と同じ方式で構成される。
エンコーディングプロセスは、 24bitの入力ビットグループを4つのエンコードキャラクタ文字列出力として表している。 (この処理は、まず)左から右へ進み、 3つの8 bit入力グループを連結することによって、 24bit入力グループを形成する。 これらの24bitは、4つの連結した6bitグループとして取り扱われ、 各6bitグループは、Radix-64アルファベットの1桁に変換される。 Radix-64でビットストリームをエンコードするとき、 ビットストリームは最有力ビット(most-significant-bit)が最初にくる配列であることが必ず仮定されている。 すなわち、ストリームの最初のビットは、最初の8bitの上位ビットであり、 8番目のビットは、最初の8bitの下位ビットであり...となる。
+--first octet--+-second octet--+--third octet--+ |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| +-----------+---+-------+-------+---+-----------+ |5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0| +--1.index--+--2.index--+--3.index--+--4.index--+
各6bitグループは、 下表にある64個のプリンタブルキャラクタ配列のインデックスとして使用される。 インデックスに関連づけられるキャラクターは、文字列として出力される。
Value Encoding Value Encoding Value Encoding Value Encoding 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 2 C 19 T 36 k 53 1 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t 62 + 12 M 29 d 46 u 63 / 13 N 30 e 47 v 14 O 31 f 48 w (pad) = 15 P 32 g 49 x 16 Q 33 h 50 y
エンコードされた出力ストリームは、 各行76文字以下で表さなければならない。
エンコードするデータの終わりが24bit以下であった場合、 特別な処理を実行する。 その処理には3種類ある。
base64アルファベット以外のすべてのキャラクタは、 Radix-64データの中では無視される。 デコードするソフトウェアは、 すべての改行その他上記の表に無いキャラクタを無視しなければならない。
Radix-64データの中では、おそらく、上記の表に無いキャラクタ、改行、 その他スペース等は、トランスミッションエラーとして表され、 それには警告メッセージやある環境下ではメッセージの拒絶等が適切な場合もある。
データの最後にパディングするときにのみ使われるので、 どのような「=」キャラクタもデータの終端であると認識してもよい。 (伝送中の切り捨てが無いと仮定。) そのような保証はできないが、 伝送されるオクテット数が3の倍数であるとき、 「=」キャラクターは、存在しない。
Input data: 0x14fb9c03d97e Hex: 1 4 f b 9 c | 0 3 d 9 7 e 8-bit: 00010100 11111011 10011100 | 00000011 11011001 11111110 6-bit: 000101 001111 101110 011100 | 000000 111101 100111 111110 Decimal: 5 15 46 28 0 61 37 62 Output: F P u c A 9 l + Input data: 0x14fb9c03d9 Hex: 1 4 f b 9 c | 0 3 d 9 8-bit: 00010100 11111011 10011100 | 00000011 11011001 pad with 00 6-bit: 000101 001111 101110 011100 | 000000 111101 100100 Decimal: 5 15 46 28 0 61 36 pad with = Output: F P u c A 9 k = Input data: 0x14fb9c03 Hex: 1 4 f b 9 c | 0 3 8-bit: 00010100 11111011 10011100 | 00000011 pad with 0000 6-bit: 000101 001111 101110 011100 | 000000 110000 Decimal: 5 15 46 28 0 48 pad with = = Output: F P u c A w = =
-----BEGIN PGP MESSAGE----- Version: OpenPrivacy 0.99 yDgBO22WxBHv7O8X7O/jygAEzol56iUKiXmV+XmpCtmpqQUKiQrFqclFqUDBovzS vBSFjNSiVHsuAA== =njUN -----END PGP MESSAGE-----
この例は、ふたつのスペースでインデントされていることに注意。
特別なソフトウェアを使用せず署名テキストが読みとれるので、 ストリームをASCII Armorせずに、 原文のオクテットストリームへ署名することが望ましい。 そのようなクリアテキストへ署名をバインドするために、 このフレームワークが使用される。 (注意:RFC 2015において、 MIMEをサポートする環境では異なる方法を規定している。)
Cleartext 署名メッセージには、下記の項目含まれる。
「Hash」Armorヘッダが与えられている場合、 署名には指定されたメッセージダイジェスト方式が使われる。 そのようなヘッダが無い場合、MD5 が使われ、実装は、 V2.xへの互換性のためにそれらを省略してもよい(MAY)。 複数のメッセージダイジェストが署名の中で使用された場合、 「Hash」Armorヘッダには使用したメッセージダイジェスト方式がコンマで区切ってリストされる。
現在あるメッセージダイジェストの名称は、アルゴリズムIDと共に後述する。
メッセージのクリアテキスト内容は、Dash-Escapedでなければななない。 Dash-Escapedクリアテキストとは、通常のクリアテキストであり、 すべての行は、ダッシュ('-':0x2D)から始まり、 ダッシュ('-':0x2D)の連続とスペース(' ':0x20)が前につく。 これによって、パーサ(Parser:構文解析ツール)が、 クリアテキストのArmorヘッダをクリアテキストの一部であると認識することを防ぐ。 メッセージダイジェストは、クリアテキスト上で計算しており、 Dash-Escaped形状上での計算ではない。
テキストドキュメントのバイナリ署名と同様に、 Cleartext Signatureは、 標準の<CR><LF>行終端子を使用してテキストを計算する。 署名データの終わりに来る「-----BEGIN PGP SIGNATURE-----」の前にある行終端子(例:<CR><LF>)は、 署名テキストの一部とは考えない。
また、Cleartext Signatureが計算されるとき、 行末のスペースは、すべて無視される。
正規表現は、「|」でわけられた0個以上の枝である。 一致の対象は、枝で分かれた内のひとつと必ず一致する。
枝は、0個以上の部分で構成され、連結している。 各部分は、記述順(左から右)に沿って一致していく。
正規表現の各部分はアトムであり、 「*」「+」「?」が後ろに続きアトムを修飾して正規表現を表すこともある。 「*」がつづくときは直前のアトムの0回以上の繰り返しを表す。 (例:ab*d=ad,abd,abbd..)。 「+」が続くときはアトムの1回以上の繰り返しを表す。 (例:ab+d=abd,abbd...)。 「?」が続くときはそのアトムが1回あるか否かを表す。 (例: ab?d=ad,abd)。
正規表現は、アトムの組み合わせから成り立つ。 アトムは、以下のいずれかとなる。
正規表現の範囲は、「[]」で区切られた文字リストで表し、 一致の対象は、通常その文字リストのいずれかと一致する。 文字リストが「^」で始まるものは、 後ろに続く文字リスト以外の任意の1文字と一致する (*訳注:文字集合内での否定)。 文字リストの中の2文字が「-」で分けられている場合、 これはその2文字の間のすべてのASCII文字を示す短縮形であり、 例えば、「[0-9]」という正規表現はすべての一桁の数字(0から9)と一致する。 文字リストに「]」等を含むときは (*訳注:メタキャラクタとして使われる文字を文字として表したい場合)、 それを文字リストの最初の文字とすること(「^」に続くこともある)。 同様に、「-」を含むときは文字リストの最初か最後の文字にすること。
この章ではOpenPGPで使用する定数について説明する。
注意: これらのテーブルは、完全なリストではない。 実装は、 これらのリストにないアルゴリズムの定数を作成してもよい(MAY)。
アルゴリズムの詳細に関しては、 後述する"Notes on Algorithm"の章を参照すること。
ID Algorithm -- --------- 1 - RSA(暗号と署名) 2 - RSA 暗号用 3 - RSA 署名用 16 - Elgamal(暗号用)、後述する[ELGAMAL]を参照 17 - DSA (Digital Signature Standard) 18 - (予約) 楕円形暗号 19 - (予約) ECDSA 20 - Elgamal(暗号と署名) 21 - (予約) Diffie-Hellman (X9.42:IETF-S/MIMEに定義) 100 to 110 - 秘密/試験的アルゴリズム
実装は、署名にはDSA、 暗号化にはElgamalを必ず実装しなければならない(MUST)。 実装は、RSAの鍵を実装する必要がある(SHOULD)。 実装は、他の暗号アルゴリズムを実装してもよい(MAY)。
ID Algorithm -- --------- 0 - Plaintextもしくは暗号化していないデータ 1 - IDEA [IDEA] 2 - Triple-DES(DES-EDE:192 bit ブロックに基づく 168 bit 鍵) 3 - CAST5 (128 bit 鍵、RFC 2144 に基づく) 4 - Blowfish (128 bit 鍵、16 ラウンド)[BLOWFISH] 5 - SAFER-SK128 (13ラウンド)[SAFER] 6 - (予約) DES/SK 7 - (予約) 128 bit 鍵の AES 8 - (予約) 192 bit 鍵の AES 9 - (予約) 256 bit 鍵の AES 100 to 110 - 秘密/試験的アルゴリズム
実装は、Triple-DESを必ず実装しなければならない(MUST)。 実装は、IDEAとCAST5を実装する必要がある(SHOULD)。 実装は、その他の暗号アルゴリズムを実装してもよい(MAY)。
ID Algorithm -- --------- 0 - 圧縮していない 1 - ZIP (RFC 1951) 2 - ZLIB (RFC 1950) 100 TO 110 - 秘密/試験的アルゴリズム
実装は、データを圧縮しない実装を必ずしなければならない(MUST)。 実装は、ZIPを実装する必要がある(SHOULD)。 実装は、ZLIBを実装してもよい(MAY)。
ID Algorithm Text Name -- --------- ---- ---- 1 - MD5 "MD5" 2 - SHA-1 "SHA1" 3 - RIPE-MD/160 "RIPEMD160" 4 - (予約) 2倍幅(double-width)のSHA (試験的) 5 - MD2 "MD2" 6 - (予約) TIGER/192のため予約 "TIGER192" 7 - (予約) HAVAL(5 pass, 160-bit) "HAVAL-5-160" 100 to 110 - 秘密/試験的アルゴリズム
実装は、SHA-1を必ず実装しなければならない(MUST)。 実装は、MD5を実装する必要がある(SHOULD)。
OpenPGPのパケットは、 メッセージ生成とキー転送のために一定の順序で組み立てられる。 すべてのパケットの順序が、正しく意味があるとは限らない。 ここでは、パケットシーケンスの規則を解説する。
OpenPGPユーザは、公開鍵を転送することがある。 転送可能な公開鍵の基本要素を以下に示す。
Public Keyパケットは、最初に位置する。 それに続く各UserIDパケットは、このPublic Key所有者の身元情報を提供する。 複数のUserIDパケットが続く場合は、同一人物の異なる身元情報を意味する。 例えば、ユーザは、複数のメールアドレスをもつ場合があり、 メールアドレスごとにユーザIDを構成する。
各UserIDパケットの後ろに、0個以上のSignatureパケットが続く。 各Signatureパケットは、 すぐ前にあるUserIDパケットと最初のPublic Keyパケット上で計算される。 その署名は公開鍵とユーザIDの関連性を証明する。 要するに、署名者は示されたユーザIDによってその公開鍵が本人のものである証明をするということである。
UserIDパケットの後ろには、ひとつ以上のSubkeyパケットが続く。 一般的にサブキーは、 トップレベルの公開鍵が署名のみに使用する鍵の場合に提供される。 しかし、すべてのv4鍵は、サブキーをもつことが可能であり、サブキーは、 暗号のみの鍵であったり、署名のみの鍵であったり、 もしくは両方の場合でも存在する。
各SubkeyパケットにはSignatureパケットが必ず後に続く。 その署名は、 トップレベルの公開鍵が発行したサブキーにバインドする署名にする必要がある。
サブキーや鍵パケットが無効であることを示すとき、 各鍵にはRevocation Signatureが続く場合がある。 Revocation Signatureは、その鍵自身が発行した場合か、 もしくはその鍵のトップレベル鍵が無効化権限を与えた鍵 (Self-Signaureの中のRevocation-Keyサブパケットを通じて無効化を発行の権限を与えている) によって、発行されたものは受け付ける。
転送可能なPublic Keyパケットのシーケンスは、 1回の処理で複数の公開鍵が転送できるように連結されていることがある。
OpenPGPメッセージは、パケット、 もしくは下記の文法English的なルールにしたがったパケットシーケンスで構成。 (下の表記では、コンマ「,」はシーケンスに含まれる組合せを示し、垂 直のバー「|」は選択肢をわけている。)
OpenPGPメッセージ :- 暗号メッセージ | 署名付メッセージ | 圧縮メッセージ | リテラルメッセージ 圧縮メッセージ :- Compressed Data パケット. リテラルメッセージ :- Literal Data Packet ESK :- Public Key Encrypted Session Key パケット | Symmetric-Key Encrypted Session Key パケット. ESKシーケンス :- ESK | ESKシーケンス、ESK 暗号メッセージ :- Symmetrically Encrypted Data パケット | ESKシーケンス, Symmetrically Encrypted Data パケット. One-Pass署名付メッセージ :- One-Pass Signature パケット, OpenPGPメッセージ, 関連する Signature パケット. 署名付メッセージ :- Signature パケット, OpenPGPメッセージ | One-Pass署名付メッセージ.
また、Symmetrically Encrypted Dataパケットを復号したり、Compressed Dataパケットを展開しても、 有効なOpenPGP Messageを生まなければならない。
OpenPGPアプリケーションには、 「分離署名(Detached Signature)」と呼ばれるものを使用するものがある。 例えば、プログラムのバンドルにファイルが含まれる場合、 それと共にあるふたつめのファイルが、 ひとつめのファイルのDetached Signatureである。 これらDetached Signatureは、 単純にファイルの署名データを別のSignatureパケットに格納したものである。
OpenPGP v3鍵の構成は、下記のとおりである。 スクエア括弧'[]'の中は、オプションを意味し、 省略記号'.'は、反復を示す。
RSA Public Key [Revocation Self Signature] User ID [Signature ...] [User ID [Signature ...] ...]
各署名は、RSA Public Keyと直前のユーザIDを証明する。 RSA Public Keyは、複数のユーザIDをもつことが可能であり、 各ユーザIDは、複数の署名をもつことが可能となる。
ふたつの公開鍵を使用するOpenPGP v4鍵の形式は、 v3鍵の形式と似ているが、 他の鍵をPrimary Keyの「Subkey」として後ろに足されていく点は異なる。
Primary-Key [Revocation Self Signature] [Direct Key Self Signature...] User ID [Signature ...] [User ID [Signature ...] ...] [[Subkey [Binding-Signature-Revocation] Primary-Key-Binding-Signature] ...]
SubkeyにはPrimary Key発行のSignatureが必ず後ろにつき、 そのふたつの鍵を結びつけている。 このBinding-Signatureは、v3形式でもv4形式でもよいが、 v4形式のほうがより好ましい。
上図で、SubkeyのBinding-Signatureが失効(Revoke)された場合、 失効されたBinding-Signatureは削除され、 Signature(*訳注:Binding-Signature-Revocation)のみを残してもよい。
メインキーとサブキーの両方をもつ鍵の中では、 Primary Keyは、必ず署名可能な鍵としなければならない(MUST)。 Subkeyは、どのタイプの鍵でもよい。 v4鍵ではその他の構造も可能である。 例えば、v4形式のRSA鍵のSingle-Key、RSA暗号用鍵のDSA Primary Key、 Elgamal SubkeysをもつRSA Primary Key等があり得る。
署名専用のSubkeyを有することも可能である。 これによって、Primary Keyは、Certifications(key signatures)を集め、 暗号と署名の両方に使えるSubkeysの証明(Ceritfy)にのみ使える。
v3鍵では、8オクテットの鍵IDは、 RSA鍵の公開モジュールの下位64bitで構成される。(5.5.2参照)
v3鍵のフィンガープリントは、 鍵素材(公開モジュール n、指数eが続く)を構成するMPIのボディ (2オクテットレングスパケットは含まない) をMD5でハッシュすることで作成される。
v4鍵のフィンガープリントは、 1オクテットPacket Tagの160-bit SHA-1ハッシュであり、 後ろに2オクテットのレングスパケット、 バージョンフィールドから始まるPublic Key パケット全体が続く。 鍵IDは、フィンガープリントの下位64bitである。 下記にDSA鍵を例としたハッシュ材料のフィールドを示す。
a.1) 0x99(1オクテット) a.2) (b)-(f)の上位レングスパケット(1オクテット) a.3) (b)-(f)の下位レングスパケット(1オクテット) b) バージョン番号=4(1オクテット) c) 鍵作成時間のタイムスタンプ(4オクテット) d) アルゴリズム(1オクテット): 17 = DSA (例) e) アルゴリズム特定フィールド DSAキーのアルゴリズム特定フィールド(例): e.1) DSA素数pのMPI e.2) DSA群位数q(qは、p-1を割り切れるprime diviser)のMPI e.3) DSA元gのMPI e.4) DSA公開鍵値y ( = g**x xは秘密である)のMPI
(注意)鍵IDの衝突(ふたつの異なる鍵が同じ鍵IDをもつ)が発生する可能性がある。 フィンガープリントの衝突の可能性は、鍵IDよりずっと低いが、 まったく無いとはいえない。
また、v3形式とv4形式の鍵が同じRSA鍵素材を共有した場合、 それらは異なるフィンガープリントと鍵IDをもつ。
共通鍵暗号アルゴリズムの設定(Symmetric algorithm preference)は、 鍵保持者が受け入れる暗号アルゴリズムをリストしたものである。 これは、Self-Signatureにあることから、 鍵保持者はそれぞれ異なる設定を有してもかまわない。 例えば、Aliceは、"alice@work.com"にTripleDESのみを指定し、 "alice@home.org"にはCAST5、Blowfish、TripleDESを指定してもよい。 (注意:サブキーに付属する署名も同様である。)
TripleDESは、必ず実装されるアルゴリズムなので、 明示的にリストされていなくても、リストの最後にあると認識する。 しかし、そこで明示的にリストする方が望ましい。 実装が選択を実装していない場合、 TripleDESのみの実装であると見なすこと。
実装は、 受信者の設定リストにない共通鍵暗号アルゴリズムを使用してはならない(MUST)。 複数の受信者へ暗号化をするときは、 実装は複数の受信者の設定の共通部分を適したアルゴリズムとして使用する。 (注意:TrippleDESが必ず実装されるので、共通部分は、ヌル(空)にならない。) 実装は、共通部分からアルゴリズムを選択するとき、 どのようなメカニズムを使用してもよい。
鍵保持者の選択に無い暗号アルゴリズムでメッセージが暗号化されている場合、 実装は、 何らかの方法でメッセージを復号する必要がある(SHOULD)が、 プロトコル違反を鍵保持者に必ず警告しなければならない(MUST)。 (例えば、先ほど説明したAliceは、 この仕様書にあるすべてのアルゴリズムを実装したソフトウェアをもつと仮定する。 それでもなお、仕事と家での設定を区別したいとする。 彼女の選択にないIDEAで暗号化されたメッセージを受信した場合、 ソフトウェアは、メッセージがIDEA暗号メッセージであることを彼女に警告し、 何らかの方法で適した形に復号する。)
下位互換性を重要視させた実装では、 「v3 Self-Signatureと共にあるv3鍵は、IDEAの選択であり、TripleDESは、 使えない」と暗黙に解釈してもよい(MAY)。 これは、厳密にいえば準拠していないが、実装は、この場合に限って、 上記のルールを冒してメッセージ作成者に警告を与え、 メッセージの暗号にIDEAを使用してもよい(MAY)。 OpenPGPユーザの実装にIDEAが無くメッセージを読めないことが起こりうるので、 理想的には、実装は、 ふたつのメッセージを生成することによってルールに従う。 したがって、実装は、 v3鍵と矛盾するIDEAを使用してもよい(MAY)が推奨されていない(SHOULD NOT)。
その他のアルゴリズムも共通鍵アルゴリズムの選択と似たような働きをしており、 「鍵保持者は、どのアルゴリズムを受け入れるか?」を指定する。 そこにはコメントが作られる必要がある興味深いふたつのケースがあり、 圧縮アルゴリズム設定とハッシュアルゴリズム設定である。
圧縮は、PGPが始まったときから欠くことのできない部分となっている。 OpenPGPと以前のすべてのPGPバージョンは、圧縮を提案してきた。 そして、この仕様の中では、実装が必要としなくても、 メッセージは圧縮されるのがデフォルトである。 したがって、圧縮設定は、 相手が圧縮をもたない最小の実装を使用していることを仮定して、 メッセージを圧縮しないことを鍵保持者が選択できる必要がある。 また、これによって、 どのアルゴリズムをサポートしているかを鍵保持者が表せる。
アルゴリズムの設定のように、実装は、 設定(preference vector)に無いアルゴリズムを使用してはならない(MUST NOT)。 設定が存在しない場合、それらは、 [ZIP(1)かUNCOMPRESSED(0)] と仮定される。
一般的に、ハッシュアルゴリズムは、 証明者ではなく署名者が選択するものである。 なぜならば、署名者は、誰が署名を証明するかについて、 予測できないからである。 この設定によって、デジタル署名に基づくプロトコルは、 ネゴシエーションが簡単になる。
それゆえ、AliceがBobに署名で彼女自身を証明する場合、 Bobのソフトウェアが使用しているハッシュアルゴリズムを利用するのは理解できることである。 この設定で、Bobは、 Aliceが使用しても良いアルゴリズムを自分の鍵の中で表すことを可能にしている。
アルゴリズムID0 (Plaintextを意味する)は、 秘密鍵が暗号化されずに格納されていることを表すときにのみ使用してもよい。 実装は、Symmetrically Encrypted Dataパケットの中でプレーンテキストを使用してはならない。 実装は、 暗号化されてないデータやリテラルデータをエンコードするためにLiteral Dataパケットを必ず使用する必要がある。
RSA方式タイプには、RSA署名専用鍵とRSA暗号専用鍵がある。 これらは推奨されていない。 同じことを表すために、署名の中の「鍵フラグ」サブパケットは、 よりよい方法であり、すべてのアルゴリズムへ一般化されている。 実装は、そのような鍵を作ってはいけない(SHOULD NOT)が、 解釈してもよい(MAY)。
実装は、 サイズが768bit未満のRSA鍵を実装してはいけない(SHOULD NOT)。
単に下位互換性のために、実装をRSA対応にすることは許可されている。 例えば、そのような実装は、 IDEA共通鍵暗号でのv3鍵に対応する可能性がある。 これは、その他の必須な実装規則の例外であることに注意すること。 v4の鍵でRSA対応する実装は、 必須な実装の機能を必ず実装しなければならない(MUST)。
Elgamal鍵が署名と暗号の両方に使用される場合、 鍵の生成時には特に気をつけなければならない。
Elgamalの鍵は、
から成る。
元(generator)と素数(prime)は、 離散対数問題(discrete log problem)が困難であるものを選択しなければならない。 群(group) gは、乗法群の位数がp-1、または、 その大きな部分群(subgroup)を生成するもので、 もう一方のgは、少なくとも、 ひとつの大きな素因数をもたなければならない。 良い選択肢は、pと(p-1)/2の両方が素数となるようなpを選ぶために、 「強力な」Sophie-German数を使用することである。 実際に「小さな部分群攻撃」を避けるためにも、この選択は有効であり、 実装者は、これを使う必要がある(SHOULD)。
また、Bleichenbacher [BLEICHENBACHER] の研究結果が示すように、元gが小さな素因数しかもっておらず、 gが生成する群の位数を割り切る場合、署名は、偽造可能だといえる。 特に、群の位数が偶数の場合、g = 2は、悪い選択である。 一方で、元の値が2というのは、暗号化処理が速いという点で、 暗号専用鍵に対しては有効な選択であろう。
Elgamal署名を証明するとき、 rとsがpより小さいことをテストするのは重要な点に注意していただきたい。 これをテストしない場合、pの約2倍の長さの値の大きなrを使用すれば、 簡単に署名は偽造される可能性がある。 この攻撃についても、Bleichenbacherの研究論文の中で議論されている。
Elgamal署名の安全な使用法の詳細は、 [MENEZES] に紹介されており、 上記のすべての脆弱性について議論されている。
Elgamal署名を可能にする実装は、 署名ができるElgamal公開鍵に暗号アルゴリズム識別子「20」を使わなければならない(MUST)。
実装は、 サイズが768bit未満のElgamal鍵を実装してはいけない(SHOULD NOT)。 長期のセキュリティ観点からも、Elgamal鍵のサイズは、 最低1024bit以上にする必要がある。
実装は、 サイズが768bit未満のDSA鍵を実装してはいけない(SHOULD NOT)。 現在あるDSA鍵は、 長期使用への推奨値である最大1024bitに制限されている。
多くのアルゴリズム番号がOpenPGPの実装に役立つと考えられるアルゴリズムのために予約されているが、 実際のアルゴリズムの実装を困難にする問題点がある。 それらは公開鍵暗号アルゴリズムセクションで「予約(reserved for)」と記されている。
予約公開鍵暗号アルゴリズムである楕円暗号(Elliptic Curve) (18)、 ECDSA (19)、X9.42 (21)は、必要なパラメーターやパラメーター命令、 セマンティックが定義されていない。
予約共通鍵暗号アルゴリズムであるDES/SK (6)は、 セマンティックが定義されていない。
予約ハッシュアルゴリズムであるTIGER192 (6)とHVAL-5-160 (7)は、 OIDが定義されていない。 予約済みアルゴリズムID4は、 double-width (2倍幅)のSHA1の変型に予約されているが、 (そのアルゴリズム自体は)現在まだ定義されていない。
NISTのAES (Advanced Encryption Standard)のために、 3つのアルゴリズムIDが予約されている。 このアルゴリズムは、 (少なくとも)128、192と256bitの鍵長が利用できる予定である。 このアルゴリズムは、2000年に候補の中から選択される予定である。
OpenPGPは、 CBC( Cipher FeedBack)モードの変型を利用して共通鍵暗号化をする。 この節は、そのプロセスの詳細について解説する。 このCFBモードは、Symmetrically Encrypted Dataパケットにおいて使用されている。 秘密鍵の鍵素材を暗号化するメカニズムに似ているが、それについては、 前の節で前述している。
OpenPGPのCFBモードは、 すべてゼロの初期ベクタ(IV:Initialization Vector)を使用し、 10オクテットのランダムデータをプレーンテキストの前にprefixする (オクテット9と10はオクテット7と8のコピー)。 それら10オクテットを暗号化した後、CFBの「再同期(resync)」を行う。
(注意) ブロックサイズが64bit以上のアルゴリズムの場合、 その全体のブロックに相当する関数がかけられる。 例えば、16オクテットのブロックアルゴリズムは、16オクテットで処理する。 それゆえ、2オクテットのチェックサムを作成した後、 16オクテットに取りかかる。
プロセスの順序を以下に示す。
暗号に関連するすべての技術情報と同様に、 ここで使用されるアルゴリズムの脆弱性を見極めるため、 常に現在の状況を知っておく必要がある。
このOpenPGP仕様は、公開鍵暗号技術を使用する。 鍵ペアの秘密鍵の部分の所有は、 適切な関係者およびグループによってコントロールされると仮定される。
この仕様書で示す特定の処理は、乱数の使用を必要とする。 それら乱数の生成には適切なエントロピーの源泉を使用する必要がある。 (RFC 1750参照)。
MD5ハッシュアルゴリズムには、 脆弱性(圧縮機能での疑似衝突:pseudo-collisions in the compress function)が見つかっており、MD5の使用に不賛成な人も存在する。 彼らは、SHA-1ハッシュアルゴリズムがより安全だと考えている。
多くのセキュリティプロトコル設計者は、 ひとつの鍵で秘匿性(暗号化)と完全性(署名)の両方の目的を担うのは、 よいアイデアではないと考える。 実際、署名と暗号化に異なる鍵を使用するv4の鍵の形式には、 このような動機が作成理由のひとつとなっている。 2とおりに使用できる鍵の実装を勧める実装者であるならば、 この論争について少なくとも認識している必要がある。
DSA暗号アルゴリズムは、 どのような160bitハッシュアルゴリズムとも機能するが、 ハッシュアルゴリズムの品質には敏感であり、 ハッシュアルゴリズムが弱い(broken)場合、 秘密鍵漏洩の可能性がでてくる。 DSS (Digital Signature Standard)では、 DSAは、SHA-1と使用するよう指定している。 多くの暗号学者は、RIPEMD-160を強いと見なしている。 弱いハッシュアルゴリズムは、署名を偽造されるのみでなく、 秘密鍵漏洩の可能性がある点で、実装は、 どのハッシュアルゴリズムがDSAと共に使用されているかについて、 注意する必要がある。 これらハッシュアルゴリズムの品質に関する考察は、 Elgamal署名にも同様にあてはまる。
受領者が署名方式を指定可能な認証システムを開発するならば、 単純に受領者がその署名方式を指定しているという理由によって、 署名者があえて弱いハッシュ方式を使用する可能性があることを認識すること。
この中で紹介する暗号アルゴリズムのいくつかは、 他の暗号アルゴリズムと比較してあまり分析されていないものもある。 例えば、CAST5は、現在のところ強いと見なされているが、 TripleDESの方がより長く分析されている。 他の暗号アルゴリズムにも、そのような物議がある可能性がある。
ここに挙げたいくつかの技術は、国によっては政府の管理下におかれている。
この章は、実装者への特に下位互換性についての補足コメントの集合である。 以前のPGPの実装は、OpenPGP互換ではない。 (双方の)差は、それほど大きくないこともあるが、しばしば、小さな差が、 大きな差よりもわずらわしい場合がある。 それゆえ、 ここに考えられる問題点と位互換性を考える開発者への了解事項を掲げる。
ワーキンググループへは、現在のチェアを通して連絡可能である。
John W. Noerenberg, II
Qualcomm, Inc
6455 Lusk Blvd
San Diego, CA 92131 USA
電話: +1 619-658-3510
EMail: jwn2@qualcomm.com
このメモの主要な著者を以下に示す。
Jon Callas
Network Associates, Inc.
3965 Freedom Circle
Santa Clara, CA 95054, USA
電話: +1 408-346-5860
EMail: jon@pgp.com, jcallas@nai.com
Lutz Donnerhacke
IKS GmbH
Wildenbruchstr. 15
07745 Jena, Germany
電話: +49-3641-675642
EMail: lutz@iks-jena.de
Hal Finney
Network Associates, Inc.
3965 Freedom Circle
Santa Clara, CA 95054, USA
EMail: hal@pgp.com
Rodney Thayer
EIS Corporation
Clearwater, FL 33767, USA
EMail: rodney@unitran.com
このメモは、以下に挙げる多くの著者の作業も利用している。
Derek Atkins, Charles Breed, Dave Del Torto, Marc
Dyksterhouse, Gail Haspert, Gene Hoffman, Paul Hoffman,
Raph Levien, Colin Plumb, Will Price, William Stallings,
Mark Weaver, and Philip R. Zimmermann
篠田 佳奈
Neoteny
Email: kana@neoteny.com
宮川 寧夫
独立行政法人 情報処理推進機構
Email: miyakawa@ipa.go.jp
[BLEICHENBACHER] |
Bleichenbacher, Daniel, "Generating ElGamal signatures without knowing the secret key," Eurocrypt 96. Note that the version in the proceedings has an error. A revised version is available at the time of writing from <ftp://ftp.inf.ethz.ch/pub/publications/papers/ti/isc/ElGamal.ps> |
[BLOWFISH] |
Schneier, B. "Description of a New Variable-Length Key, 64-Bit Block Cipher (Blowfish)" Fast Software Encryption, Cambridge Security Workshop Proceedings (December 1993), Springer-Verlag, 1994, pp191-204 <http://www.counterpane.com/bfsverlag.html> |
[DONNERHACKE] |
Donnerhacke, L., et. al, "PGP263in - an improved international version of PGP", ftp://ftp.iks-jena.de/mitarb/lutz/crypt/software/pgp/ |
[ELGAMAL] |
T. ElGamal, "A Public-Key Cryptosystem and a Signature Scheme Based on Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31, n. 4, 1985, pp. 469-472. |
[IDEA] |
Lai, X, "On the design and security of block ciphers", ETH Series in Information Processing, J.L. Massey (editor), Vol. 1, Hartung-Gorre Verlag Knostanz, Technische Hochschule (Zurich), 1992年。 |
[ISO-10646] | ISO/IEC 10646-1:1993. International Standard -- Information technology -- Universal Multiple-Octet Coded Character Set (UCS) -- Part 1: Architecture and Basic Multilingual Plane. UTF-8 is described in Annex R, adopted but not yet published. UTF-16 is described in Annex Q, adopted but not yet published. |
[RFC822] |
Alfred Menezes, Paul van Oorschot, and Scott Vanstone, "Handbook of Applied Cryptography," CRC Press, 1996. |
[MENEZES] |
Crocker, D., "Standard for the format of ARPA Internet text messages", STD 11, RFC 822, 1982年8月. |
[RFC1423] |
Balenson, D., "Privacy Enhancement for Internet Electronic Mail: Part III: Algorithms, Modes, and Identifiers", RFC 1423, 1993年10月. |
[RFC1641] |
Goldsmith, D. and M. Davis, "Using Unicode with MIME", RFC 1641, 1994年7月. |
[RFC1750] |
Eastlake, D., Crocker, S. and J. Schiller, 「セキュリティのための乱雑性についての要件(Randomness Recommendations for Security)」, RFC 1750, 1994年11月. |
[RFC1951] |
Deutsch, P., "DEFLATE Compressed Data Format Specification version 1.3.", RFC 1951, 1996年5月. |
[RFC1983] |
Malkin, G., "Internet Users' Glossary", FYI 18, RFC 1983, 1996年8月. |
[RFC1991] |
Atkins, D., Stallings, W. and P. Zimmermann, "PGP Message Exchange Formats", RFC 1991, 1996年8月. |
[RFC2015] |
Elkins, M., "MIME Security with Pretty Good Privacy (PGP)", RFC 2015, 1996年10月. |
[RFC2231] |
Borenstein, N. and N. Freed, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies.", RFC 2231, 1996年11月. |
[RFC2119] |
Bradner, S., 「RFCにおいて要請の程度を示すために用いるキーワード(ey words for use in RFCs to Indicate Requirement Level)」, BCP 14, RFC 2119, 1997年3月. |
[RFC2144] |
Adams, C., "The CAST-128 Encryption Algorithm", RFC 2144, 1997年3月. |
[RFC2279] |
Yergeau., F., "UTF-8, a transformation format of Unicode and ISO 10646", RFC 2279, 1998年1月. |
[RFC2313] |
Kaliski, B., "PKCS #1: RSA Encryption Standard version 1.5", RFC 2313, 1998年3月. |
[SAFER] |
Massey, J.L. "SAFER K-64: One Year Later", B. Preneel, editor, Fast Software Encryption, Second International Workshop (LNCS 1008) pp212-241, Springer-Verlag 1995年. |
Copyright (C) The Internet Society (1998). All Rights Reserved.
This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.
The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.