パスキー(Passkey)は、パスワードの代替として設計された公開鍵認証方式です。
ユーザー体験としては「生体認証やPINでログインする仕組み」ですが、実際の認証基盤は 公開鍵暗号によるチャレンジレスポンス方式です。
本記事では、パスキーを実装する上で理解しておくべき仕様・安全性の根拠・設計上の注意点を整理します。
パスキーの仕様
パスキーは、FIDO Alliance が策定した FIDO2 規格に基づいています。
FIDO2は主に以下の2仕様で構成されます。
1. WebAuthn(Web Authentication API)
W3C が標準化したブラウザAPIです。
役割:
- ブラウザとサーバ間の認証インターフェース
- 公開鍵クレデンシャルの登録(Registration)
- 署名による認証(Authentication)
- challengeの受け渡し
- 署名検証に必要なデータの生成
実装対象は:
- フロントエンド(
navigator.credentials) - サーバ側の検証処理
2. CTAP2(Client to Authenticator Protocol 2)
CTAP2は、クライアント(PC・スマートフォン)と認証器の通信仕様です。
認証器の例:
- YubiKey
- OS内蔵の認証器(Windows Hello / Touch ID など)
役割:
- 鍵ペアの生成
- 秘密鍵の安全な保持
- 署名生成
- ユーザー確認(生体・PIN)
FIDO2の基本原理
- デバイス側で鍵ペアを生成
- 公開鍵のみをサーバに保存
- 認証時にサーバがchallengeを発行
- デバイスが秘密鍵で署名
- サーバが公開鍵で検証
重要なのは:
生体認証は「秘密鍵操作のロック解除手段」であり、認証そのものではない
実際の本人性確認は、秘密鍵による署名生成です。
何故安全か
1. サーバに秘密情報を保存しない
サーバは公開鍵のみ保持します。
パスワードのような共有秘密は存在しません。
データベースが漏洩しても、攻撃者はログインに必要な秘密鍵を取得できません。
2. チャレンジレスポンス方式
毎回ランダムなchallengeを発行し、それに署名させます。
これにより:
- リプレイ攻撃が成立しない
- 過去の通信の再送が無効
challengeは使い捨てでなければなりません。
3. ドメイン拘束(フィッシング耐性)
公開鍵はRP ID(ドメイン)に紐づいて生成されます。
- 正しいドメインでのみ署名可能
- 偽サイトでは署名生成不可
この性質により、パスキーはSMS認証やTOTPよりも高いフィッシング耐性を持ちます。
4. クローン検知(signCount)
認証器は署名回数カウンタ(signCount)を保持します。
サーバは前回値と比較し、
- 値が減少していればクローンの疑い
を検出できます。
シーケンス例
ユーザー登録
ログイン
設計する上での注意点
1. challenge管理は厳密に行う
要件:
- 暗号学的乱数(32byte以上)
- サーバ保存
- 有効期限設定(1〜5分)
- 使用後は削除
マルチインスタンス構成ではRedis、DynamoDB等を利用します。
2. origin と rpId (ドメイン)を必ず検証する
検証必須:
clientDataJSON.originrpIdHash
これを怠ると、フィッシング耐性が失われます。
3. credentialIdの逆引き設計
ユーザー名を入力しないログイン(Discoverable Credential)では:
credentialId → userId
の検索が必要です。
DynamoDB等では、credentialIdに対するGSIを設計しておく必要があります。
4. 複数Credential前提で設計する
1ユーザーに対して:
- PC
- スマートフォン
- セキュリティキー
- 同期型パスキー
複数登録が前提です。
DBは1対多構造にします。
5. userVerificationはrequired推奨
userVerification: "required"
とすることで、生体またはPINを必須化できます。
6. アカウント復旧設計
端末紛失時の対策を必ず設計します。
例:
- 複数パスキー登録
- 管理者承認フロー
- バックアップ認証手段
復旧設計なしの完全パスキー化はリスクがあります。
7. HTTPS必須
WebAuthnはSecure Contextのみ動作します。
- 本番はHTTPS必須
- localhostのみ例外
実装時の技術的ポイント
使用ライブラリ
Node.jsでは:
の利用が推奨されます。
理由:
- COSE鍵処理
- DER署名形式変換
- signCount検証
- 仕様差異吸収
を安全に処理できます。
まとめ
パスキーは単なる「便利な生体ログイン」ではなく、
公開鍵暗号に基づく堅牢な認証基盤です。
実装時に重要なのは:
- challengeの厳密管理
- origin / rpId検証
- credentialId逆引き設計
- 複数Credential前提のDB設計
- 復旧設計
これらを正しく設計して初めて、
パスキーは高いセキュリティと優れたUXを両立できます。
設計段階で仕様を正確に理解し、
実装時には検証処理を省略しないことが重要です。