Baldanders.info

わかる! OpenPGP 暗号

OpenPGP は秘密データを当事者以外の第3者から守るための暗号スイート(cipher suite)です。 この記事では OpenPGP で使われている暗号技術について解説します。

  1. わかる! OpenPGP 暗号
    1. そもそも「暗号」とは
    2. 「暗号」で何ができるのか
    3. 共通鍵暗号(Symmetric-Key Cryptography)
    4. 公開鍵暗号(Public-Key Cryptography)
    5. 暗号周辺の技術
    6. OpenPGP における暗号化手順
    7. OpenPGP 鍵の構成
    8. 公開鍵基盤(Public Key Infrastructure)としての OpenPGP
  2. 暗号に関する雑多な話
    1. GnuPG の使い方
    2. GnuPG 以外の OpenPGP 実装
    3. 安全な鍵長について
    4. パスフレーズ(Passphrase)の長さについて
    5. X.509 と OpenPGP
  3. 参考文献
  4. フィードバック

そもそも「暗号」とは

そもそも「暗号」とはなんでしょう。 暗号と呼ばれているものには様々なものがありますが,セキュリティの世界でいう「暗号」は専ら数学的な手法を使ったものです。

\[ S' = F(S,K_1) \label{eq:enc} \] \[ S = F^{-1}(S',K_2) \label{eq:dec} \]

この2つの式が成り立つ仕組みを「暗号(cipher, cryptography)」と呼びます。 また,式 \eqref{eq:enc} を「暗号化(encryption)」,式 \eqref{eq:dec} を「復号(decryption)」と呼びます。

暗号化では元のデータ $S$ に対し関数 $F$ をパラメータ $K_1$ と共にあてはめ,新たなデータ $S'$ を生成します(元のデータ $S$ を「平文(plain text)」,新たなデータ $S'$ を「暗号文(cipher text)」と呼びます)。 暗号文 $S'$ から平文 $S$ が推測(解読)できないのが特徴です。

復号では暗号文 $S'$ に対し関数 $F^{-1}$ をパラメータ $K_2$ と共にあてはめ,平文 $S$ を復元します。

関数 $F$ および $F^{-1}$ のセットを「暗号方式」または単に「アルゴリズム(algorithm)」と呼び,パラメータ $K_1$ および $K_2$ を「鍵(key)」と呼びます。 よく出来た暗号は,その暗号強度(暗号の破れにくさ)が鍵の「鍵長(key size)」に依存するように設計されています。 コンピュータシステムにおいてはアルゴリズムはプログラムコードとして記述されるため秘密にできません。 一方,鍵はプログラムとは独立のデータなので,鍵さえ知られなければ平文 $S$ を安全に管理することができます。

このように,データ・アルゴリズム・鍵の3つの要素を組み合わせてデータを秘匿する技術が「暗号」なのです。

(「暗号」に近い技術として「隠蔽」があります。 これは対象のデータを一定の手順で別のデータに潜ませる技術です(逆手順で対象データを抽出します)。 「隠蔽」の具体例としてはステガノグラフィ(steganography)あるいは電子透かし(digital watermark)があります)

「暗号」で何ができるのか

この「暗号」を使って何ができるのでしょうか。 OpenPGP では「暗号」を使って以下の機能を達成します。

機密性(Confidentiality)
対象となるデータ(平文)が第3者に知られないよう秘匿します。これは「暗号」の基本的な機能ですね。
完全性(Integrity)
データ(平文または暗号文)が第3者によって改竄されていないか検知します。これには「暗号」の応用である「電子署名(digital signature)」という仕組みを使います。(電子署名については後ほど解説します)
認証(Authentication)
当事者同士でデータをやりとりする際に,なりすまし等を防止するため,正しい相手であるか確認(認証)する必要があります。認証機能の一部は電子署名(後述)を使って行いますが,本当に正しい(信頼できる)相手であるか確認するための仕組み「基盤(infrastructure)」が必要です。(この「基盤」についても後ほど解説します)
否認防止(Non-repudiation)
「否認防止」とはデータをやりとりした際に「データを送った」という事実を送信側が否定出来ないようにすることを言います。これは見落とされがちですが重要な機能です。「否認防止」は「完全性」と「認証」を達成する事で実現できます。

(最近のメッセージング・アプリでは OTR(Off-the-Recording)機能を持ったものがあります。 OTR の特徴のひとつが「否認可能(Deniability)」です。 やりとりした過去のメッセージについて送信元を証明できなくする機能で,通信の匿名性を補強する機能として「スノーデン以後」の現代において注目されています。 OpenPGP 暗号は「否認可能」ではありません)

ではこれから OpenPGP でどのような暗号技術が用いられているか見ていくことにしましょう。

共通鍵暗号(Symmetric-Key Cryptography)

先ほどの式 \eqref{eq:enc} \eqref{eq:dec} を思い出して下さい。 2つの式にある鍵 $K_1$ および $K_2$ が同じであるアルゴリズムを「共通鍵暗号(symmetric-key cryptography)」といいます(対称暗号(symmetric cryptography),秘密鍵暗号(secret key cryptography)と呼ばれることもあります)。 多くの場合,復号のアルゴリズム $F^{-1}$ が暗号化のアルゴリズム $F$ の逆手順になっているのも特徴です。

共通鍵暗号の利点はアルゴリズムがコンパクトで高速な点にあります。 また暗号文のデータサイズが(平文と比べて)あまり変わらないのも利点です。

欠点は,暗号化と復号で同じ鍵を使うため当事者間で鍵を共有しなければならないことです。 これは「鍵配送問題」と呼ばれ長年の懸案になっていました。

さらに運用上の問題点として,共通鍵暗号は1対1で使われる暗号であるため,大勢が一度に運用する場合に,必要となる鍵の数が膨大になり過ぎる,という点が挙げられます。($n$ 人が共通鍵暗号でやり取りするには一番単純な場合で $n(n-1)/2$ 個の鍵を管理する必要があります)

OpenPGP で使用可能な共通鍵暗号アルゴリズム

OpenPGP で利用可能な共通鍵暗号アルゴリズムは次のとおりです。

IDアルゴリズム鍵長ブロック長参考文献
1 IDEA 128 64 "IDEA International Data Encryption Algorithm"
2 TripleDES (3TDEA) 168 (112 bits of strength) 64 SP800-67
3 CAST5 128 64 RFC2144
4 Blowfish 128 64 "Description of a New Variable-Length Key, 64-Bit Block Cipher (Blowfish)"
5 Reserved -- --  
6 Reserved -- --  
7 AES with 128-bit key 128 128 FIPS PUB 197
8 AES with 192-bit key 192 128 FIPS PUB 197
9 AES with 256-bit key 256 128 FIPS PUB 197
10 Twofish with 256-bit key 256 128 "The Twofish Encryption Algorithm"
11 Camellia with 128-bit key 128 128 RFC3713
12 Camellia with 192-bit key 192 128 RFC3713
13 Camellia with 256-bit key 256 128 RFC3713
OpenPGP で使用可能な共通鍵暗号アルゴリズム一覧

(OpenPGP では暗号モードに CFB(Cipher Feedback) mode (の変型; RFC4880: 13.9. OpenPGP CFB Mode)を使用します。

Camellia 218/192/256 は RFC5581 で追加されました)

公開鍵暗号(Public-Key Cryptography)

前述したように,共通鍵暗号は安全に鍵を管理・配送するのに膨大なコストがかかるため,政府や軍あるいは大企業以外には扱いかねるものでした。 この問題を解消したのが1970年代に登場した「公開鍵暗号(public-key cryptography)」です。

再び式 \eqref{eq:enc} \eqref{eq:dec} を思い出して下さい。 暗号化に使う鍵 $K_1$ と復号に使う鍵 $K_2$ が異なるもので,かつ鍵 $K_1$ から鍵 $K_2$ が推測できない関数 $F$ / $F^{-1}$ が存在すれば,暗号化に使う鍵 $K_1$ は秘密にする必要がなくなります(公開可能な鍵 $K_1$ を「公開鍵(public key)」といい,秘密の鍵 $K_2$ を「秘密鍵(private key or secret key)」といいます)。 このような関数は落し戸関数(trap door function)あるいは一方向関数(one-way function)と呼ばれています。 具体的には離散対数や素因数分解などの数学的な特徴を利用したものです。

公開鍵暗号の利点は鍵配送のコストを低く抑えることができることです。 また秘密鍵を誰とも共有する必要が無いため,ひとつの鍵(公開鍵と秘密鍵の組み合わせ)で複数の相手とやりとりが可能になるのも利点です。 一方で公開鍵暗号は鍵長が巨大になるものが多く,処理速度も遅く,暗号文も巨大になる傾向(概ね平文の倍のサイズ)があります。

電子署名(Digital Signature)への応用

再び再び,式 \eqref{eq:enc} \eqref{eq:dec} を思い出して下さい。 もし暗号化に使う鍵 $K_1$ を秘密鍵とし,復号に使う鍵 $K_2$ を公開鍵にできるとすると,どうなるでしょう。 暗号化できるのは秘密鍵を持っている人のみなので,暗号文 $S'$ を公開鍵で復号した結果と実際の平文 $S$ を比較して全く同じであれば,暗号化を行ったのが秘密鍵を持っている本人であると証明できます。 これが「電子署名(digital signature)」の基本的な考え方です。

電子署名を用いることでデータの「完全性」を証明できます。 また電子署名は「認証」にも用いることができます(電子署名だけではダメですが)。 「完全性」と「認証」が達成できれば「否認防止」も達成できます。

OpenPGP で使用可能な公開鍵暗号アルゴリズム

OpenPGP で利用可能な公開鍵暗号アルゴリズムは次のとおりです。

IDアルゴリズム参考文献
1 RSA (Encrypt or Sign) "PKCS #1: RSA Cryptography Standard", RFC3447
2 RSA Encrypt-Only "PKCS #1: RSA Cryptography Standard", RFC3447
3 RSA Sign-Only "PKCS #1: RSA Cryptography Standard", RFC3447
16 Elgamal (Encrypt-Only) Taher El Gamal A public key cryptosystem and a signature scheme based on discrete logarithms
17 DSA (Digital Signature Algorithm) FIPS PUB 186-4
18 ECDH SP800-56A Revision 1
19 ECDSA FIPS PUB 186-4
20 Reserved (formerly Elgamal Encrypt or Sign)
21 Reserved for Diffie-Hellman ANSI X9.42, as defined for IETF-S/MIME
22 EdDSA High-speed high-security signatures
OpenPGP で使用可能な公開鍵暗号アルゴリズム一覧

(DSA および ECDSA は署名専用のアルゴリズムです。 また Diffie-Hellman はリモートとの通信時にリアルタイムで安全に鍵を交換するためのアルゴリズムです。 SSL/TLS や ssh などでよく用いられますが OpenPGP では今のところ用いられません。

ECDH および ECDSA は RFC6637 で追加されました。 EdDSA は現在ドラフト段階です)

暗号周辺の技術

暗号そのものではないですが,暗号に不可欠な要素技術を以下に紹介します。

メッセージ要約(Message Digest)

公開鍵暗号(電子署名も含む)の欠点は

  • 処理に時間がかかること
  • 平文よりも暗号文の方が大きくなる(概ね倍のサイズ)こと

です。 したがって,平文そのものを使って電子署名を行うのは効率的ではありません。 そこで平文を短い数値列に「要約」することが考えられました。 これが「メッセージ要約(message digest)」と呼ばれるものです。

メッセージ要約として使われるアルゴリズムは「一方向ハッシュ関数(one-way hash function)」と呼ばれています。 一方向ハッシュ関数には次の機能が要求されます。

  • ハッシュ値から元のデータが復元できないこと
  • 複数データのハッシュ値が衝突しないこと

OpenPGP で利用可能なアルゴリズムは次のとおりです。

IDアルゴリズム参考文献
1 MD5 RFC1321
2 SHA-1 FIPS PUB 186-2
3 RIPE-MD/160 "The hash function RIPEMD-160"
4 Reserved  
5 Reserved  
6 Reserved  
7 Reserved  
8 SHA256 FIPS PUB 180-4
9 SHA384 FIPS PUB 180-4
10 SHA512 FIPS PUB 180-4
11 SHA224 FIPS PUB 180-4
OpenPGP で使用可能な一方向ハッシュ関数一覧

S2K(String-to-Key)

S2K(string-to-key)はパスフレーズ(passphrase)などから共通鍵暗号用の鍵を生成する際に使われるアルゴリズムです。

IDS2K タイプ
1 Salted S2K
2 Reserved value
3 Iterated and Salted S2K
OpenPGP で使用可能な S2K アルゴリズム一覧

擬似乱数生成

充分に secure な乱数の生成はとても重要な技術要素です。 OpenPGP では RFC4086 を参照し擬似乱数生成を行います。

OpenPGP における暗号化手順

ここからは OpenPGP でどのように暗号化・復号が行われているのか見ていくことにしましょう。

その前に,いったん用語を整理しておきます。

平文(Plain Text)
暗号化する前のデータを指します。テキストとは限らずバイナリデータを含めてこう呼びます。
暗号文(Cipher Text)/dt>
平文を暗号化したデータを指します。通常はバイナリデータ(またはバイナリをテキスト展開したデータ)です。
メッセージ(Message)
やりとりする平文を「メッセージ」を呼ぶことがあります。これは OpenPGP 特有の言い回しで, OpenPGP の前身である PGP(Pretty Good Privacy)が主に電子メールの暗号化に利用されていたことに由来しています。また元のメッセージ(平文)に対する暗号文を「暗号化メッセージ(encrypted message)」と呼ぶことがあります。
送信者(Sender)
暗号化メッセージの送り手を指します。メッセージを暗号化するのも送信者です。
受信者(Recipient)
暗号化メッセージの受け手を指します(「受取人」という場合もあります)。受信者によって暗号化メッセージは復号されます。
共通鍵暗号(Symmetric-Key Cryptography)
暗号化と復号に同じ鍵を用いるアルゴリズムの総称です。コンパクトで高速なのが利点ですが,鍵の管理コストが高くなるのが欠点です。
公開鍵暗号(Public-Key Cryptography)
暗号化と復号に異なる鍵を用いるアルゴリズムの総称です。暗号化用の鍵を公開できるため鍵の管理コストを抑えられるのが利点ですが,処理が遅く暗号化メッセージが元のメッセージよりかなり大きくなるのが欠点です。
電子署名(Digital Signature)
公開鍵暗号の一種ですが暗号化用の鍵を秘密鍵とし復号用の鍵を公開します。この機能によりメッセージの完全性(integrity)を担保します。利点・欠点は公開鍵暗号と同じです。

アルゴリズムとして共通鍵暗号と公開鍵暗号を挙げましたが,それぞれ利点と欠点があります。 そこで OpenPGP では両者の利点を上手く組み合わせた「ハイブリッド暗号」を用います。

ハイブリッド暗号(Hybrid Cryptography)

コンパクトで高速な共通鍵暗号,鍵を安全に管理できる公開鍵暗号,両者の利点を組み合わせた暗号化・復号の手順を「ハイブリッド暗号(hybrid cryptography)」と呼びます。

まず,ハイブリッド暗号の暗号化の手順を以下に示します。

Hybrid Encription
ハイブリッド暗号による暗号化手順(参考:結城浩著『新板暗号技術入門』)

メッセージを暗号化するための鍵を「セッション鍵(session key)」と言います。 セッション鍵は暗号化の度ごとに異なる鍵を擬似乱数生成器で生成します。 セッション鍵は受信者の公開鍵で暗号化します。 公開鍵暗号は処理が重く暗号文が大きくなるのが欠点ですが,セッション鍵は共通鍵暗号用の鍵で,鍵長の最大はせいぜい $512\,\mathrm{bits}$ ほどなので問題になりません。

一方,ハイブリッド暗号の復号は暗号化の逆手順で,以下のとおりになっています。

Hybrid Decryption
ハイブリッド暗号による復号手順(参考:結城浩著『新板暗号技術入門』)

セッション鍵の復号には受信者の秘密鍵を用います。 秘密鍵は受信者しか持っていないので,セッション鍵は受信者しか復号できません。 セッション鍵が復号できない限り暗号化メッセージも復号できません。

このようにしてメッセージの「機密性(confidentiality)」を保ちます。

鍵への電子署名

公開鍵は秘密情報ではないので第3者に知られても構いませんが,鍵配送の過程で改竄やなりすましを受ける可能性があります。

そこで鍵に対して受信者(鍵の持ち主)または送信者(公開鍵の使用者)が電子署名を行うことによって,改竄を防ぎなりすましのリスクを下げます。 (詳しくは後述の「公開鍵基盤」の節を参照して下さい)

OpenPGP 鍵の構成

OpenPGP 鍵は主に以下の「パケット(packet)」で構成されています。

  • 公開鍵パケット(Public-Key Packet)
  • 公開サブ鍵パケット(Public-Subkey Packet)
  • 秘密鍵パケット(Secret-Key Packet)
  • 秘密サブ鍵パケット(Secret-Subkey Packet)
  • ユーザ ID パケット(User ID Packet)
  • 署名パケット(Signiture Packet)

以降,1つづつ見ていくことにしましょう

公開鍵パケット/公開サブ鍵パケット(Public-Key Packet / Public-Subkey Packet)

公開鍵は1個の公開鍵パケットと0個以上の公開サブ鍵パケットを持ち,それぞれ公開鍵情報を格納します。 公開鍵パケットは主に電子署名の検証に用います。 公開サブ鍵パケットは暗号化に用います。

(ほとんどのアルゴリズムでは暗号化用の鍵と電子署名用の鍵は別になっているため,公開鍵パケットは電子署名用,公開サブ鍵パケットは暗号化用で使い分けます。 更に電子署名専用の鍵も作成可能で,その場合は公開サブ鍵パケットを含みません。 ちなみに暗号化専用の鍵は作成できません)

秘密鍵パケット/秘密サブ鍵パケット(Secret-Key Packet / Secret-Subkey Packet)

秘密鍵は1個の秘密鍵パケットと0個以上の秘密サブ鍵パケットを持ち,それぞれ秘密鍵情報を暗号化した状態で格納します。 秘密鍵パケットは主に電子署名に用います。 秘密サブ鍵パケットは復号に用います。

秘密鍵情報の暗号化には共通鍵暗号を用います。 鍵はパスフレーズ(passphrase)から生成します(S2K)。

ユーザ ID パケット(User ID Packet)

公開鍵パケットまたは秘密鍵パケットに対して1個以上のユーザ ID パケットを持ちます(複数のユーザ ID が設定可能です)。 ユーザ ID は,通常はユーザの名前とメールアドレスが入りますが,内容に関して特に制約があるわけではありません。

署名パケット(Signiture Packet)

ユーザ ID パケットに対して0個以上の署名パケットを持ち,それぞれ電子署名情報を格納します。 また公開サブ鍵パケットおよび秘密サブ鍵パケットに対しても0個以上の署名パケットを持ちます。

(実際の OpenPGP 実装では,ユーザ ID パケットおよび公開/秘密サブ鍵パケットのそれぞれについて必ず自己署名(自分自身の電子署名用秘密鍵による電子署名)が付きます。 更に自己署名のない鍵は無効とされ使用することができないようになっています)

署名パケットには署名サブパケット(Signature Subpacket)によって以下の情報が付加されます。(主なもののみ挙げています)

  • 署名作成日時(signature creation time)
  • 鍵有効期間(key expiration time)
  • 共通鍵暗号アルゴリズム設定(preferred symmetric algorithms)
  • 発行者の鍵 ID(issuer key ID)
  • ハッシュアルゴリズムの設定(preferred hash algorithms)
  • 圧縮アルゴリズムの設定(preferred compression algorithms)
  • プライマリユーザ ID(primary user id)
  • 鍵フラグ(key flags)
  • 失効の理由(reason for revocation): 鍵の失効については後述します

OpenPGP 鍵の生成から失効まで

ここで OpenPGP の実装のひとつである GnuPG を使って鍵の生成を実際に行ってみます。

まずは鍵の生成から。 鍵の生成には --gen-key オプションを付けて実行します。

> gpg --gen-key
gpg (GnuPG) 1.4.18; Copyright (C) 2014 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 2
DSA keys may be between 1024 and 3072 bits long.
What keysize do you want? (2048) 3072
Requested keysize is 3072 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 30
Key expires at 11/14/14 21:53:38
Is this correct? (y/N) y

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: John Doe
Email address: john@examle.com
Comment: Demonstration
You selected this USER-ID:
    "John Doe (Demonstration) <john@examle.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.

Enter passphrase:

この例では公開鍵暗号アルゴリズムに DSA and Elgamal を,鍵長を $3072\,\mathrm{bits}$ とし,有効期限を30日に,ユーザ ID を John Doe (Demonstration) <john@examle.com> としました。 最後にパスフレーズを入力すれば鍵を生成できます。 生成した公開鍵は以下のようになっています。

> gpg --fingerprint --fingerprint 0xCE59D5FA
gpg: using PGP trust model
pub   3072D/CE59D5FA 2014-10-15 [expires: 2014-11-14]
      Key fingerprint = 72E3 0B61 4831 3F49 BB20  418B AB5B 0C7F CE59 D5FA
uid                  John Doe (Demonstration) <john@examle.com>
sub   3072g/EAE9813D 2014-10-15 [expires: 2014-11-14]
      Key fingerprint = 9309 0D77 D525 115B 0880  0C12 3937 2D4D EAE9 813D

Key fingerprint(鍵指紋)は公開鍵パケットおよび公開サブ鍵パケットの SHA-1 ハッシュ値($160\,\mathrm{bits}$)です。 3072D/CE59D5FA は公開鍵パケットのアルゴリズム(前半: $3072\,\mathrm{bits}$ DSA であることを示す)と鍵 ID を示します。 鍵 ID は鍵指紋の下 $32\,\mathrm{bits}$ (または $64\,\mathrm{bits}$)の値で,鍵の識別子として用いられています。 3072g/EAE9813D は公開サブ鍵パケットのアルゴリズム(前半: $3072\,\mathrm{bits}$ Elgamal であることを示す)と鍵 ID を示します。

では,この公開鍵を更に pgpdump で詳しく見てみましょう。

> gpg -a --export 0xCE59D5FA | pgpdump
gpg: writing to stdout
Old: Public Key Packet(tag 6)(1198 bytes)
        Ver 4 - new
        Public key creation time - Wed Oct 15 21:55:47 東京 (標準時) 2014
        Pub alg - DSA Digital Signature Algorithm(pub 17)
        DSA p(3072 bits) - ...
        DSA q(256 bits) - ...
        DSA g(3071 bits) - ...
        DSA y(3071 bits) - ...
Old: User ID Packet(tag 13)(42 bytes)
        User ID - John Doe (Demonstration) <john@examle.com>
Old: Signature Packet(tag 2)(128 bytes)
        Ver 4 - new
        Sig type - Positive certification of a User ID and Public Key packet(0x13).
        Pub alg - DSA Digital Signature Algorithm(pub 17)
        Hash alg - SHA256(hash 8)
        Hashed Sub: signature creation time(sub 2)(4 bytes)
                Time - Wed Oct 15 21:55:47 東京 (標準時) 2014
        Hashed Sub: key flags(sub 27)(1 bytes)
                Flag - This key may be used to certify other keys
                Flag - This key may be used to sign data
        Hashed Sub: key expiration time(sub 9)(4 bytes)
                Time - Fri Nov 14 21:55:47 東京 (標準時) 2014
        Hashed Sub: preferred symmetric algorithms(sub 11)(5 bytes)
                Sym alg - AES with 256-bit key(sym 9)
                Sym alg - AES with 192-bit key(sym 8)
                Sym alg - AES with 128-bit key(sym 7)
                Sym alg - CAST5(sym 3)
                Sym alg - Triple-DES(sym 2)
        Hashed Sub: preferred hash algorithms(sub 21)(5 bytes)
                Hash alg - SHA256(hash 8)
                Hash alg - SHA1(hash 2)
                Hash alg - SHA384(hash 9)
                Hash alg - SHA512(hash 10)
                Hash alg - SHA224(hash 11)
        Hashed Sub: preferred compression algorithms(sub 22)(3 bytes)
                Comp alg - ZLIB <RFC1950>(comp 2)
                Comp alg - BZip2(comp 3)
                Comp alg - ZIP <RFC1951>(comp 1)
        Hashed Sub: features(sub 30)(1 bytes)
                Flag - Modification detection (packets 18 and 19)
        Hashed Sub: key server preferences(sub 23)(1 bytes)
                Flag - No-modify
        Sub: issuer key ID(sub 16)(8 bytes)
                Key ID - 0xAB5B0C7FCE59D5FA
        Hash left 2 bytes - e5 fb
        DSA r(256 bits) - ...
        DSA s(255 bits) - ...
                -> hash(DSA q bits)
Old: Public Subkey Packet(tag 14)(781 bytes)
        Ver 4 - new
        Public key creation time - Wed Oct 15 21:55:47 東京 (標準時) 2014
        Pub alg - ElGamal Encrypt-Only(pub 16)
        ElGamal p(3072 bits) - ...
        ElGamal g(3 bits) - ...
        ElGamal y(3072 bits) - ...
Old: Signature Packet(tag 2)(103 bytes)
        Ver 4 - new
        Sig type - Subkey Binding Signature(0x18).
        Pub alg - DSA Digital Signature Algorithm(pub 17)
        Hash alg - SHA256(hash 8)
        Hashed Sub: signature creation time(sub 2)(4 bytes)
                Time - Wed Oct 15 21:55:47 東京 (標準時) 2014
        Hashed Sub: key flags(sub 27)(1 bytes)
                Flag - This key may be used to encrypt communications
                Flag - This key may be used to encrypt storage
        Hashed Sub: key expiration time(sub 9)(4 bytes)
                Time - Fri Nov 14 21:55:47 東京 (標準時) 2014
        Sub: issuer key ID(sub 16)(8 bytes)
                Key ID - 0xAB5B0C7FCE59D5FA
        Hash left 2 bytes - a5 62
        DSA r(253 bits) - ...
        DSA s(254 bits) - ...
                -> hash(DSA q bits)

これまで述べたパケットの様子が見れると思います。

何らかの理由で鍵の有効期間より前に破棄しなければならない場合は,鍵の失効(revoke)手続きを行います。 まず失効証明書を作成します。 GnuPG の場合は --gen-revoke オプションで起動します。

> gpg -a -o john-revoke.asc --gen-revoke 0xCE59D5FA

sec  3072D/CE59D5FA 2014-10-15 John Doe (Demonstration) <john@examle.com>

Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here)
Your decision? 3
Enter an optional description; end it with an empty line:
> demonstration
>
Reason for revocation: Key is no longer used
demonstration
Is this okay? (y/N) y

You need a passphrase to unlock the secret key for
user: "John Doe (Demonstration) <john@examle.com>"
3072-bit DSA key, ID CE59D5FA, created 2014-10-15

Enter passphrase:

gpg: writing to `john-revoke.asc'
gpg: DSA/SHA256 signature from: "CE59D5FA John Doe (Demonstration) <john@examle.com>"
Revocation certificate created.

Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable.  But have some caution:  The print system of
your machine might store the data and make it available to others!

ちなみにこの失効証明書の中身はこのようになっています。

> pgpdump john-revoke.asc
Old: Signature Packet(tag 2)(110 bytes)
        Ver 4 - new
        Sig type - Key revocation signature(0x20).
        Pub alg - DSA Digital Signature Algorithm(pub 17)
        Hash alg - SHA256(hash 8)
        Hashed Sub: signature creation time(sub 2)(4 bytes)
                Time - Wed Oct 15 22:50:14 東京 (標準時) 2014
        Hashed Sub: reason for revocation(sub 29)(14 bytes)
                Reason - Key is retired and no longer used
                Comment - demonstration
        Sub: issuer key ID(sub 16)(8 bytes)
                Key ID - 0xAB5B0C7FCE59D5FA
        Hash left 2 bytes - e7 ce
        DSA r(254 bits) - ...
        DSA s(255 bits) - ...
                -> hash(DSA q bits)

この失効証明書をインポートすることで目的の鍵を失効することができます。

> gpg --import john-revoke.asc
> gpg --fingerprint --fingerprint 0xCE59D5FA
gpg: using PGP trust model
pub   3072D/CE59D5FA 2014-10-15 [revoked: 2014-10-15]
      Key fingerprint = 72E3 0B61 4831 3F49 BB20  418B AB5B 0C7F CE59 D5FA
uid                  John Doe (Demonstration) <john@examle.com>
sub   3072g/EAE9813D 2014-10-15 [revoked: 2014-10-15]
      Key fingerprint = 9309 0D77 D525 115B 0880  0C12 3937 2D4D EAE9 813D

公開鍵基盤(Public Key Infrastructure)としての OpenPGP

これまで見てきたように公開鍵暗号を使えば鍵を安全に管理することができます。 また公開鍵暗号の応用である電子署名を使えばデータや鍵の改竄を防ぐことができます。 しかし,このままでは「なりすまし」を防ぐことができません。 「なりすまし」を防ぐためには,公開鍵が正しく本人のものであると証明する仕組みが必要です。 この仕組みのことを公開鍵基盤(PKI; Public Key Infrastructure)と呼びます。 電子署名と公開鍵基盤を組み合わせることで「認証(authentication)」が達成できます。

ここでは OpenPGP がどのようにして公開鍵を証明しているのか見ていくことにします。

OpenPGP における鍵の配送・交換

OpenPGP では公開鍵が本人のものであるかどうかを末端利用者(end user)同士が個人レベルで認証します。 OpenPGP では権威的に機能する CA(Certification Authority)は存在しません。 ではどのようにして公開鍵を認証しているのか,簡単な例で説明します。

ケース1:直接公開鍵を交換する場合

メッセージを交換したい2人のユーザ Alice と Bob を想定してみます。 交換したいメッセージは第3者には秘密にしておきたいのでメッセージを暗号化してやりとりすることにしました。 そのために,まずお互いの公開鍵を交換します。 この交換には,直接手渡しするか(改竄やなりすましのない)安全な通信経路を使う必要があります。

Hybrid Decryption
公開鍵の交換1(Alice と Bob)

Alice と Bob はそれぞれ相手の公開鍵に署名し送り返します(既に公開鍵の交換自体は成立しているので安全でない通信経路でも大丈夫です)。

Hybrid Decryption
公開鍵の交換2(Alice と Bob)

これでお互いにお互いの公開鍵を認証したことになります。

Hybrid Decryption
公開鍵の交換3(Alice と Bob)
ケース2:第3者の署名で公開鍵を認証する場合

Alice と Bob に加えて Chris ともメッセージを交換したいと考えます。 このとき既にAlice と Chris の間では公開鍵の交換と認証が完了しているとします。

Hybrid Decryption
公開鍵の交換4(Alice と Bob と Chris)

Bob と Chris の間でも公開鍵を交換したいのですが,お互い面識が無いため,安全に公開鍵を交換する方法がありません。 この場合でも,Chris の公開鍵には既に Alice の電子署名があるため, Bob は Chris の公開鍵を(Alice の電子署名を通じて)認証できます。 Bob の公開鍵も同様に(Alice の電子署名を通じて)認証できます。

Hybrid Decryption
公開鍵の交換5(Alice と Bob と Chris)
ケース3:鍵サーバ(Keyserver)を介して公開鍵を取得する場合

公開鍵を鍵サーバ(Keyserver)に預け,利用者と鍵サーバとの間で公開鍵(と電子署名)の状態を最新に保つことで,利用者間の鍵の交換と認証がスムーズになります。 これはメッセージをやりとりする関係者が多い場合に有効です。

Hybrid Decryption
公開鍵の交換6(Alice と Bob と Chris と鍵サーバ)

ただし,この場合でも認証を行うのはあくまでも利用者側です。 鍵サーバはアップロードされる公開鍵に対して何の保証もしません。

実際にインターネットではいくつかの鍵サーバが稼働しています。

鍵サーバ間は同期しているため,どの鍵サーからも同じ公開鍵を取得する事ができます。

OpenPGP の信用モデル(Trust Model)

先程述べたように, OpenPGP では公開鍵が本人のものであるかどうかを末端利用者(end user)同士が個人レベルで認証します。 取得した公開鍵を認証する際に電子署名を行うのですが,このとき公開鍵に対して以下の信用度(trust)を設定できます。

  • 未定義(undefined)
  • 未知(unknown)
  • 信用しない(untrusted)
  • ある程度信用する(marginal)
  • 完全に信用する(complete)
  • 絶対的に信用する(ultimate; 自分自身のみ)

公開鍵を認証する際は電子署名ごとの信用度をチェックし,最終的に鍵の有効性(validity; 改竄やなりすましがないこと)を以下のように判定されます(信用度と同じ名称なのでややこしいですが)。

  • 未定義(undefined)
  • 無効(untrusted)
  • 最低限有効(marginal)
  • 完全に有効(complete)

つまり,ある鍵に対して多くのユーザから高い信用度(「ある程度信用する」または「完全に信用する」)を集めるほど有効性も高くなるわけです。 このやり方であれば未知のユーザの公開鍵でも(鍵に付与される信用度を基に)判断することができます。

このように鍵に対する署名(および信用度)のネットワークによって有効性を判断するモデルを「信用の輪(web of trust)」と言います。 OpenPGP の公開鍵基盤はこの「信用の輪」がベースになっています。

(ここで言う「信用」は「あなたは人として信用できる」の信用ではなく,鍵に対して改竄やなりすましがなく適切に運用されているか否かという意味での信用です。 たとえ有名人の鍵であっても安全な方法で鍵を受け取っているのでなければ安易に信用すべきではありません。 一方,顔見知りから直接鍵を受け取ったなら改竄やなりすましは低いと判断できます)