PGG
***

PGG は、安全な通信のための様々なツールと Emacs の仲を取り持つライブラリーです。また、PGG は MIME メッセージの暗号化と解読、それに署名と検証のための単純なユーザーインタフェースも提供します。

このファイルは様々な PGP の実装への Emacs インターフェースである PGG 0.1 を説明します。

Copyright © 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.

     Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover texts being ``A GNU Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the license is included in the section entitled ``GNU Free Documentation License''.

     この文書を、フリーソフトウェア財団発行の GNU フリー文書利用許諾契約書第 1.3 版またはそれ以降の版が定める条件の下で複製、配布、あるいは変更することを許可します。変更不可部分は指定しません。“A GNU Manual”は表表紙テキスト、以下の (a) は裏表紙テキストです。この利用許諾契約書の複写は「GNU フリー文書利用許諾契約書」という章に含まれています。

     (a) The FSF's Back-Cover Text is: ``You have the freedom to copy and modify this GNU manual.  Buying copies from the FSF supports it in developing GNU and promoting software freedom.''

     (a) FSF の裏表紙テキスト:「あなたにはこの GNU Manual を複製したり変更する自由があります。FSF からの複写の購入は GNU の開発とソフトウェアの自由の促進を支援します。」

概要
**

PGG は、安全な通信のための様々なツールと Emacs の仲を取り持つライブラリーです。同様の機能は Mailcrypt も持っていますが、Mailcrypt は PGP/MIME のインフラで通常用いられる分離された PGP メッセージを取り扱うことができません。これが、私 (作者) が新しいライブラリーを書いた主な理由です。

PGP/MIME は MIME Object Security Services (RFC1848) の実装です。その標準は RFC2015 で記述されています。

必要条件
****

PGG を使うためには、少なくとも一つのプライバシー保護システムの実装が必要です。このマニュアルは、そのようなプログラムをすでに取得、インストールしていて、基本的な使い方を知っていることを想定しています。

ディフォルトでは PGG は GnuPG を使います。そのようなシステムに慣れていないのであれば、http://www.gnupg.org/documentation/ にある GNU Privacy Handbook (GPH) に目を通すことを勧めます。

GnuPG を使う場合には gpg-agent の利用を推奨します。それはバージョン 2.0 以降の GnuPG とともに配布されています。これは、どんなプロトコルを使うかとは無関係に秘密鍵を管理するデーモンで、パスフレーズを入力してキャッシュするための最も安全な手段を提供します (see Caching passphrase)。それが稼働している場合、PGG はディフォルトで gpg-agent を使おうとします。See Invoking GPG-AGENT (Using the GNU Privacy Guard).

PGG は Pretty Good Privacy バージョン 2 またはバージョン 5 もサポートします。

使い方
***

このライブラリーの最上位インタフェースはとても単純で、公開鍵による暗号の操作のみを想定しています。

PGG を使うためには、アプリケーションプログラムの冒頭で次の S 式を評価してください。

     (require 'pgg)

実行時に pgg.el の存在を確認したいなら、上記の方法ではなく以下のように、必要な機能の autoload を設定することもできます。

     (autoload 'pgg-encrypt-region "pgg"
       "Encrypt the current region." t)
     (autoload 'pgg-encrypt-symmetric-region "pgg"
       "Encrypt the current region with symmetric algorithm." t)
     (autoload 'pgg-decrypt-region "pgg"
       "Decrypt the current region." t)
     (autoload 'pgg-sign-region "pgg"
       "Sign the current region." t)
     (autoload 'pgg-verify-region "pgg"
       "Verify the current region." t)
     (autoload 'pgg-insert-key "pgg"
       "Insert the ASCII armored public key." t)
     (autoload 'pgg-snarf-keys-region "pgg"
       "Import public keys in the current region." t)

ユーザーコマンド
========

この時点で、いくつかの暗号に関するコマンドを使うことができます。これらのコマンドの挙動は起動方法に依存します。これらのコマンドは、ライブラリー関数として利用されることもあるからです。例えば、あなたがある署名者の公開鍵を持っていないと pgg-verify-region という関数は即座に失敗しますが、これが対話的に呼び出された場合には、サーバーから公開鍵をダウンロードするかどうかをあなたに尋ねます。

 -- Command: pgg-encrypt-region start end recipients &optional sign passphrase
     START と END の間の領域を RECIPIENTS 宛に送るものとして暗号化します。対話的に呼ぶと、受信者を尋ねます。

     暗号化に成功すると、現在の領域の内容を暗号化したデータで置き換えます。

     オプション引数 SIGN が nil でなかったら、署名と暗号化を同時に行ないます。現在この機能は GnuPG で動作することが確認されていますが、 PGP や PGP5 では動作しないかもしれません。

     オプション引数 PASSPHRASE が nil だったら、パスフレーズのキャッシュからか、またはユーザーに入力してもらうことによってパスフレーズを得ます。

 -- Command: pgg-encrypt-symmetric-region &optional start end passphrase
     現在の START と END の間の領域を、共通鍵暗号 (symmetric cipher) で暗号化します。呼び出した後でパスフレーズが尋ねられます。

     オプション引数 PASSPHRASE が nil だったら、パスフレーズのキャッシュからか、またはユーザーに入力してもらうことによってパスフレーズを得ます。

     共通鍵暗号による暗号化は、現在 GnuPG だけで実装されています。

 -- Command: pgg-decrypt-region start end &optional passphrase
     START と END の間の領域を解読します。解読に成功すると、現在の領域の内容を解読したデータで置き換えます。

     オプション引数 PASSPHRASE が nil だったら、パスフレーズのキャッシュからか、またはユーザーに入力してもらうことによってパスフレーズを得ます。

 -- Command: pgg-sign-region start end &optional cleartext passphrase
     START と END の間のテキストに署名します。三番目のオプション引数 CLEARTEXT が nil ではないか、あるいは対話的に呼ばれた場合、分離された署名を作りません。そのような場合には、現在の領域の内容を署名したデータで置き換えます。

     オプション引数 PASSPHRASE が nil だったら、パスフレーズのキャッシュからか、またはユーザーに入力してもらうことによってパスフレーズを得ます。

 -- Command: pgg-verify-region start end &optional signature fetch
     START と END の間の領域にある署名を検証します。三番目のオプション引数 SIGNATURE が nil でなかったら、その引数は現在の領域の分離された署名のファイルとして取り扱われます。

     四番目のオプション引数 FETCH が nil ではないか、あるいは対話的に呼ばれた場合、公開鍵をサーバーから取得します。

 -- Command: pgg-insert-key
     ユーザーの公開鍵を取得して、それを ASCII 装甲の形式で挿入します。

 -- Command: pgg-snarf-keys-region start end
     START と END の間の領域にある公開鍵を集め、ユーザーの鍵束 (keyring) に追加します。

どの実装を使うか
========

PGP は歴史が長く、今では多くの実装を利用することができるので、それぞれが持っている個々の機能がずいぶん異なっていることがあります。例えば GnuPG を使っているのならば、暗号アルゴリズムとして 3DES や CAST5、 BLOWFISH などを選ぶことができますが、PGP のバージョン 2 は IDEA しかサポートしていません。

どの実装を使うかは pgg-scheme 変数が制御します。nil だったら (それがディフォルト)、代わりに pgg-default-scheme 変数の値を使います。

 -- Variable: pgg-scheme
     どの PGP 実装を用いるかを強制します。設定できるのは gpg、 pgp および pgp5 のどれかです。ディフォルトは nil です。

 -- Variable: pgg-default-scheme
     ディフォルトの PGP 実装です。値は gpg、pgp および pgp5 のどれかでなければなりません。ディフォルトは gpg です。

パスフレーズをキャッシュする
==============

PGP 実装として GnuPG (gpg) を使うのであれば、パスフレーズの入力とキャッシュ (gpg-agent は実際にはパスフレーズではなくて秘密鍵をキャッシュします。一方ユーザーの視点からは、この技術的な差異は見えません。)するために gpg-agent というプログラムを使うことを推奨します。

 -- Variable: pgg-gpg-use-agent
     nil でない値では、可能な場合は常にいつでも gpg-agent を使おうとします。ディフィフォルトは t です。gpg-agent が稼働していないか、または GnuPG が現在の PGP 実装として選択されていない場合は、 PGG 自身が持っているパスフレーズをキャッシュする仕組みが使われます (下記参照)。

PGG で gpg-agentを使うには、第一に gpg-agent が確実に稼働しているようにしてください。例えば X Window System を走らせているのであれば、以下の行をあなたの .xsession ファイルに置くことによって、それを確実にすることができます:

     eval "$(gpg-agent --daemon)"

gpg-agent の起動に関するさらに詳しいことは、see Invoking GPG-AGENT (Using the GNU Privacy Guard).

GnuPG のパスフレーズを必要とする PGG の機能を実行するときはいつも、 GnuPG は gpg-agent とやり取りを行ない、それはあなたにパスフレーズを入力することを要求します。しかし gpg-agent がその結果を「キャッシュ」するので、次回以降の実行では再びパスフレーズの入力は要りません。 (通常このキャッシュは一定時間経過後に期限切れ消去されます。これを変更するには、gpg-agent を起動するときに --default-cache-ttl オプションを使ってください。)

X Window System の環境では gpg-agent はパスフレーズの入力を要求するためにグラフィックなウィンドウを開きます。しかし文字端末で Emacs を使っている場合は、gpg-agent は端末からの入力を受け取る上で問題があります。それが Emacs に送られてしまうからです。この問題に対処するための暫定的な対策のひとつは、gpg-agent を --keep-tty オプションとともに Emacs とは別の端末で走らせることです。これは gpg-agent に、パスフレーズの入力にそれ自身の端末を使うようにさせます。

gpg-agent を使わない場合、PGG は Emacs を介してパスフレーズの入力を要求します。これにはパスフレーズをキャッシュする仕組みがあり、それは変数 pgg-cache-passphrase で制御されます (下記参照)。

gpg-agent ではなく PGG でパスフレーズを扱う場合には安全上のリスクがあります。Emacs の要求に従ってパスフレーズを入力すると、それは一時的に Emacs が実行しているメモリーに cleartext 文字列として格納されます。もしそのメモリーがディスクとの間で swap されると、理論上 root ユーザーはパスフレーズを swap ファイルから抽出することができます。その上、そのシステムが廃棄されたり盗難に会った後も、その cleartext のパスフレーズが含まれている swap ファイルはディスクに残っているかもしれないのです。 gpg-agent はメモリーを lock するような策をもって、この問題を回避しています。それは Emacs には実装されていません。

 -- Variable: pgg-cache-passphrase
     nil でなければ、パスフレーズを保持します。初期値は t です。しかし、あなたがセキュリティについて気掛かりなら、この変数を nil に設定することによって、パスフレーズのキャッシュをやめさせることができます。

 -- Variable: pgg-passphrase-cache-expiry
     パスフレーズを保持しておく時間を秒で指定します。

パスフレーズが非-ASCII 文字を含んでいる場合は、それをエンコードするための coding system を指定する必要があります。GnuPG はパスフレーズを文字列としてではなく、バイト列として扱うからです。

 -- Variable: pgg-passphrase-coding-system
     パスフレーズをエンコードするための coding system です。

ディフォルトのユーザー ID
==============

通常 PGP の実装は、暗号化および復号化に使う適切な鍵を選ぶことができますが、あなたが一つ以上の鍵を持っている場合、用いる鍵の id を指定する必要があります。

 -- Variable: pgg-default-user-id
     ディフォルトのユーザー ID です。指定しない場合は (user-login-name) の戻り値がディフォルトになります。この変数はカスタマイズ可能です。

 -- Variable: pgg-gpg-user-id
     GnuPG で使うディフォルトのユーザー ID です。ディフォルトは nil です。nil ではない値にすると、pgg-default-user-id より優先して使われます。カスタマイズ可能です。

 -- Variable: pgg-pgp-user-id
     PGP 2.x/6.x で使うディフォルトのユーザー ID です。ディフォルトは nil です。nil ではない値にすると、 pgg-default-user-id より優先して使われます。カスタマイズ可能です。

 -- Variable: pgg-pgp5-user-id
     PGP 5.x で使うディフォルトのユーザ ID です。ディフォルトは nil です。nil ではない値にすると、pgg-default-user-id より優先して使われます。カスタマイズ可能です。

構成
**

PGG は「PGP 実装のスキーム (枠組)」という考えを導入します。以後、「スキーム (scheme)」と表記します。この用語は luna object system での singleton object に由来します。

PGG は PGP の機能にアクセスすると同時にそれを開発するために設計されたので、その構成は、相互運用性だけでなく拡張性も考慮する必要がありました。この章では、PGG のバックエンドをどのように記述するかを探しながら、PGG がどのようにつくられているかを探検してみましょう。

初期化
===

スキームは、使う前に初期化されなければなりません。ただ一つのスキームを使うことを保証するのが良いでしょう。

以下のコードは pgg-gpg.el からの抜き書きです。ある pgg-gpg のスキームがいったん初期化されると、それは pgg-scheme-gpg-instance 変数に保存され、以後、再利用されます。

     (defvar pgg-scheme-gpg-instance nil)

     (defun pgg-make-scheme-gpg ()
       (or pgg-scheme-gpg-instance
           (setq pgg-scheme-gpg-instance
     	    (luna-make-entity 'pgg-scheme-gpg))))

関数の名前は pgg-make-scheme- の後ろにバックエンド名を付加したものにしなければなりません。

バックエンドのメソッド
===========

各バックエンドには、これらのメソッドが存在しなければなりません。メソッドの実行結果のステータスを知らせなければならないので、メソッドの出力は特別なバッファーに保存されます (see Getting output)。

 -- Method: pgg-scheme-lookup-key scheme string &optional type
     STRING に関連付けられた鍵を返します。三番目のオプション引数 TYPE が非-nil だったら、秘密の鍵束から検索します。

 -- Method: pgg-scheme-encrypt-region scheme start end recipients &optional sign passphrase
     START と END の間の領域を RECIPIENTS 宛に送るものとして暗号化します。オプション引数 SIGN が nil でなかったら、署名と暗号化を同時に行ないます。暗号化に成功すると t を、失敗すると nil を返します。

 -- Method: pgg-scheme-encrypt-symmetric-region scheme start end &optional passphrase
     現在の START と END の間の領域を、共通鍵暗号 (symmetric cipher) とパスフレーズで暗号化します。暗号化に成功すると t を返し、そうでなければ nil を返します。この機能は現在 GnuPG だけで実装されています。

 -- Method: pgg-scheme-decrypt-region scheme start end &optional passphrase
     START と END の間の領域を解読します。解読に成功すると t を、失敗すると nil を返します。

 -- Method: pgg-scheme-sign-region scheme start end &optional cleartext passphrase
     START と END の間のテキストに署名します。三番目のオプション引数 CLEARTEXT が nil ではない場合、分離された署名を作りません。署名に成功すると t を、失敗すると nil を返します。

 -- Method: pgg-scheme-verify-region scheme start end &optional signature
     START と END の間の領域にある署名を検証します。三番目のオプション引数 SIGNATURE が nil でなかったら、その引数は現在の領域の分離された署名のファイルとして取り扱われます。署名が正しく検証された場合は t を、失敗すると nil を返します。

 -- Method: pgg-scheme-insert-key scheme
     ユーザーの公開鍵を取得して、それを ASCII 装甲の形式で挿入します。成功すると t を、失敗すると nil を返します。

 -- Method: pgg-scheme-snarf-keys-region scheme start end
     START と END の間の領域にある公開鍵を集め、ユーザーの鍵束 (keyring) に追加します。成功すると t を、失敗すると nil を返します。

出力を得る
=====

バックエンドメソッド (see Back end methods) の出力は特別なバッファーに格納されます。したがって、これらのメソッドは実行結果を伝える必要があります。

 -- Variable: pgg-errors-buffer
     PGP コマンド実行時の標準エラー出力は、このバッファーに格納されます。

 -- Variable: pgg-output-buffer
     PGP コマンド実行時の標準出力は、このバッファーに格納されます。

 -- Variable: pgg-status-buffer
     PGP コマンド実行時のその他の結果の情報は、このバッファーに格納されます。

OpenPGP パケットの解析
***************

OpenPGP のメッセージのフォーマットは、相互運用できるアプリケーション開発に必要なすべての情報を出力するように維持されています。その標準は RFC2440 に記載されています。

PGG は OpenPGP パケットに対応した独自のメッセージ解析を行ないます。

 -- Function: pgg-parse-armor string
     STRING 内のパケットの並びを list の形式で返します。

 -- Function: pgg-parse-armor-region start end
     START と END の間の領域にあるパケットの並びを list の形式で返します。

 -- Variable: pgg-ignore-packet-checksum
     nil でなかったら、パケットのチェックサムを検証しません。

GNU フリー文書利用許諾契約書
****************

訳注: 非公式な日本語訳 (http://www.opensource.jp/fdl/fdl.ja.html.euc-jp) があります。

     [file doclicense.texi not included]