← 暗号化のしくみに戻る
🔐 暗号化の技術仕様
Pushany のエンドツーエンド暗号化の方式、鍵の構成、サーバーが扱う情報を説明します。しくみの概要は暗号化のしくみをご覧ください。
2026年10月20日時点の実装に基づいています。
概要
- 暗号化と復号は、端末 (ブラウザ・PC の CLI) で Web Crypto API を使って行います。サーバー (Cloudflare Workers・D1・R2) は暗号文を保存・中継するだけです。
- 暗号化はオフにできません。ノート・トレイ・チェックリスト・タグ・ファイルは、端末で暗号化してから送信します。
- 暗号文には、どの項目のどの欄のものかを関連データ (AAD) として含めます。サーバーが別の項目・欄の暗号文に差し替えると、端末で復号できません。
- 暗号文と鍵の形式は、2 つの別々の実装 (TypeScript と Rust) と検証用のデータで、同じ結果になることを確かめています。
使っている方式
鍵の構成
復元キー (端末の中だけ)
├─ PBKDF2 ─→ 暗号化の鍵 (最初の版)
│ ├─ 自分の項目・タグ・ファイル・連絡先の表示名
│ └─ 共有していないチェックリストの鍵
├─ PBKDF2 (別の塩) ─→ 保護用の鍵
│ ├─ 暗号化の鍵の新しい版
│ ├─ 共有したリスト・ノートの鍵
│ ├─ 鍵ペアの秘密鍵
│ └─ 覚えた相手の安全番号
└─ PBKDF2 (別の塩) ─→ ロック付きノートの鍵 (PIN を忘れたとき用)
PIN + 保護用の鍵 + サーバーの乱数 ─→ ロック付きノートの鍵
└─ ロック付きノートごとの鍵
鍵ペアの公開鍵
├─ 招待で相手に渡すリスト・ノートの鍵
└─ エージェントが書いたもの
リスト・ノートの鍵
└─ チェックリスト・共有できるノート・ロック付きノートの中身
エージェントに内容の読み取りを許可している間は、サーバーが暗号化の鍵を保管します (サーバーで復号できる場合)。
暗号化の鍵の更新
- 暗号化の鍵には版があります。エージェントの読み取りの許可がなくなったとき (オフにした・期限が切れた) と、設定で「新しくする」を押したときに、端末が新しい版の鍵を乱数で作ります。
- 新しい版の鍵は保護用の鍵で暗号化してサーバーに保存し、ほかの端末と CLI はそれを受け取ります。保護用の鍵は暗号化の鍵から作れないため、前の版の鍵を持っていても、新しい版は復号できません。
- これから保存するものは、新しい版で暗号化します。連絡先の表示名・タグ・共有していないチェックリストの鍵は、その場で作り直します。ノート・トレイ・ファイルは、次に保存するときに新しい版になります。前に暗号化したものを読むため、前の版の鍵も端末に残します。
- サーバーは、前の版の鍵で暗号化したものの書き込みを受け付けません。
共有
共有したチェックリスト・ノートの中身は、リスト・ノートの鍵で暗号化します。この鍵は、メンバーごとに本人の保護用の鍵か相手の公開鍵で暗号化して渡すため、サーバーは復号できません (例外はサーバーで復号できる場合と守る範囲と限界)。
- 共有をはじめるとき — 新しいリスト・ノートの鍵を作り、中身を暗号化し直します。
- @名で招待 — 招待する端末が、相手の公開鍵でリスト・ノートの鍵を暗号化します。相手の端末は秘密鍵で鍵を取り出し、自分の保護用の鍵で暗号化し直して保存します。
- 安全番号 — 相手の公開鍵から作る 30 桁の数字です。端末は、最初に見た相手の安全番号を覚え、鍵を渡す前に今の公開鍵と比べます。違っていれば、鍵を渡さずに止めます。覚えた番号は保護用の鍵で暗号化してサーバーにも保存し、ほかの端末でも使います。共有の画面では、相手と自分の安全番号を表示します。自分の番号は、自分の秘密鍵から作ります。
- 招待リンク — URL の
# より後ろの秘密から作った鍵で、リスト・ノートの鍵を暗号化してサーバーに保存します。サーバーは秘密を受け取りません。リンクを知っている人は誰でも参加できます。有効期限は 7 日で、取り消せます。
- メンバーを外したとき — サーバーはその人の分の鍵を削除し、中身を取得できないようにします。外した端末が新しいリスト・ノートの鍵を作り、中身と履歴を暗号化し直して、残ったメンバーに渡し直します。前の鍵で暗号化した招待は暗号化し直し、招待リンクは削除します。ノートの添付ファイルの中身は暗号化し直さず、前の鍵を新しい鍵で暗号化して、ファイル名と種類と一緒に保存します。メンバーが自分で退出・退会したときや、すぐに作り直せなかったときは、オーナー・管理者・編集者の端末が次に開いたときに作り直します。
- オーナー権限を譲渡したとき — リスト・ノートの鍵は変わりません。メンバーはそれぞれの鍵のまま使い続けます。前のオーナーは管理者として残ります。
- ファイルの共有リンク — ファイルを乱数の鍵で暗号化したコピーをサーバーに保存し、鍵は URL の
# より後ろに載せます。パスワードを付けた場合は、パスワードから鍵を作ります。有効期限は 7 日です。
ロック付きノート
- ロック付きノートは、ノートごとの鍵で中身・履歴・添付を暗号化し、その鍵をロック付きノートの鍵で暗号化します。ロック付きノートの鍵は利用者に 1 つで、解錠している間だけ端末のメモリに置きます。
- ロック付きノートの鍵は、PIN から PBKDF2 (1,000,000 回) で作った値・保護用の鍵から作った値・サーバーの乱数から、HKDF で作った鍵で暗号化して保存します。
- サーバーは、PIN と保護用の鍵から作った確認用の値を持ち、合ったときだけサーバーの乱数と暗号化した鍵を返します。続けて 10 回間違えると、すべての端末でロックします。サーバーは保護用の鍵を復号できないため、PIN を総当たりできません。
- PIN を忘れたときのために、復元キーから作った鍵で暗号化したものも保存します。復元キーで PIN を設定し直すと、ロックも解けます。
- パスキーで解錠をオンにしたパスキーには、そのパスキーの PRF の出力から HKDF で作った鍵で暗号化したものも保存します。PRF に渡す値は暗号化の鍵のものとは別に作るので、パスキーで復号したときの値からは開けません。PRF の出力は端末の外に出ないため、サーバーは復号できず、総当たりもできません。試せる回数は、パスキーの保存先 (Face ID・指紋・端末のパスコード) が制限します。
- ロック付きノートは、エージェント・PC のエージェント・ショートカットには出さず、共有もできません。エージェントの読み取りの許可で保管した暗号化の鍵でも復号できません。
- ロックを外すと、中身・履歴・添付を暗号化の鍵で暗号化し直して、ふつうのノートに戻します。
新しい端末の承認
鍵のない端末 (B) に、鍵のある端末 (A) から暗号化の鍵と保護用の鍵を渡します。サーバーは中継するだけで、渡す鍵を復号できません。
- B が承認を求めると、アプリを開いているほかの端末に確認の画面が出ます。画面には、B の端末名・端末の種類・おおよその場所・日時を表示します。
- A で承認をはじめると、両方の端末が使い捨ての公開鍵を交換し、そこから 6 桁のコードを作ります。コードは B にだけ表示します。
- 利用者が B のコードを A で入力すると、A は端末の中で照合します。一致すれば、ECDH で作った鍵で渡す鍵を暗号化して送ります。一致しなければ要求を削除します。
- B は、受け取った鍵が正しいかを確かめてから保存します。承認したことはお知らせに残ります。
- 公開鍵は、先に値を固定してから見せる方式 (コミットメント) で交換します。サーバーが公開鍵をすり替えるとコードが一致せず、すり替えて同じコードになる確率は 1 回の要求につき 100 万分の 1 です。
- 要求は 10 分で無効になります。PC の CLI も同じ方法で承認します。
パスキー
設定で追加したパスキーで、ログインと暗号化の鍵の受け取りを一度に行えます。アカウントは Google・GitHub・X のどれかで作ります。
- 追加 — サーバーが作った使い捨ての challenge でパスキーを作り、応答 (attestation は none) をサーバーで確かめてから、パスキーの ID と公開鍵を保存します。同時に、PRF の出力から作った鍵で暗号化の鍵と保護用の鍵を暗号化して保存します。端末が送る応答には PRF の出力を含めず、含まれていればサーバーは受け付けません。
- ログイン — 名前を入れずに、保存先にあるパスキーを選びます。サーバーは challenge・origin・rpId・本人の確認 (UV)・署名・署名の回数を確かめ、パスキーが返した利用者 ID が持ち主と同じかも確かめます。ログインのたびに新しいログインのトークンを作ります。
- 鍵の受け取り — ログインと同じ 1 回で PRF の出力も受け取り、端末の中で暗号化の鍵と保護用の鍵を開きます。PRF の出力は端末のメモリにだけ置き、使ったとき・2 分たったとき・ログアウトしたときに消します。QR コードでほかの端末のパスキーを使うと PRF の出力が違うことがあり、そのときはログインだけを行います。
- 削除 — パスキーを削除すると、そのパスキーでのログインもサーバーで無効にします (削除した端末のログインは残ります)。追加とログインはお知らせに残ります (端末の種類とおおよその場所)。
サーバーに保存するもの
暗号化して保存するもの
本文・タイトル・URL・タグ・ファイル名と種類・ファイルと添付の中身・リストの名前・色・アイコン・期限・メモ・セクション名・項目の文字とメモ・連絡先の表示名・覚えた相手の安全番号・タグの定義・ノートとリストの履歴の文字。
平文で保存するもの
並び替え・絞り込み・通知・共有に使うため、次のものは暗号化しません。
このほかの通信の記録などは、プライバシーポリシーをご覧ください。
サーバー・運営者が見られないもの
- 上の「暗号化して保存するもの」の内容
- 復元キー
- 暗号化の鍵 (下の例外を除く)
- 保護用の鍵・秘密鍵・リストとノートの鍵 (下の例外を除く)
- ロック付きノートの PIN と鍵
- 招待リンク・共有リンクの
# より後ろ
サーバー・運営者が見られるもの
- 上の「平文で保存するもの」
- 暗号文の大きさと、書き込みの日時・回数
- 誰と何を共有しているか
- 下の「サーバーで復号できる場合」の内容
サーバーで復号できる場合
- エージェントの「内容の読み取りを許可」 — どれかのエージェントで許可すると、端末が暗号化の鍵 (すべての版) をサーバーに送信します。サーバーはサーバーの秘密の鍵で暗号化して保存し、エージェントが読み書きするたびに復号して使います。この間は、運営者が暗号化の鍵を保管している状態です。許可は、エージェントが 14 日間使わないか、許可してから 90 日たつと自動でオフになります。許可したエージェントがなくなると、サーバーは鍵を削除し、端末が暗号化の鍵を新しくします。
- この間にサーバーが復号できるのは、暗号化の鍵で暗号化したもの (共有していないノート・トレイ・ファイル・チェックリスト、タグ、連絡先の表示名) です。共有したリスト・ノートとロック付きノートは、この鍵では復号できません。
- 共有の「エージェントに内容の読み取りを許可」 — 共有したリスト・ノートで、オーナーか管理者がオンにすると、オンにした端末がそのリスト・ノートの鍵をサーバーに送信します。サーバーはサーバーの秘密の鍵で暗号化して保存し、内容の読み取りを許可しているメンバーのエージェントが読み書きするたびに復号して使います。この間は、運営者がそのリスト・ノートの鍵を保管している状態で、中身・履歴・添付ファイルを復号できます。エージェントが書くものは、リスト・ノートの鍵で暗号化します。エージェントが 14 日間使わないか、オンにしてから 90 日たつと自動でオフになります。オフになると、サーバーは鍵を削除し、メンバーの端末がリスト・ノートの鍵を作り直します。オン・オフはメンバー全員のお知らせに表示し、オンのものは見出しに印を出します。
- エージェントが書いたもの — サーバーは受け取るとすぐに本人の公開鍵で暗号化し、平文は保存しません。端末がアプリを開いたときに取り込みます。エージェントに伝えた内容は、エージェントの側に残ります。
- エージェントの「名前を表示するリスト」と、共有の「名前をエージェントに表示」 — 選んだリストの名前は、エージェントが指定できるように平文で保存します。共有しているリストでは、オーナーと管理者がオンにした場合だけ保存し、メンバー全員のエージェントが名前で指定できます。オン・オフはメンバー全員のお知らせに表示し、オンのものは見出しに印を出します。オフにすると平文の名前を削除します。
- ショートカット — ショートカットから送信したものは、暗号化されずにサーバーに届きます。テキストと URL は、サーバーが受け取るとすぐに本人の公開鍵で暗号化し、平文は保存しません。端末がアプリを開いたときに取り込み、暗号化の鍵で暗号化し直します。鍵ペアをまだ作成していない場合は平文で保存し、端末があとで暗号化します。ファイルは暗号化しません。PC のエージェントも API キーを使いますが、PC で暗号化してから送信します。
- 暗号化を有効にする前に保存したもの — テキスト・リンクとノートの履歴は、暗号化の鍵がある端末が、開いたとき・編集したときと、アプリを開いている間に少しずつ暗号化します。ファイルと添付ファイルは暗号化しません。
- お問い合わせ・通報 — 運営者が読むためのもので、暗号化しません。
端末に保存するもの
- 暗号化の鍵 (すべての版) と保護用の鍵は、ブラウザの IndexedDB に保存します。端末の承認でほかの端末に渡すため、取り出せる形の鍵です。ロック付きノートの鍵は保存せず、解錠している間だけメモリに置きます。ロック付きノートの中身は、検索の索引にも保存しません。
- 検索は端末の中で行います。検索の索引 (復号した本文・タイトルなど)・電波がないときの送信待ち・一覧のキャッシュ・下書きは、端末に平文で保存します。
- 別の利用者でログインしたときや、ログインが切れたときは、これらをまとめて削除します。
- 「この端末に鍵を保存しない」をオンにした端末 (共用の端末向け) では、上の鍵・検索の索引・送信待ち・一覧のキャッシュ・下書きと、覚えた安全番号・最近使ったタグ・作成した共有リンク・前回の自分の情報を端末に保存せず、開いているタブのメモリにだけ置きます。タブを閉じると消えるため、開くたびに承認・パスキー・復元キーのどれかで鍵を受け取ります。Service Worker は鍵を読めないため、通知に内容は表示しません。端末に保存するのは、オンにしたことだけです。ログインの Cookie は期限の無いもの (ブラウザを閉じると削除される) にし、サーバーでは最後に使ってから12時間でログインを無効にします。オンにしたときは、ログインのトークンも新しくします。
- PC の CLI は、API キーと鍵を設定ファイルに暗号化せずに保存し、本人だけが読み書きできるようにします。
守る範囲と限界
- 検知しない差し替え — 暗号文の書き換えと、別の項目・欄の暗号文への差し替えは検知します。同じ欄の古い暗号文への巻き戻し、項目の削除や並べ替え、タグの定義どうしの入れ替え、同じノートの中での添付の並べ替えは検知しません。
- AAD のない暗号文 — AAD を含めるようにする前に保存した暗号文は、どの欄でも復号できます。同じ鍵のこうした暗号文が残っている間は、ほかの欄の暗号文をこれに差し替えられても検知できません。アプリは項目を開いたときと裏で少しずつ、AAD を含めて暗号化し直します。それより前に追加したファイルの中身は暗号化し直さないため、AAD のないままです。
- 公開鍵で暗号化する形 — エージェントが書いたものとショートカットから届いたものは本人の公開鍵で暗号化するため、サーバーはチェックリストの項目やトレイ・ノートの中身に、任意の内容を書けます。
- 復元キーの総当たり — サーバーの情報を持つ人は、復元キーをオフラインで総当たりできます。アプリが作る 120 ビットのキーでは現実的ではありません。自分で決めたキーの強さはそのキー次第です。12 文字以上で、よくあるパスワードは使えないようにし、PBKDF2 を 1,000,000 回使います。
- ロック付きノートの PIN — 試せる回数の制限は、サーバーでの確認によるものです。端末の保護用の鍵とサーバーのデータの両方を入手した人は、PIN をオフラインで総当たりできます。数字 6 桁の PIN は、現実的な時間で試せます。パスキーで解錠をオンにすると、パスキーを使える人 (端末のパスコードを知っている人を含む) は PIN なしで開けます。今あるノートにロックを付けたときは、前の暗号文がバックアップに残ります。
- パスキー — パスキーを使える人 (端末のパスコードを知っている人を含む) は、ログインと復号の両方ができます。ログインを奪った人はパスキーを追加でき、それでログインできます。追加はお知らせに残り、ほかの端末からログアウトしたあとにパスキーの一覧を表示するので、知らないパスキーは削除してください。
- 招待の公開鍵 — 招待で使う相手の公開鍵はサーバーから取得します。最初に見た安全番号と違えば鍵を渡さずに止めますが、最初に見た公開鍵がすり替えられていた場合は防げません。サーバーは覚えた番号を削除できるため、新しい端末やログインし直した端末でも同じです。相手と安全番号を見比べると、すり替えに気付けます。
- 端末の承認で確かめること — コードの入力で、サーバーによる公開鍵のすり替えと、コードを見ていない人による承認を防ぎます。ログインを奪った人に B のコードを伝えられて入力してしまうと防げません。端末名と端末の種類は B が送る値で、偽れます。場所は IP アドレスからの目安です。
- 配信するコード — Web アプリのため、端末で動くコードはサーバーから配信されます。サーバーが改ざんしたコードを配信する攻撃は防げません。
- 鍵の更新 — 復元キーを変更しても、暗号化の鍵と保護用の鍵は変わりません。暗号化の鍵は新しくできますが、それまでのデータは暗号化し直しません。保護用の鍵を新しくする機能はありません。
- エージェントの読み取りをやめたあと — 週に 1 回作成するデータベースのバックアップ (90 日保管) と、D1 の Time Travel (7〜30 日) には、削除する前の鍵の写しが残ります。写しとサーバーの秘密の鍵があれば、オフにする前のデータと、端末が鍵を新しくするまでに保存したものを復号できます。
- 共有の「エージェントに内容の読み取りを許可」をやめたあと — バックアップと Time Travel には、削除する前のリスト・ノートの鍵の写しが残ります。写しとサーバーの秘密の鍵があれば、オフにする前の内容と、メンバーの端末が鍵を作り直すまでに保存したものを復号できます。添付ファイルは鍵を作り直しても暗号化し直さないため、オフにする前からあった添付ファイルも復号できます。
- ほかのメンバーの設定 — 「エージェントに内容の読み取りを許可」は、オーナーか管理者がほかのメンバーの同意なしにオンにできます。お知らせで気付いて退出できますが、オンの間に保存されていた内容は、サーバーで復号できる状態になります。
- メンバーを外したあと — すぐに鍵を作り直せなかったときは、オーナー・管理者・編集者の端末が次に開くまで前の鍵のままのため、外した人は、暗号文を入手すればその間に保存した内容も復号できます。ノートの添付ファイルは前の鍵で暗号化したままのため、外す前からあった添付ファイルは、外した人が暗号文を入手すれば復号できます。外したあとに追加した添付ファイルは新しい鍵で暗号化します。
- 端末の中 — 端末に保存した鍵は取り出せる形のため、端末のマルウェアや開発者ツールから取り出せます。検索の索引・送信待ちも平文で端末にあります。「この端末に鍵を保存しない」をオンにしても、タブを開いている間は鍵がメモリにあります。ログインの Cookie はブラウザを閉じるまで残ります。前回開いていたページを開く設定のブラウザや、iPhone・iPad のホーム画面に追加したアプリでは、閉じたあとも残ることがあります。ブラウザが保存したパスワード・入力の候補は端末に残ります。
- メタデータ — 平文で保存するもののとおり、日時・件数・大きさ・共有の相手などは隠せません。