技術 約7分で読めます

PasskeysのPRF拡張をデータ暗号化の鍵導出に使ってはいけない

W3C WebAuthn Level 3仕様の共同エディターであるTim Cappalli(Okta Standards Architect、元Microsoft Identity Standards Team)が、PasskeysのPRF拡張を暗号化の鍵導出に使うのは危険だという警告記事を公開した。HNで100点超えの注目を集めている。Cappalliはpasskeys.devのメンテナーでもあり、WebAuthn仕様を書いている本人からの警告という重みがある。

PRF extensionの仕組み

WebAuthnのPRF(Pseudo-Random Function)拡張は、認証器から確定的な疑似乱数(32バイト)を取り出せる機能だ。同じ認証器・同じRP ID(通常はサービスのドメイン)・同じソルトの組み合わせなら、常に同じ出力が得られる。

プロトコル的には2つの層がある:

名称コンテキスト
WebAuthn API(ブラウザ)prf 拡張Webアプリケーション専用
CTAP2(認証器プロトコル)hmac-secret 拡張ネイティブアプリ + Web

WebAuthn PRFは、開発者が渡すソルトをそのまま使わず、ブラウザが内部でSHA-256変換をかける。これによりWebコンテキストで導出したシークレットが、ディスク暗号化等の非Web用途のシークレットと暗号的に分離される仕組みになっている。

この確定的な出力をデータ暗号化の鍵として使えるのではないか、というアイデアが広まっていた。認証とデータ保護を一つのPasskeyで完結させられるなら確かに便利に見える。

何が問題なのか

PRFの出力はCredential IDとRP IDに紐付いている。同じ認証器・同じドメインの組み合わせなら同じ鍵が得られる一方で、認証器が変わると鍵も変わる。

Cappalliは記事の中で、架空のユーザー「Erika」を使って典型的な事故シナリオを説明している:

  1. ErikaはあるサービスでパスキーのPRFを使ってバックアップデータを暗号化した
  2. 後日、クレデンシャルマネージャーを整理中にそのパスキーを削除した。暗号化に使われていたことは画面上のどこにも表示されていない
  3. 新デバイスで同じサービスにパスキーを新規登録したが、以前の認証器で導出した鍵は再現できない
  4. 亡くなった親族の写真やメッセージを含むバックアップが永久に復元不能になる

Cappalliの核心的な指摘はこうだ:

When you overload a credential used for authentication by also using it for encryption, the “blast radius” for losing that credential becomes immeasurably larger.

(認証用のクレデンシャルに暗号化の役割まで兼ねさせると、そのクレデンシャルを失ったときの「爆発半径」が計り知れないほど大きくなる)

認証クレデンシャルは置き換え可能だ。パスワードリセットや別のパスキー登録で回復できる。一方、暗号化鍵は置き換え不可能で、鍵を失ったらデータは永久に消える。パスキーを暗号化に使うと、「置き換え可能なもの」が「置き換え不可能なもの」に変わってしまう。ユーザーはパスキーをログインツールだと思っているが、実際には暗号化鍵として機能している。このメンタルモデルのずれが事故を生む。

Synced Passkeys vs Device-Bound Passkeysでのリスクの違い

Synced passkey(iCloud Keychain、Google Password Manager経由で同期されるもの)の場合、パスキーの秘密鍵素材がデバイス間で同期されるため、同じソルトを使えばPRF出力も同一になる。つまりPRFで導出した暗号化鍵は、同じパスキーにアクセスできる全デバイスで利用可能だ。

一方、Device-Bound Passkeys(YubiKey等のハードウェアセキュリティキー)の場合、PRF出力はそのデバイスに完全に拘束される。デバイス紛失 = 暗号化データへのアクセス永久喪失。

ここで厄介なのが、プラットフォームごとのPRFサポート状況がまだバラバラだという点:

プラットフォーム状態備考
Android安定Google Password Manager全パスキーでPRF対応
macOS 15+良好Safari 18+, Chrome 132+, Firefox 139+
iOS/iPadOS 18+バグありiOS 18.0-18.3でデータロスのバグ(18.4+で修正)
Windows 11限定的Windows Helloはhmac-secret非対応。外部セキュリティキーのみ
Firefox部分的Androidは非対応。macOS/Windowsはv139+で対応

2026年2月時点でもサポートが不完全なため、PRFをコア機能ではなく強化機能として扱うべきだという指摘がある。

PRFを暗号化に使っている実装

実際にPRFを暗号化に使っているサービスは既にいくつかある。

パスワードマネージャー系

  • Bitwarden: PRFでボールト暗号化鍵を導出し、マスターパスワードなしでのボールトアンロックを実現。32バイトのPRF出力をHKDFで64バイトに拡張し、RSA鍵ペアを介した3層暗号化アーキテクチャを構築している。複数パスキー対応済み。PRF非対応環境ではマスターパスワードにフォールバックする設計
  • Dashlane + Yubico: WebAuthn PRF拡張でYubiKeyが認証とボールトアンロックの両方を実行。主要クレデンシャルマネージャー初のFIDO2セキュリティキーによるボールトアクセスを実現
  • 1Password: 保存されたパスキーでPRFをサポートし、サードパーティアプリがパスキーでE2EE可能にするライブラリをオープンソースで公開

一般向けサービス

  • WhatsApp: 暗号化チャットバックアップのパスワード/64桁暗号化鍵の代替としてパスキーを追加。PRF拡張でパスキーから暗号化鍵素材を導出
  • Confer(Signal創設者のMoxie Marlinspike): E2EE AIチャットサービス。パスキーのPRF拡張から32バイトシークレットを導出し、ルート鍵素材として使用。サブ鍵を派生させてクライアントサイドで暗号化/復号し、暗号文はTEE(信頼実行環境)に送信して推論を実行する

パスワードマネージャー系はCappalliも「正当な用途」と認めている。これらは独自のリカバリ機構(マスターパスワード、リカバリーコード等)を持っているからだ。問題はWhatsAppやConferのような、パスキーPRFに暗号化を全面的に依存する設計。

推奨パターン: Envelope Encryption

PRFを暗号化に使う場合に推奨されるのがEnvelope Encryptionパターンだ:

[Data Encryption Key (DEK)] -- 実際のデータを暗号化
        |
[Key Encryption Key (KEK)] -- DEKをラップ(各認証器ごとに異なるKEK)
        |
[PRF出力 → HKDF → KEK導出] -- 各パスキー/セキュリティキーからKEKを導出

サーバーには暗号化ボールト + 各KEKでラップされた複数のDEKコピーを保存する。各認証器が独立してDEKをアンロックできるため、1つの認証器を失っても他の認証器からデータにアクセスできる。

PRF拡張は1回の認証で2つの異なるシークレットを導出可能に設計されており、旧ソルトと新ソルト両方のPRFシークレットを要求してアトミックに鍵ローテーションを行える。

やってはいけないアンチパターン:

  • PRF生出力を直接暗号化鍵として使用する(必ずHKDFを通す)
  • HKDFのinfoパラメータを省略する(目的バインディングがなくなる)
  • 単一認証器のみでの暗号化設計(Erikaのシナリオに直結)
  • 複数ユーザー/クレデンシャルに静的ソルトを使用する

HNの議論から見えるエコシステムの課題

HNスレッドで指摘されていた構造的な問題がいくつかある。

一つ目は、パスキーは「置き換え可能な認証クレデンシャル」として設計されているのに、PRFがそれを「置き換え不可能な暗号化鍵」に変換してしまう「カテゴリーエラー」だという指摘。ユーザーはパスキーを「ログインツール」として認識するため、削除に永久的な結果があると気づかない。WebAuthn仕様で「このパスキーは暗号化に使われている」というシグナルを出すべきだという提案が出ていた。

二つ目は、クレデンシャルマネージャー側がサービスのPRF使用状況を知る手段がないという問題。サービスとの常時通信なしでは、削除時に「このパスキーを消すとデータが消えます」という警告を出しようがない。

この問題に対し、CappalliとMatthew Miller(Cisco)が共同エディターを務めるW3C仕様「Well-Known URL for Relying Party Passkey Endpoints」では、prfUsageDetailsフィールドを定義している。PRFの使用方法を説明する情報ページへのURLを配置し、クレデンシャルマネージャーがパスキー削除時に警告を表示できるようにする仕組みだ。

{
  "enroll": "https://example.com/passkey/enroll",
  "manage": "https://example.com/passkey/manage",
  "prfUsageDetails": "https://example.com/passkey/prf-info"
}

なお、FIDO Allianceの「PRFを暗号化に使うな」という公式ガイダンスは現時点で存在しない。仕様自体はPRFを暗号化鍵導出に使うことを想定して設計されている。今回の記事はあくまでCappalli個人の警告/業界への提言という位置づけだが、WebAuthn L3仕様のエディター本人からの発信であり、その重みは軽くない。