目次
背景
- 最近パスキーで認証するシステムを実装した
- パスワードを使わない公開非公開鍵方式でCryptみたいに便利だった
- その仕組みを整理した
パスキーとは
- FIDO Allianceの定義によれば、パスキーとは「FIDO標準に基づく認証情報で、スマートフォンやPC、またはハードウェアセキュリティキーに保存できるもの」
- 中身は公開鍵暗号の鍵ペア。パスワードのような「サーバーと共有する秘密の文字列」ではなく、デバイス側に秘密鍵を保持し、サーバー側には公開鍵だけを保存する方式
- ログイン時は、デバイスのロック解除と同じ操作(生体認証・PIN・パターンなど)で承認するだけで済む
公開鍵暗号を使った認証の仕組み
- WebAuthn(ブラウザが提供するAPI)の用語では、サービス側を「Relying Party(RP)」、ブラウザを「Client」、鍵ペアを生成・保管する側(スマートフォンやセキュリティキーなど)を「Authenticator」と呼ぶ
登録(Registration)
- ユーザーがアカウント登録・新しいパスキーの追加を行うと、ブラウザは
navigator.credentials.create()を呼び出す
| |
- Authenticatorが、そのRPに紐づく公開鍵・秘密鍵のペアを新しく生成する
- 秘密鍵はAuthenticator内に残り、外に出ることはない。公開鍵だけがRPに送られ、ユーザーアカウントに紐づけて保存される
- この際、Authenticatorが自分の正当性を証明する「Attestation(証明)」という情報も一緒に返されることがある
認証(Authentication)
- ログイン時は、ブラウザが
navigator.credentials.get()を呼び出す
| |
- RPがランダムな challenge(毎回変わる使い捨ての値)を発行する
- Authenticatorが、デバイスのロック解除などでユーザー本人であることを確認した上で、保存していた秘密鍵でそのchallengeに署名する
- RPは、登録時に保存しておいた公開鍵を使って、その署名を検証する。秘密鍵そのものはネットワーク上を一切流れない
なぜフィッシング耐性があるのか
- 署名の対象には、challengeだけでなく、RP ID(アクセス先のドメイン)も含まれる
- 例えば正規サイトが
acme.comだとして、攻撃者がacme-fake.comのようなフィッシングサイトを用意しても、Authenticatorはそのドメイン向けの署名を作ってくれない。署名がオリジン(ドメイン)に紐づいているため、別ドメインでは再利用できない - パスワードのように「人間がどのサイトにいるか勘違いして入力してしまう」という失敗がそもそも起こり得ない設計になっている
- Yubicoのデータでは、パスキーによってフィッシング・認証情報窃取へのリスクが99.99%減少するとされている
Discoverable Credential(Resident Key)
- 通常のWebAuthn認証では、RPが
allowCredentialsでcredential IDを指定する必要があるが、パスキーは「Discoverable Credential(かつてはResident Keyと呼ばれた)」という形式を使う - これは、RP IDさえ分かれば、Authenticator側に保存された資格情報を自分で見つけ出し、署名を生成できる方式
- この「Client-side Discoverable Credential」のうち、複数デバイス間で同期されるものが、一般に「パスキー」と呼ばれている
WebAuthn・FIDO2・CTAPの関係
- WebAuthnは、ブラウザが提供する、Webサイトから公開鍵認証を扱うためのJavaScript API(W3Cの標準)
- CTAP(Client to Authenticator Protocol)は、ブラウザ(Client)と、USBキーやスマートフォンなどの外部Authenticatorとの間の通信プロトコル
- WebAuthn + CTAPをあわせて「FIDO2」と呼ぶ。パスキーは、このFIDO2の標準をベースにした実装にあたる
デバイス間の同期
- パスキーの保存・同期方法には、大きく2種類ある
| 種類 | 内容 |
|---|---|
| 同期パスキー(Synced passkeys) | iCloudキーチェーンやGoogleパスワードマネージャーなどのクラウド経由で、同じアカウントの他のデバイスにも自動的に複製される |
| デバイス固定パスキー(Device-bound passkeys) | 特定の1台のデバイスやハードウェアセキュリティキーの中に留まり、クラウドには同期されない |
- 自分のスマートフォンにパスキーがあり、PC側にはまだ登録していない場合でも、FIDOのCross-Device Authenticationという仕組みで、Bluetoothによる近接確認を行った上で、スマートフォン経由でPC側のログインを完了できる
まとめ
- パスキーは、公開鍵暗号の鍵ペアをベースにした認証方式で、秘密鍵はデバイス(Authenticator)内に留まり、サーバー(RP)には公開鍵だけが保存される
- 登録(
navigator.credentials.create())でAuthenticatorが鍵ペアを生成して公開鍵をRPに渡し、認証(navigator.credentials.get())ではRPが発行したchallengeに秘密鍵で署名することで、本人確認が行われる - 署名がRP ID(ドメイン)に紐づいているため、フィッシングサイトでは署名が成立せず、パスワードと違って原理的にフィッシング耐性を持つ
- パスキーは、RP IDだけで資格情報を特定できるDiscoverable Credentialという形式をベースにしており、WebAuthn・CTAPをあわせたFIDO2標準の実装にあたる
- 同期パスキー(クラウド経由で複数デバイスに複製)とデバイス固定パスキー(1台に留まる)の2種類があり、Bluetoothによる近接確認を使ったデバイス間認証の仕組みもある
