ドキュメント本文へスキップ
ナレッジベース

エンドツーエンド暗号化

OpenPGP の鍵はブラウザー内で生成される。別の OpenEmail アドレス宛に送るメールは、タブを離れる前に封をできる。自分宛の封をされたメールは閲覧ペインで開き、復号は自分の端末上で行われる。鍵は当社のものではないため、引き渡すこともできない。

詳細

  • 送受信の両方が端から端まで接続されている。鍵を公開している宛先に対して作成すると、リクエストがブラウザーを離れる前に本文が封をされる。サーバーが受け取るのは読めない armor であり、それを pgp-mime として記録し、本物の multipart/encrypted メッセージを組み立てる。読むときは同じ流れが逆向きに走る。暗号文を取得し、タブ内で復号し、通常のメールとして描画する。
  • アルゴリズムは他のどこでも既に使われているものである。openpgp.js による OpenPGP で、通信路上は PGP/MIME である。鍵は Curve25519 上の v4 鍵で、Proton が発行するもの、および gpg が既定の最新アルゴリズムで生成するものと同じ形式である。したがって、ここで読めるメールは原理的に Thunderbird、gpg、Proton が生成するメールと同じであり、後で解きほぐす必要のある独自形式は一切ない。
  • ただし実際に使えるのは OpenEmail 同士に限られる。このコードベースには Web Key Directory も、キーサーバーへの照会も、Autocrypt ヘッダーの解析も一切ない。宛先の鍵が見つかる場所は当社自身のディレクトリだけであり、そこにはここでホストされているドメインのアドレスを持つ人がこのアプリから公開した鍵が収められている。自分の鍵を外部に渡す手段もない。アプリは公開鍵をそのディレクトリに公開するだけで、コピーも書き出しも提供していないため、Thunderbird を使う相手がそれを入手する方法は用意されていない。より広い PGP の世界との相互運用性は形式が持つ性質であって、現時点で製品が代わりに実現してくれるものではない。
  • 読む側にはこの制約がない。復号にディレクトリは不要だからである。このブラウザーにある鍵宛に封をされた PGP/MIME またはインライン PGP のメッセージであれば、送信者が誰で、どのクライアントを使っていても開ける。すでにローテーションして使わなくなった鍵宛に封をされたメッセージも含まれる。古い鍵はキーリングに残り、現在の鍵と併せて試されるため、ローテーションによって受信済みのメールが読めなくなることはない。
  • 緑は「開けた」という意味であり、他の経路で緑になることはない。Details → Security の行が緑になるのは、このタブで実際に復号して平文が返ってきた後だけである。メッセージ上のフィールドによってでも、暗号化されたエンベロープが届いたという事実によってでもない。表示は「Encrypted end-to-end. Opened with your key in this browser」となる。そこに至らない状態には、共通の文言ではなくそれぞれ専用の文がある。確認中、鍵がロックされている、このブラウザーが持たない鍵宛に封をされている、開けなかった、ここに鍵が1つもない、このブラウザーが参照を許可しなかった、である。「確認できなかった」と「鍵を持っていない」は別の主張であり、この行はどちらを受け取ったのかを必ず読ませる。
  • S/MIME は依然として開けない。これは X.509 証明書に基づく CMS であり、openpgp.js では扱えない。仮に扱えたとしても、鍵を保持する証明書ストアが製品内に存在しない。そのため S/MIME のメッセージには OpenEmail では開けない旨が表示され、何も起こらないロック解除が提示されることはない。
  • 秘密鍵はブラウザー内で生成され、決してそこから出ない。暗号化された形でも、バックアップの中でも、サポートツールの中でも出ない。サーバーに送られることはないため、ここには引き渡すものも、召喚に応じるものも、漏れるものもない。鍵はパスフレーズでロックされた状態で、専用の IndexedDB データベース openemail-keyring に保存される。これは「キャッシュを消してください」という案内やデバッグコンソールのリセットが届かない場所に意図的に置かれている。どちらもクエリキャッシュを消去するため、鍵をその隣に置いていれば、ありふれたサポート案内によって、そのアカウントが受信したすべての暗号化メッセージが永久に失われてしまう。アカウントを削除すれば鍵も削除される。その場合はメールも一緒になくなるからである。ロックを解除すると、無操作15分、最長でも8時間のあいだ鍵がメモリーに保持され、その後は次の封をされたメッセージを読む際に再びパスフレーズが求められる。
  • エスクローも復元手段も存在せず、これは未実装ではなく恒久的な仕様である。入口はパスフレーズだけであり、忘れてしまえば、自分宛に封をされたすべてのメッセージは、当社を含め誰も読めない暗号文として当社のサーバーに残る。メールは失われ、どれだけ問い合わせても取り戻せない。登録画面は最初の鍵が存在する前にこのことを説明し、チェックボックスへのチェックを求める。バックアップファイルの作成は必須であり、ダウンロードするまで Done ボタンは無効のままである。このファイルは、このブラウザーが使う追加の保存時保護なしで書き出される。これは意図的で、古い gpg のビルドでも読み込めるようにするためである。他の場所で開けないバックアップはバックアップではない。また、鍵は1台の端末の1つのブラウザーにしか存在しないため、スマートフォンや2台目のノートパソコンには、そのファイルを読み込むまで何もない。
  • ディレクトリが保持するのは公開鍵だけであり、鍵はメールボックスではなく人に属する。アドレスに紐づけた鍵は、そのアドレスを共有している全員のあいだで複製しなければならず、それは名前を変えたエスクローにほかならないからである。鍵の参照にはサインイン済みのセッションと送信権限が必要で、公開エンドポイントは用意していない。誰でも叩けるアドレス照会は、どのアドレスがここで実在するメールボックスかを誰にでも教えるオラクルになるからである。照会は「そのドメインはホストしていない」場合と「ホストしているが誰も鍵を公開していない」場合とで同一の応答を返す。両者を区別すれば、オラクルはなくなるのではなくログインの背後に移るだけだからである。また、鍵の提供が止まるのは、誰かが失効を思い出したときではなく、所有者がそのアドレスへのアクセスを失った時点である。
  • すべてのバイト列は書いた時点でブラウザー内で封をされる。遅延送信が成立するのはそのためである。予約されたメッセージや取り消し待機中のメッセージは暗号文として保存され、鍵を持たず中身を読めないキューによって後から送出される。ディレクトリ照会に失敗した宛先がある場合、鍵がないものとして黙って扱うのではなく、送信を中止する。また、封をされたメッセージは、メッセージを丸ごと運べる経路でしか送出されない。代わりに HTML 本文を受け取る送信経路では、armor がそのまま可視テキストとして投稿され、成功として報告されてしまう。そのため、そこへ流れる送信は1バイトも出る前に拒否される。
  • 封をすることのコストは、推測ではなく実測されている。armor は元のバイト数のおよそ1.86倍になるため、送信経路が許容する 5 MB には添付ファイル約 2.7 MB が収まる。作成画面は、転送側が拒否するものを数秒かけて暗号化する前に、この上限を超えるペイロードを拒否する。暗号化されたメールは開封もクリックも報告しない。宛先ごとのトラッキングは本文を人ごとに変えることで成り立つが、封をされた1つのブロックは変えられないからである。また、書き換えられたリンクは当社が読めるリンクであり、それはこの主張と正反対である。暗号化された送信は冪等性キーで重複排除することもできない。毎回新しいセッション鍵が使われるため、試行のたびに暗号文のバイト列が変わり、再試行が元の送信と同じ指紋にならないからである。
  • 予約送信では、送信時ではなく作成時に封をする。作成画面は、メッセージが送られる日ではなく、書いた日に宛先が持っている鍵に対して暗号文を組み立てる。これは、予約したメッセージが後から変わったものではなく承認した内容を運ぶという、この製品がテンプレートと翻訳にすでに適用している規則と同じである。違いは、古いテンプレートは単に内容が古いだけだが、古い鍵では読めないという点である。そのため作成画面は但し書きを添えるのではなく、日付を言葉で明示する。「Sealed now, sent on …. Everyone on it will need the key they have today.」もう一方を守る拒否処理は実装済みだが一度も発動していない。そのようなメッセージがまだ存在しえないからである。もし存在した場合、後からの編集は黙って許可されるのではなく拒否される。本文を書き換えれば暗号文の上に平文が書かれ、宛先を変えれば封をした相手が変わってしまい、いずれの場合も画面上は暗号化と表示されたまま平文で配信されることになるからである。
  • 作成画面がそもそも提供しないものが2つあり、通信の段階で失敗するのではなく、その旨をあらかじめ示す。テンプレートは公開済みのバージョンからサーバー側で描画されるため、このブラウザーに封をすべきものが存在しない。返信は下部に会話を引用するが、その引用は本文に封をした後で付け足されるため、スレッド全体の読める複製が封の外に残ってしまう。したがって、引用履歴を暗号文の内側に取り込めるようになるまで、返信と転送は暗号化できない。
  • これらはいずれも、件名、宛先、送信時刻を隠さない。封をされたメッセージでも、件名は他のメッセージと同じく平文で流れる。閲覧ペインはその旨をメッセージ上に表示する。「The subject and the addresses travelled in the clear; this text did not.」PGP が対象とするのは本文であり、それ以外を対象とする実装は存在しない。下書きにも封はされない。作成中は自動保存が平文をメールボックスに書き込み続けるからであり、黙って保存しなければ書いたものが失われるからである。鍵アイコンはこのことを言葉で開示する。
  • 封をされて届くメールを認識する仕組みが先に作られ、いまも有効である。以前は PGP/MIME、インラインの PGP armor、S/MIME はいずれも、本文が空で意味のない添付ファイルが2つ付いた状態で描画されていた。パーサーがプレーンテキストと HTML だけを読めるものとして扱い、残りを添付ファイル欄に落としていたためである。現在はこれらのパートが識別され、プロトコル上の付属物は添付ファイル一覧に入らず、暗号文はそのまま保存される。閲覧側は新たに何かを取得するのではなくこれを復号する。ここでは誰も開けないメッセージについては、その旨が率直に表示される。
  • 署名されたメッセージは別物として扱われる。実際に別物だからである。署名のみのメッセージは本文が読めるので、検索もルールもその他すべてがこれまでどおり機能する。鍵で閉ざされることはなく、復号処理にかけられることもない。この行には「Signed by the sender. Signature not checked」と淡色で表示され、ここで実際に署名を検証できるようになるまで淡色のままである。復号に成功したメッセージを含め、現時点で署名を検証するものは何もない。メッセージが封をされていると分かることと、それを開いたこととは別であり、開いたことと、誰が封をしたのかを知ることもまた別である。
  • 暗号化されたメッセージでは、本文を読むはずのすべての処理から本文が伏せられる。検索用の抜粋、フィッシング判定の本文パス、AI 作成の判定、ルールの本文条件、カレンダー招待の取り込み、スレッドの要約がこれにあたる。フィッシング判定のうち認証に関する部分は引き続き実行される。DMARC、DKIM、SPF は暗号文が隠さないヘッダーから読まれるからである。復号してもこれらは変わらない。平文はそれを開いたタブの中にしか存在しないため、封をされたメッセージは読んだ後も検索対象にならず、AI 機能の対象外のままであり、翻訳も提供されない。これは省略ではなく、この主張を成り立たせるためのコストである。