セキュリティ設計

スマホで封をして、
スマホで開きます。

投稿・写真・会話はスマホを出る前に封をされ、自分が選んだ人だけが開けます。誰と知り合いかはそれぞれのスマホが持ち、サーバーには保存しません。

01 封をする

開けられるのは
自分が選んだ人だけ

投稿すると、スマホが先に封をしてから送ります。サーバーは封をされた投稿を預かって届けるだけで、開ける鍵を持っていません。返信・写真・動画・リンクのプレビューも同じ道で行き来します。

投稿に封をして届けるまで:書いた人のスマホ、Krypton のサーバー、受け取る人のスマホ
  1. 書いた人のスマホが、セキュリティコアの中でこの投稿のためだけの新しいコンテンツの鍵をつくります。

  2. その鍵で文章と写真・動画に鍵をかけます。文章は、正確な長さがわからないよう決まった大きさまで埋めてから鍵をかけます。

  3. コンテンツの鍵を、受け取る人それぞれの暗号化の鍵で封じ、一人に一通ずつ封筒をつくります。書いた人自身の封筒も一通あります。

サーバーは暗号文と封筒を預かり、受け取る人に渡します。封筒を開ける鍵は受け取る人のスマホにしかないので、サーバーには開けられません。

  1. 受け取る人のスマホは、セキュリティコアの中で自分の封筒を開け、コンテンツの鍵を取り出します。

  2. その鍵で投稿を開き、画面に表示します。

サーバーにあるのは暗号文だけ
投稿・返信・写真・動画・リンクのプレビューは、サーバーに届く前にもう鍵がかかっています。
読む人ごとに封筒を一通
投稿の鍵は読む人ごとに別の封筒に入り、その封筒を開けられるのはその人のスマホだけです。
投稿ごとに新しい鍵
投稿と返信のたびに新しい鍵をつくります。ひとつの投稿の鍵で、別の投稿は開きません。
受け取る人は自分のスマホが決めます
スマホは、自分で持っているFamの名簿に向けて投稿に封をします。その名簿に入るのは、申し込みを受け入れた人か、QRコード・Famのリンクでつながった人だけです。自分が送ったFamのリンクは24時間以内に一度だけ使え、最初に開いた人が確認なしでFamになります — リンクを送ったことが同意です。

投稿はXChaCha20-Poly1305で鍵をかけ、封筒はX25519で封をしてペアの秘密の中に入れます。ペアの秘密はX25519とML-KEM-768を同時に使って共有します。

02 関係

誰と知り合いかは
スマホにだけ残ります

自分のFamの名簿はスマホで封をされ、サーバーは誰が誰を招き入れたかも、誰が誰に送ったかも保存しません。封をしたものは、どのアカウントにも結びつかない郵便受けを通って行き来します。ただしリクエストが届くその瞬間には、サーバーもIPアドレスと日時を見ており、それによって郵便受けがアカウントと結びつくことがあります。Kryptonチームが直接招き入れた人は、チームが招き入れたことがサーバーに残ります。

二台のスマホだけの秘密
ふたりがFamになると、二台のスマホはサーバーに見えない秘密を分け合います。ふたりの間で行き来するものは、すべてこの秘密で行き先が決まります。
アカウントではなく郵便受け
投稿・会話・名刺は、どのアカウントにも結びつかない郵便受けに入り、その番号は30日ごとに変わります。
送り主は封の中に
誰が送ったかは署名とともに封の中に入っていて、受け取ったスマホがその署名を確かめます。
記録に残らない招待
メンバーは、サーバーが中を見ずに発行した招待券を受け取ります。誰かが入るとき、サーバーはその券が本物かどうかだけを確かめます。保存された記録には誰が誰を招き入れたかはありませんが、接続の記録とその瞬間のリクエストからは分かります。

ふたりの秘密はX25519とML-KEM-768を同時に使って封をし、郵便受けの鍵はHKDF-SHA256で導き、送り主はEd25519で署名します。

03 鍵

鍵は
自分のスマホの中に

秘密鍵は、自分のスマホのセキュリティコアの中にあります。iPhoneとAndroidのアプリが共有するコアです。画面を描くアプリのコードにも、鍵は渡りません。

自分のスマホの中で鍵がある場所
自分のスマホ
Krypton アプリ
画面のコードJavaScript
  • 番号札(ハンドル)
  • 開いた投稿・写真

秘密鍵は渡りません

セキュリティコアRust
  • 四つの秘密鍵
  • コンテンツの鍵
キーチェーン・キーストア
  • 封をした秘密鍵
  • このスマホだけ
Krypton のサーバー
  • 公開鍵
  • 封をした取り戻し用データ
  • 取り戻し用の半分・検索値のハッシュ
このスマホだけに
iPhoneのキーチェーンかAndroidのキーストアに置き、バックアップでほかのスマホに移ることはありません。新しいスマホが鍵を受け取るのは、取り戻すときだけです。
アプリのコードには番号札だけ
コアはアプリに、鍵の代わりに番号札を渡します。番号札だけでは、アプリの外で何も開きません。
電話番号もメールもなしで
登録もサインインも、スマホにある鍵だけで行います。電話番号やメールアドレスは集めません。
広く使われる標準の暗号
自作の暗号は使いません。広く使われている標準を、RustのライブラリdalekとRustCryptoの実装で使います。
  • X25519
  • ML-KEM-768
  • Ed25519
  • XChaCha20-Poly1305
  • HKDF-SHA256
  • BIP39

04 取り戻す

スマホをなくしても
アカウントはそのまま

暗証番号を決め、英単語18個を紙に書き留めます。単語は登録時に受け取るか、あとから設定で作れます。新しいスマホで単語と暗証番号が合えば、アカウントが戻ってきます。

紙にだけある単語
18個の単語は作るときに一度だけ表示し、書いた単語をいくつか聞き返して確かめます。登録時でも、あとから設定でも作れます。単語はサーバーにもクラウドにもスマホにも残らず、再表示もしません。
単語と暗証番号の両方
単語だけでも暗証番号だけでも開きません。暗証番号は何度か間違えるとロックされ、サーバーは単語そのものではなく、単語から一方向に作った値のハッシュでアカウントを探します。
止められる時間
取り戻しは48時間待ってから完了します。その間、古いスマホはリクエストを見て取り消せます。
サーバーが持つものだけでは開きません
バックアップを開ける秘密は二つに分かれています。片方はサーバーに、もう片方は紙に書いた単語にあります。サーバーを丸ごと持ち去っても、単語がなければ開きません。

単語はBIP39標準の18語、192ビットです。量子コンピューターで総当たりしても2⁹⁶回が必要です。二つの半分はHKDFで合わせてバックアップを開きます。

05 通話

ふたりの間だけの
通話

Famと声で話します。声は二台のスマホの間で暗号化されて行き来し、通話履歴はそれぞれのスマホにだけ残ります。

かけられるのはFamどうしだけ
着信は封をされ、ふたりだけの郵便受けから鳴ります。サーバーは誰が誰にかけたかを記録しません。
発信者は受けるスマホだけが知ります
誰からの着信かは、受けるスマホが自分で開いて着信画面に表示します。サーバーは発信者の名前を知りません。
中継で隠すIPアドレス
通話はふだん中継サーバーを通ってつながります。中継サーバーはふたつのスマホのIPアドレスを見ますが、暗号化された音声は開けず、相手に自分のIPアドレスは見えません。スマホが中継の情報を受け取れないときはふたつのスマホが直接つながり、そのときはお互いのIPアドレスが見えることがあります。
二台のスマホが署名した接続
二台のスマホは接続情報にそれぞれの鍵で署名します。途中で何かが差し替えられれば、通話はつながりません。

接続情報は、それぞれのEd25519のアカウント鍵で署名します。

06 自分で決めること

何を見せるかは
自分で決めます

アプリをロックし、名刺を見る人を選び、画面に映したものは画面の中だけに。

アプリのロック
スマホの顔認証・指紋認証やパスコードでKryptonをロックします。すぐに、またはアプリを離れて1分・15分・1時間後に。オンのあいだは、アプリの切り替え画面にも中身は映りません。設定はこのスマホにだけ置き、サーバーはロックを使っているかを知りません。
名刺を見る人
名刺は封をしてあります。「Famのみ」か「全体に公開」を選べ、どちらでも元の写真はFamにだけ届きます。範囲を狭めると、スマホが新しい鍵で名刺に封をし直します。
スクリーンショットを防ぎます
Kryptonで見ている画面は、キャプチャも録画もできません。
消える投稿
消える投稿にすると、表示されてから24時間後に、投稿・会話・写真がまとめて消えます。

07 耐量子

量子コンピューターでも
破りにくく

暗号文をいまためておき、将来量子コンピューターで開ける攻撃があります。Kryptonは、自分が選んだ人に鍵を渡す外側の層で、いま実績のある暗号(X25519)と耐量子暗号(ML-KEM-768)を同時に使います。

両方を破らないと開かない
2つの暗号から得た秘密をひとつにまとめて封をします。片方に弱点が見つかっても、もう片方が守ります。SignalやiMessageが選んだのと同じハイブリッド方式です。
外側の層はすべて両方の暗号で
Famの申し込みとペアごとの秘密を共有するメモ、封をしたバックアップ、取り戻す方法、招待のパッケージ、通報など、鍵を渡す外側の層はすべて両方の暗号で封をします。ペアの郵便受けの中の投稿と会話は、こうして共有したペアの256ビットの秘密で包みます。
すり替えられない公開鍵
耐量子の公開鍵もアカウントの署名で結びつけます。サーバーや途中の誰かが別の鍵にすり替えると署名が合わず、スマホが受け取りません。
本文の鍵はそのまま強い
投稿や写真に鍵をかける256ビットのXChaCha20-Poly1305とSHA-256は、量子コンピューターに対しても十分な強さが残るため、変える必要がありません。

外側の層はX25519とML-KEM-768(米国NIST標準FIPS 203)を同時に使って封をし、2つの秘密はSHA3-256でひとつにまとめます。

まだ移行中のもの

  • 署名(Ed25519)はまだ耐量子ではありません。署名は偽造されても、過去の内容を開けることはできません。アカウントごとにML-DSA(FIPS 204)の署名鍵を登録時に作ってアイデンティティに結びつけてあり、実用的な量子コンピューターが現れそうになる前に、Ed25519と同時に使うよう切り替える計画です。
  • 匿名の招待は、量子コンピューターに対しても誰の招待だったかを隠し続けます。招待を偽造できないようにする部分は、署名と一緒に移行します。
  • 通話の音声は2台のスマホの間でWebRTC標準の暗号で鍵をかけており、この部分はまだ耐量子ではありません。

どのアプリにも守れないもの

  • 受け取った人が自分の写真アプリに保存した写真や、別のカメラで撮った画面
  • ロックを解いたままのスマホを受け取った人
  • 改造したアプリで、自分が受け取ったものを取り出す人
  • 通話の相手が別に行う録音
  • すでにマルウェアに乗っ取られたスマホ
  • ネットワークを見ている人が、IPアドレスと日時から郵便受け・通話・登録をアカウントに結びつけること — KryptonはリクエストをIPアドレスを隠す中継に通していません
  • 改変したアプリが端末で守るルールを無視すること — ブロックや手渡せる回数の上限のようなルールは受け取る人のアプリが守り、サーバーは止めません
  • 自分とFamのひとりとの間の秘密が漏れること — この秘密は時間がたっても変わらないため、サーバーに残るそのペアの封をしたメモ(最大90日)が開けられることがあります

詳しい技術説明は、GitHubで公開する予定です。