前回、私はマスターパスワードがサーバに届かない仕組みを書きました (前記事のリンクは末尾に置いています)。書き終えた後、私の中に別の疑問が残りました。
「じゃあチームで同じパスワードを共有できているのは、どうやってるんだろう? 誰かが相手にパスワードを渡してるはずだ」
少し調べて、驚きました。誰も渡していません。サーバも、招待した側も、招待される側の相手のパスワードを知らないまま、共有が成立していました。
この記事では、その中身を2つの仕組みで解剖します。「各ユーザーが持つ RSA キーペア」と「Vault Key の鍵束モデル」です。
前回書いたこと: 2つの秘密は本人しか持たない
前記事の要点だけ引き出します。
1Password では、暗号化された金庫を開く鍵を Account Unlock Key (AUK) と呼びます。この AUK を、マスターパスワードと Secret Key の2つから導出します。この仕組みが Two Secret Key Derivation、通称 2SKD です。Secret Key はあなたのデバイス側でランダム生成された 128 bit で、サーバに一度も送られません。
認証は SRP と呼ばれるプロトコルを使います。マスターパスワードそのものをサーバに送らずに、「私はマスターパスワードを知っている」ことを証明します。
図にすると、こんな構造でした。
MP と Secret Key はクライアント側にしかなく、サーバに渡すのは「MP や Secret Key から復元できない値」(verifier や暗号化データ) だけ。この構造が前記事の核でした。
つまり:
- サーバは、あなたのマスターパスワードも Secret Key も持っていない
- 別のユーザーも、あなたのマスターパスワードも Secret Key も知らない
ここまでは、1人のユーザーの中で完結する話です。私が引っかかったのは次の疑問でした。「じゃあチームで Vault を共有しているとき、他のメンバーは何をもとにその Vault を開けているのか」
それでチーム共有が成立するのはなぜか
素直に考えると、何かの鍵の共有が必要な気がします。「Vault の鍵」をメンバー全員に配って、みんなが同じ鍵で金庫を開く。だとしたら、その配布のどこかで平文の鍵が誰かの手を渡るはずです。
しかし前記事のとおり、1Password は「相手のパスワードや鍵」の平文をやり取りしません。サーバも、他のユーザーもです。矛盾するように見えます。
答えは、対称鍵ではなく 非対称鍵 (公開鍵暗号) を使うことでした。前記事は「1人のユーザーが自分の金庫を開く」話 (対称鍵の設計) でした。今回は「複数ユーザー間で1つの Vault を共有する」話 (非対称鍵の設計) です。同じ 1Password の中で、認証層と共有層で別の暗号を使い分けています。
| 認証・自分のVault | チーム共有 | |
|---|---|---|
| 主役の暗号 | 対称鍵 (AUK, AES) | 非対称鍵 (RSA 公開鍵暗号) |
| 秘密の出所 | MP + Secret Key | 個人のキーペア |
| サーバの役割 | verifier 保管 | 公開鍵と暗号化データの中継 |
答え1: 各ユーザーはRSAキーペアを持っている
サインアップすると、あなたのクライアントは自分専用の RSA キーペアを1組生成します。
- 公開鍵: 誰でも見られる。サーバに平文で保存され、他のメンバーがダウンロードできる (RSA-OAEP 2048 bit)
- 秘密鍵: あなたしか使えない。AUK から導出される鍵で暗号化されてサーバに保存される
秘密鍵がサーバに置かれると聞くと、身構えるかもしれません。でも暗号化されているので、サーバは中身を復号できません。あなたがログインし (SRP で認証)、クライアント側で AUK を作って、そこで初めて秘密鍵が復号されます。
つまり、あなたの秘密鍵にアクセスできるのは、AUK を作れる人だけです。AUK を作れるのは、マスターパスワードと Secret Key の両方を知っている人。つまり、あなただけ。
秘密鍵の役割は1つだけです。「あなた宛に暗号化された Vault Key を復号する」こと。この Vault Key が何者かを次に見ていきます。
答え2: 鍵束モデルで1つのVault KeyをN人分暗号化する
チーム Vault のアイテム本体は、Vault Key と呼ばれる対称鍵 (AES) で暗号化されています。ここは Google Drive の共有ドライブと同じ発想で、中身は対称鍵で暗号化しておいた方が復号が速いからです。
問題は「その Vault Key をメンバー全員にどうやって配るか」です。
1Password はこう解いています。Vault Key を、メンバーそれぞれの公開鍵で個別に暗号化する。N 個の暗号化済みコピーを Vault に紐付けて保存する。
鍵束のイメージです。1つの Vault Key を、メンバー数だけコピーして、それぞれ違う公開鍵で暗号化する。誰かが自分の秘密鍵で復号すれば、平文の Vault Key が手に入ります。あとは Vault Key で AES 復号すればアイテムが読める。
通常のフローでは、サーバは平文の Vault Key を一度も見ません。鍵束はサーバに保存されていますが、鍵束の各エントリは公開鍵暗号で守られていて、対応する秘密鍵を持つ本人しか復号できません。「通常のフロー」と条件付きで書いた理由は、次の章に出てきます。
招待の実際: 誰が何を暗号化するか
桜井が相葉を Vault に招待するときのシーケンスを追ってみます。
桜井は「自分の秘密鍵」と「相葉の公開鍵」だけを触ります。相葉の秘密鍵は桜井に見せないし、桜井の秘密鍵も相葉に見せません。
サーバは、桜井がアップした「相葉用の暗号化 Vault Key」を保管し、相葉が取りに来たら渡すだけです。中身は相葉の秘密鍵でしか開けないので、サーバは配達員に徹しています。中身が読めない小包を運ぶ宅配業者、と考えるといいかもしれません。
これで新メンバーの追加が成立します。新メンバーが増えるたびに、いま Vault を持っている誰かが、その人用のエントリを作る。それを鍵束に追加する。それだけです。
素朴な疑問: 公開鍵は誰が保証しているのか
ここで素朴な疑問が湧きます。「サーバが相葉の公開鍵を差し替えて、サーバ自身が作った公開鍵を相葉のものとして桜井に渡したら?」
もしそうなれば、桜井は誤ってサーバの鍵で Vault Key を暗号化してしまいます。実質的に Vault Key がサーバに漏れる。よくある中間者攻撃 (MITM) の構図です。
私は最初「なにか強力な検証機構が入っているに違いない」と思って調べました。しかしホワイトペーパー Appendix C (mitm.html) に、こう書かれていました。
悪意ある、または侵害された 1Password サーバが偽の公開鍵をユーザーに返してきたとき、それをクライアント側で確実に検証する堅牢な方法は現時点で存在しない
つまり、この経路の MITM 耐性は「1Password のサーバ運用を信頼している」ところに依存しています。公式が緩和策として挙げているのは、trust hierarchy (信頼の階層) と user-to-user verification (ユーザー同士で公開鍵を突き合わせる) の2つ。ただしどちらも、いまはまだ実装されていません。
正直に書きます。「サーバも信じない」設計に見える 1Password でも、この共有層の一部は「サーバは約束どおりに動く」を前提にしています。前記事の 2SKD + SRP が守ってくれるのは「サーバがマスターパスワードを盗む」経路です。「サーバが公開鍵を差し替える」経路までは、いまのところ守り切れていません。ここは書きながら自分でも驚きました。
副産物: 退職とEmergency Kit
鍵束モデルには、実務家にとって嬉しい副産物と、いくつか注意点があります。
退職者のVault Key剥奪
退職者を Vault から外すとき、サーバは鍵束のその人のエントリを削除します。以降、通常の経路では彼らはサーバから自分用の暗号化 Vault Key を取れず、Vault にアクセスできなくなります。
ただし、ここは重要な但し書きです。これは暗号学的な剥奪ではありません。Vault Key そのものは変わらないからです。退職者が過去に Vault Key を復号済みでコピーしていた場合、そのコピーは有効なままです。ホワイトペーパー §Leopard (leopard.html) にも Removing someone ... isn't cryptographically enforced. Cryptographic keys are not changed. と明記されています。
完全に情報を隔離したい場合、公式が推奨しているのは「新しい Vault を作って、アイテムをそこに移す」方法です。新 Vault は新しい Vault Key を持ち、退職者は当然新 Vault の鍵束に含まれません。既存の Vault は消してもよいですが、退職者の手元にある古い Vault Key は無関係です。手間はかかりますが、これが公式の想定運用です。正直、ここまで回している組織はあまり見たことがありません。
Emergency Kit
サインアップ時に Emergency Kit が発行されます。Secret Key を紙で持ち出す仕組みで、マスターパスワードは任意で書き込みます。この記事の主題からは外れますが、注意点だけ。鍵束モデルは「他のメンバーが助けてくれる」設計ではありません。誰も相手のマスターパスワードを知らないからです。自分の秘密鍵を復元できるのは自分だけ、が大前提です。Emergency Kit を無くすと本当にアクセスできなくなります。
強いセキュリティは、強い運用ルールを要求する、というやつです。
まとめ
前回と今回で、1Password は2つの層で暗号を使い分けていることが見えました。
| 層 | 目的 | 暗号 |
|---|---|---|
| 認証・自分の Vault (前回) | 「私だ」の証明と自分専用の金庫 | 対称鍵 (AUK, AES) + SRP |
| チーム共有 (今回) | 相手の MP を知らずに Vault を渡す | 非対称鍵 (RSA 公開鍵暗号) |
「サーバも相手も、自分のパスワードを知らない」。前記事のこの性質を保ったまま、チーム共有まで通せています。2層の使い分けのおかげでした。
とはいえ、書きながら1つ気づきがありました。共有層の公開鍵検証は「サーバの運用を信頼している」ところに依存しています。暗号だけで自動的に MITM を止められる仕組みには、まだなっていない。1Password 自身がホワイトペーパーで「未解決」と書いているのは、正直好感を持ちました。過剰なマーケティングをしていない設計文書は貴重です。
私自身の疑問は解けましたが、次の疑問が残ります。trust hierarchy はいつ実装されるのか。新 Vault 移行の実運用コスト。Emergency Kit の紙をどう保管するか。この続きは、また別の記事で書くかもしれません。
みなさんのチームでは、退職者の Vault アクセスやパスワード交代の運用、どうしていますか? コメントで教えてください。
参考
- 1Password Security Design White Paper
- §Shared Vaults
- §Deeper look at keys
- Appendix C: MITM (公開鍵検証の未解決問題)
- §Leopard: Revoking access (退職者の暗号学的剥奪はできない件)
- 前回の記事: 1Passwordは、あなたのマスターパスワードを一度も受信していません
スライド版 (Docswell 13枚)
前後編を束ねた入門編を Docswell にまとめました。2SKD / SRP-6a / RSA キーペア / Vault Key 鍵束モデルの4つを俯瞰する構成です。
「サーバも自分も過度に信じない」前提でシステムを組み替える発想は、AI 連携プロトコルのセキュリティ設計でも共通です。より深く知りたい方は下記もどうぞ。