ニュース · Blackbearのセキュリティ
私たちにも読めないもの
Blackbearはローカルファーストです。すべての機能があなたのデバイスで動き、標準ではデータはそこにだけあり、サーバーは一切関わりません。
クラウド同期をオンにすると、私たちのサーバーが、あなたのデバイスのあいだや、あなたと大切な人たちのあいだでデータを運ぶようになります。このシリーズでは、それがあなたのプライバシーにとって何を意味するのかを説明します。Part 1では暗号化を取り上げます。何がデバイスの外に出て、なぜ私たちにはそれが読めないのか。Part 2は、私たちのサーバーが実際に持っているメタデータの正直な台帳です。Part 3では共有と共同編集を扱います。
以下に書くのは、意図ではなく、すでにリリースしているコードの説明です。アルゴリズムや数値を挙げているところは、すべて今日の本番環境で動いているものです。
暗号化はあなたのデバイスで行われる
同期する変更はすべて、ネットワークに触れる前に暗号化されます。ノート、ドキュメント、タスク、予定、ジャーナル、スプレッドシート、キャンバス、オーディオ、バージョン履歴。どれもXChaCha20-Poly1305という認証付き暗号で封をされ、その鍵が保護されないままデバイスの外に出ることはありません。私たちのサーバーが受け取り、保存するのは暗号文だけです。
画像やオーディオファイルも同じです。デバイス上で暗号化され、中身の見えないデータとしてアップロードされます。
これをすべて担うコードは、RustCryptoエコシステムの上に作られ、WebAssemblyにコンパイルされた、ただひとつのRust実装です。アプリとBlackbear CLIはこれを1バイトたりとも違わず共有しており、言語をまたいだテストデータで検証することで、第2の実装がひそかにずれていくことを防いでいます。
守れるもの、守れないもの
暗号化は特定の目的のための道具であって、万能のバリアではありません。詳しい話の前に、まずその境界を示します。
この設計が守るもの:
- サーバーやデータベースへの受動的な侵害、つまり保存データの盗難。漏れるのは暗号文と、包まれた鍵だけです。
- 私たち自身。本番環境のシステムが、あなたのコンテンツの鍵や平文を受け取ることはありません。そのため、あなたのコンテンツに法的な開示要求があっても、渡せるのは実際に持っているもの、つまりメタデータ(Part 2)と封をされたデータだけです。
守れないもの:
- 乗っ取られたデバイス、盗まれたデバイス、ロックを解除したままのデバイス。鍵を持っているのはあなたのデバイスです。その安全性が、ほかのすべてを支える土台です。
- あなたのパスフレーズや、12個のリカバリーワードを知っている人。
- 共有した相手が、受け取ったものをどう扱うか。共有とは、数学だけでなく人への信頼です。
- 通信のメタデータ:誰が、いつ、どれだけ。それがPart 2のテーマのすべてです。
- アプリそのもの。Webでは、アプリは読み込むたびに私たちのサーバーから届き、デスクトップでは署名付きのリリースとして届きます。誰が配布したものであれ、悪意あるアプリに耐えられる暗号方式はありません。
- あなたが自らデータを平文で外に送るとき。Paxにクラウドのモデルを使わせる、外部のカレンダーを接続する、ファイルを書き出す、招待をメールで送る。これらは、あなたが選んだ相手に意図して届けられ、私たちの暗号化ではなく、その相手のポリシーに従います。
鍵の階層
パスフレーズがあなたのデバイスの外に出ることはありません。すべてはそこから生まれます。
- パスフレーズは、メモリハードな鍵導出関数Argon2idに通されます。設定は64 MiBのメモリ、3回のパス、4つのレーンです。そこからアカウントキーが生まれます。
- アカウントキーは、デバイス上で生成されたランダムな256ビットの鍵であるボールトキーを包みます。実際にデータを暗号化するのは、このボールトキーです。
- 私たちのサーバーに保存されるのは、包まれたボールトキー、ソルト、そして設定のパラメータです。包まれた鍵そのものが暗号文であり、パスフレーズがなければただのノイズです。
サーバーに保存されるのは包まれたコピーだけ。暗号文を守る暗号文です。
なぜ間にもう一段階挟むのでしょうか。そうすれば、あなたの暮らしのすべてを暗号化し直さずにパスフレーズを変更でき、玄関の鍵を弱めることなく復旧の手段も用意できるからです。
ここははっきり書いておきます。Argon2idは推測を高くつかせますが、弱いパスフレーズを強くすることはできません。包まれたボールトキーの強さは、それを包むパスフレーズの強さそのものです。長いものを選んでください。
復旧は12個の単語で
同期を設定すると、Blackbearはリカバリーフレーズを発行します。128ビットのエントロピーを表す、12個の英単語(BIP39)です。そこから独立した鍵が導かれ、ボールトキーをもう一度包みます。
パスフレーズを忘れても、12個の単語があれば戻れます。両方を失えば、同期したデータは失われます。私たちにはリセットできず、サポートへの問い合わせでどうにかなるものでもありません。私たちの側には、リセットできるものが何もないからです。これはサポートの不備ではありません。設計がきちんと機能している証拠です。
デバイスを追加する
新しいデバイスでは、パスフレーズを入力します。そこからアカウントキーが手元で導かれ、サーバーにある包まれたコピーからボールトキーが取り出されます。サーバーがパスフレーズを見ることも、その結果を見ることもありません。
ロックを解除した既存のデバイスから、鍵を直接渡すこともできます。ボールトキーを新しいデバイスのX25519公開鍵に対して封をし、使われても使われなくも5分後に自動で消える受け渡し用の場所に置きます。ここには正直に言うべき境界がひとつあります。既存のデバイスは、サインイン中のアカウントを通じて新しいデバイスの公開鍵を知るため、この補助的な方法では、あなたが選んだデバイスの正しい鍵を私たちのサーバーが中継することを信頼しています。パスフレーズを使う方法には、そのような信頼は必要ありません。
こうした言葉はフィッシング詐欺にそのまま流用されかねないので、ここではっきり書いておきます。私たちがあなたのパスフレーズやリカバリーワードを尋ねることはなく、デバイスの受け渡しを承認するよう求めることもありません。そうした確認が出るのは、あなたが自分で開いたアプリの中だけです。それ以外から求められたら、それは攻撃です。
メッセージ
メッセージには、同期とは別の専用の鍵を使います。各アカウントはメッセージ用のX25519のIDを持ち、メッセージごとに新しいソルトからHKDF-SHA256で固有の鍵を導きます。メッセージは封をされた封筒として運ばれます。サーバーはそれを中継しますが、開けることはできません。封筒の外側から何がわかるのかはPart 2で説明します。
設計についてひとつ、はっきり言っておきます。メッセージごとの固有の鍵は、一部のメッセンジャーが使う、鍵を更新し続けるラチェット方式ではありません。もしデバイスの長期的なメッセージ用の鍵が漏えいすれば、その鍵に対して封をされたメッセージは危険にさらされます。メッセージごとの鍵は被害の範囲を狭めますが、前方秘密性ではありません。その違いは知っておいてほしいと考えています。
内容の指紋を残さない履歴
バージョン履歴は、あなたのボールトの中だけで通用するIDで指定される、暗号化されたスナップショットとして同期されます。あなたと見知らぬ誰かがまったく同じファイルを保存しても、サーバーには無関係な2つのIDしか見えません。同じ中身をアカウントをまたいで照合することはできないのです。ただし、ほかの同期の通信と同じく、サイズとタイミングは見えます。それはメタデータであり、Part 2のテーマです。
明かさずに証明する
アカウントに対する取り返しのつかない操作には、ボールトの証明が必要です。ボールトキーから導かれたEd25519鍵による署名です。ボールトそのものをどこにも送らずに、ボールトを持っていることを証明できます。そして、メモリ上で役目を終えた鍵はゼロで消去されます。
どれも特別なものではありません。XChaCha20-Poly1305、Argon2id、X25519、Ed25519、HKDF-SHA256。いずれも標準的で地味で、徹底的に検証されてきたプリミティブです。大切なのは、それをあらゆる場所に適用し続ける規律と、それらが守れないものをはっきり口にする規律です。このシリーズの残りは、その規律についての話です。
参考文献
- Local-first software — この考え方の土台となったInk & Switchの論考
- RFC 9106 — Argon2の仕様
- XChaCha20-Poly1305 — IETFの仕様草案
- RFC 7748 — X25519の土台となる楕円曲線
- RFC 8032 — Ed25519署名
- The Password Hashing Competition — Argon2が優勝したコンテスト
Blackbearのセキュリティ
- 1. 私たちにも読めないもの (この記事)
- 2. サーバーに見えるもの
- 3. 共有しても封をしたまま