[PPAP撲滅] Web Key DirectoryでPGP鍵を配布し手軽にメールを暗号化(準備編)

2024年10月20日

サムネイル

皆さん, メールの暗号化はどうやって行っていますか?
まさかPPAPなんてしてないですよね?
もししてるなら, この記事を読んで早くPPAPから抜け出しましょう.

Web Key Directoryとは?

Web Key Directory(WKD)は, メールアドレスのドメインのHTTPSサーバーに鍵を置くことによって鍵を配信する方法です.
他の鍵配信方法として

配信方法 問題
公開鍵サーバー(keys.openpgp.orgなど)を使う 誰でもメールアドレスの所有者になりすまして鍵をアップロード出来る
最初のメールに公開鍵を添付する 最初のメールは暗号化できないし, 最初のメールを改竄されたら終わり
Web of Trustに頼る キーサインパーティーに参加する必要があり, 手軽ではない

などがあるものの, どれも問題があります.
WKDの場合は, 相手のメールサーバーを信用していいならば確実に1通目から暗号化することが可能です.

WKDに対応する

以下の手順は, メールアドレスがreimu@hakurei.win, PGP鍵のフィンガープリントが029BE97239D16F6A8B08151B8EBB335CB284FB75な場合を例とします.

ハッシュを計算する

メールアドレスのハッシュを計算します.

$ gpg-wks-client --print-wkd-hash reimu@hakurei.win
3xpxzdm4mk7a9pbnyqffyiwt38bnunpg reimu@hakurei.win

3xpxzdm4mk7a9pbnyqffyiwt38bnunpgがハッシュです.

公開鍵をエクスポートする

GnuPGのキーチェーンから使っている鍵をエクスポートします.
仕様書によると, ASCII armoredな鍵を返すべきではないとされているので, バイナリ形式でエクスポートします.
出力先のファイル名は, 前の手順で計算したハッシュにします.

$ gpg --export 029BE97239D16F6A8B08151B8EBB335CB284FB75 > 3xpxzdm4mk7a9pbnyqffyiwt38bnunpg

Webサーバーに公開鍵を設置する

ここに公開鍵を設置します.
https://hakurei.win/.well-known/openpgpkey/hu/3xpxzdm4mk7a9pbnyqffyiwt38bnunpg

また, ここに空のファイルを設置します.
無くても動くかもしれませんが, 仕様上必要ということになっています.
https://hakurei.win/.well-known/openpgpkey/policy

テスト

これでWKDへの対応は出来ているはずです, テストしましょう.

注意点として, Cloudflareなどを利用している場合はTorでもアクセス出来るようにしてください.
GnuPGが鍵を探すときにTor経由で通信を行うため, Torをブロックしているとエラーになります.

$ gpg --auto-key-locate wkd --locate-external-keys reimu@hakurei.win
gpg: 鍵8EBB335CB284FB75:"Charlie Root <reimu@hakurei.win>"変更なし
gpg:           処理数の合計: 1
gpg:               変更なし: 1
pub   ed25519 2023-08-01 [C]
      029BE97239D16F6A8B08151B8EBB335CB284FB75
uid           [  究極  ] Charlie Root <reimu@hakurei.win>
sub   ed25519 2023-08-01 [SA]
sub   cv25519 2023-08-01 [E]
sub   ed25519 2024-06-19 [SA]

処理数の合計: 1と出ていればOKです.

ちなみに

WKDでは正式な鍵のURLは
https://hakurei.win/.well-known/openpgpkey/hu/3xpxzdm4mk7a9pbnyqffyiwt38bnunpg?l=reimu
のように, クエリパラメータにl=に続けてメールアドレスのローカル部を書きます.
リンクを貼るときはこの形式で貼ると良いでしょう.

おまけ1: DNS CERT IPGPに対応する

DNS CERT IPGPとは, DNS上で鍵の在り処を公開するプロトコルです.
ついでなので出来るならこれも対応しておきましょう.

証明書を生成する

まず, 生成ツールをダウンロードしてください.
このツールは次のようにして使います.

$ python ipgp.py 029BE97239D16F6A8B08151B8EBB335CB284FB75 'https://hakurei.win/.well-known/openpgpkey/hu/3xpxzdm4mk7a9pbnyqffyiwt38bnunpg?l=reimu' reimu@hakurei.win
reimu.hakurei.win. 3600 IN CERT 6 0 0 FAKb6XI50W9qiwgVG467M1yyhPt1aHR0cHM6Ly9oYWt1cmVpLndpbi8ud2VsbC1rbm93bi9vcGVucGdwa2V5L2h1LzN4cHh6ZG00bWs3YTlwYm55cWZmeWl3dDM4Ym51bnBnP2w9cmVpbXU=

動作しない場合は, pythonコマンドがPython 2な可能性があるので, Python 3で実行してください.

DNS上に公開する

bindなどで自前のDNSサーバーを動かしている場合は, ツールの出力をそのまま貼り付ければ動くと思います.(未確認)
Cloudflareなどを使っている場合は以下のように設定します.

Cloudflareの設定

テスト

一応次のコマンドでテスト出来ます…が, 執筆時点で(開発版を除いて)最新のGnuPG 2.4.5ではバグがあるようで, 処理数の合計: 0と出て失敗します.

$ gpg --auto-key-locate cert --locate-external-keys reimu@hakurei.win

このバグは開発版のGnuPG 2.5.1で修正されたようです.

おまけ2: DNS PKAに対応する

これもまたDNS上で鍵の在り処を公開するプロトコルです.
簡単なので対応しちゃいましょう.

DNSレコードを追加する

reimu._pka.hakurei.winのTXTレコードに以下を追加します.

v=pka1;fpr=029BE97239D16F6A8B08151B8EBB335CB284FB75;uri=https://hakurei.win/.well-known/openpgpkey/hu/3xpxzdm4mk7a9pbnyqffyiwt38bnunpg?l=reimu

シンプルですね.