しくみと本当の話
2つで1組の鍵
パスキーは、サイトごとに作る秘密鍵と公開鍵の1組です。秘密鍵はスマホの中にしまわれ、外に出ません。公開鍵はサイトに渡します。秘密鍵でしか作れない「署名」を、公開鍵で正しいかどうか確かめることはだれでもできますが、公開鍵から秘密鍵を計算で求めることは、いまのコンピューターでは事実上できません(楕円曲線 P-256 の離散対数問題)。
たとえるなら、秘密鍵はあなただけが持つ印鑑、公開鍵は印影を確かめる台帳。ただし本物の印鑑とちがって、署名は毎回ちがう文書(チャレンジ)の上に作るので、前の署名を写して使い回すことができません。
ログインで行き来するもの
① サイトが、毎回ちがうでたらめな数(チャレンジ。16バイト以上が望ましい)を送る。② ブラウザが、チャレンジといま開いているページの住所(origin)を書いた紙(clientDataJSON)を作る。③ スマホが、指紋・顔・PIN で本人を確かめてから、「どのサイトの鍵か(rpIdHash)・確かめたか(フラグ)・回数(カウンター)」と紙のハッシュに、秘密鍵で署名する。④ サイトが、保存しておいた公開鍵で署名を確かめ、チャレンジ・住所・サイト名も確かめる。
なぜ偽サイトに強いのか
パスワードは、偽サイトに自分で打ちこんでしまうと、そのまま盗まれます。パスキーでは、ブラウザが「いま開いているページの住所」を見て、そのサイトの名前の鍵しか使わせません。偽サイト(donguri-bamk.example)は本物(donguri-bank.example)の鍵を頼めず、署名の紙にも偽サイトの住所が書きこまれます。人が見分けなくても、しくみで止まります(NIST はこれを「検証者の名前に結びつける」フィッシング耐性と呼んでいます)。
指紋や顔はどこへ行く?
指紋・顔・PIN は、スマホの中で秘密鍵の使用を許すためだけに使われ、サイトには送られません。サイトに届くのは「確かめた(UV)」という1ビットの印だけです。
スマホをなくしたら
多くのパスキーは、iPhone・Android・パスワード管理アプリなどの同期で、同じ人のほかの端末にも入ります(端末どうしで暗号化して送る)。新しいスマホでも使えます。フラグの BE(同期できる)・BS(同期済み)がその印です。セキュリティキーのように1台から出ないパスキーもあり、なくすと使えなくなるので、予備を登録しておきます。
簡単にしたところ
鍵の作成・署名・検証・ハッシュ(SHA-256)・パスワードのハッシュ(PBKDF2)は、ブラウザの Web Crypto API で本当に計算しています。秘密鍵は「取り出せない」設定で作っていて、このアプリ自身も中身を読めません。
簡単にしたところ: 署名は本物では DER という形式ですが、ここでは r と s を並べた 64 バイトで見せます。登録のときの機種の証明(attestation)は「なし」。ユーザー名は tanuki に決めています。本物の通信は TLS(https)で暗号化されていて、ふつうは途中で読めません。「記録して使い回す」実験は、読めてしまったと仮定したものです。パスワードのハッシュの回数は、すぐ終わるように少なくしています(本物はもっと多い)。カウンターは使うたびに1ずつ増やしていますが、同期するパスキーでは 0 のままのことも多く、そのときサーバーはこの確認を飛ばします。サイトはすべて架空です(.example は例のための名前)。
おもな出どころ
このアプリについて
学習用に簡単にしたモデルです。ここで入れるパスワードは決まった例だけで、どこにも送りません(計算はすべてこのページの中)。本物のパスワードや個人の情報は入れないでください。
使っているもの: フォント Dela Gothic One・Zen Kaku Gothic New・IBM Plex Mono(Google Fonts、SIL Open Font License)。ライブラリは使っていません(ブラウザの Web Crypto API)。