新種の PGP 暗号化メール

no extension

今回はメモ代わりの記事なので文体がいつもと違うけどご容赦を。

拙作の BkGnuPG 絡みで, ある問い合わせを受けている。 どうやら, 相手から送られてくる暗号化メールが PGP/MIME (RFC3156, 日本語訳)とは異なるフォーマットになっていて上手く復号できないらしい。

通常 PGP/MIME では以下のようなフォーマットでメールが送られてくる。 (RFC3156 から抜粋)

From: Michael Elkins <elkins@aero.org>
To: Michael Elkins <elkins@aero.org>
Mime-Version: 1.0
Content-Type: multipart/encrypted; boundary=foo;
   protocol="application/pgp-encrypted"

–foo Content-Type: application/pgp-encrypted

Version: 1

–foo Content-Type: application/octet-stream

—–BEGIN PGP MESSAGE—– Version: 2.6.2

hIwDY32hYGCE8MkBA/wOu7d45aUxF4Q0RKJprD3v5Z9K1YcRJ2fve87lMlDlx4Oj eW4GDdBfLbJE7VUpp13N19GL8e/AqbyyjHH4aS0YoTk10QQ9nnRvjY8nZL3MPXSZ g9VGQxFeGqzykzmykU6A26MSMexR4ApeeON6xzZWfo+0yOqAq6lb46wsvldZ96YA AABH78hyX7YX4uT1tNCWEIIBoqqvCeIMpp7UQ2IzBrXg6GtukS8NxbukLeamqVW3 1yt21DYOjuLzcMNe/JNsD9vDVCvOOG3OCi8= =zzaA —–END PGP MESSAGE—–

–foo–

しかし, 件のメールはこのようになっていた。 (To/From や暗号化メッセージはもちろん偽物)

From: hoge <hoge@hoge.net>
To: hoge <hoge@hoge.net>
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Content-Type: application/pgp-encrypted
Mime-Version: 1.0

—–BEGIN PGP MESSAGE—– Version: GnuPG v1.2.3 (GNU/Linux)

hIwDY32hYGCE8MkBA/wOu7d45aUxF4Q0RKJprD3v5Z9K1YcRJ2fve87lMlDlx4Oj eW4GDdBfLbJE7VUpp13N19GL8e/AqbyyjHH4aS0YoTk10QQ9nnRvjY8nZL3MPXSZ g9VGQxFeGqzykzmykU6A26MSMexR4ApeeON6xzZWfo+0yOqAq6lb46wsvldZ96YA AABH78hyX7YX4uT1tNCWEIIBoqqvCeIMpp7UQ2IzBrXg6GtukS8NxbukLeamqVW3 1yt21DYOjuLzcMNe/JNsD9vDVCvOOG3OCi8= =zzaA —–END PGP MESSAGE—–

PGP/MIME の暗号文パートをそのまま本文に持ってきたような形である。 もちろんこれは RFC 違反なのだが, 何とかなりそうだと最初は感じた。

暗号化メールが2つのパートに分かれているのは RFC1847 に合わせているためだ。 RFC1847 では multipart/encrypted を制御鍵と暗号文の2つのパートに分けている。 しかし実際には OpenPGP (RFC2440, 日本語訳)では鍵と暗号文がひとつにパッケージングされているため, multipart/encrypted を使うのは冗長だという意見もあったらしい。 例えば S/MIME (RFC2311, RFC3851)では暗号化で multipart/encrypted は使わない(電子署名用に multipart/signed は使う)。 上記のフォーマットは S/MIME っぽい感じがしないでもない。

しかし, この予想は外れた。 曲がりなりにも PGP/MIME であるなら暗号文パートを復号した結果もまた MIME フォーマットでなければならない。 例えば最初の正しい例なら以下のようなカプセル化された構造になる。 (RFC3156 から抜粋。 & でマークした部分が暗号文の内容である)

   Content-Type: multipart/encrypted;
      protocol="application/pgp-encrypted"; boundary=foo

–foo Content-Type: application/pgp-encrypted

Version: 1

–foo Content-Type: application/octet-stream

—–BEGIN PGP MESSAGE—– & Content-Type: multipart/signed; micalg=pgp-md5 & protocol="application/pgp-signature"; boundary=bar & & –bar & Content-Type: text/plain; charset=us-ascii & & This message was first signed, and then encrypted. & & –bar & Content-Type: application/pgp-signature & & —–BEGIN PGP MESSAGE—– & Version: 2.6.2 & & iQCVAwUBMJrRF2N9oWBghPDJAQE9UQQAtl7LuRVndBjrk4EqYBIb3h5QXIX/LC// & jJV5bNvkZIGPIcEmI5iFd9boEgvpirHtIREEqLQRkYNoBActFBZmh9GC3C041WGq & uMbrbxc+nIs1TIKlA08rVi9ig/2Yh7LFrK5Ein57U/W72vgSxLhe/zhdfolT9Brn & HOxEa44b+EI= & =ndaj & —–END PGP MESSAGE—– & & –bar– —–END PGP MESSAGE—–

–foo–

件のメールでも(マルチパートの構造は崩れているとはいえ)同じような MIME の構造を期待していたのだが, 実際はただのテキストらしい。 要するに昔ながらの PEM 方式の暗号化メールの Content-Type を application/pgp-encrypted としているだけのようだ。 これの何が困るかというと暗号文の中身が何なのか復号するまで分からないということだ。 テキストかもしれないし BASE64 で符号化された octet-stream かもしれない。 いや, バイナリデータが素のまま入ってることも考えられる。 良心的にテキストであるとしても文字エンコーディングが分からない。 ここではたと困ってしまったのである。 いったいこんなメールをよこしてくれる MUA は何者だろう。 問い合わせをしてくださったかたもご存じないらしい。

更にこの一連の考察の中でもっとヤバい状況も思いついてしまったのだけど, 敢えてここには書かないことにしておく。