WebAuthnとCTAPが何をしてるか分かる解説


# はじめに
最近yahooに続いて[docomo](https://www.slideshare.net/FIDOAlliance/2019-fido-tokyo-seminar-idnttd)や[LINE pay](https://www.slideshare.net/FIDOAlliance/2019-fido-tokyo-seminar-line-payfido2)も対応を始めて段々と市民権を得ているFIDOですが、
実は仕様は公開されていて誰でもサーバーやクライアント、認証器を作る事ができます。

興味はあるけど、ちょっとよく分からないなという人のために解説をしたいと思います。

# 用語の定義

|用語|定義|
|---|----|
|WebAuthn|WebサイトがFIDOベースの認証システムでログインできるようにするためのプロトコル仕様|
|FIDOペースの認証|パスワードの代わりに公開鍵認証を使った認証の仕組み、ユーザーの利便性とセキュリティを高めるため、セキュリティーキーや生体認証と一緒に使われる|
|セキュリティキー|USBメモリのようなそれ自体が鍵となる認証器のこと 例)セキュリティードングルやYubikey|
|CTAP|認証器を持たないデバイスでもWebAuthnを利用できるようにするための外部認証器とのプロトコル仕様|
|認証器|CTAPプロトコルに対応したデバイス（大抵生体認証機能を持っている）|
|RPサーバー|正式名称：Relying Partyサーバー、WebAuthnに対応したセキュアなサービスを提供するサーバー|
|クライアント|WebAuthnを使ってRPサーバーへアクセスするノード|
|Credential|一般的にはユーザーIDとパスワードなどの認証を行うための情報であるが、WebAuthnの中では認証器が発行した公開鍵情報を指す|
|Attestation|Credential情報が改竄無く、信頼のおける認証情報だということを証明するための付加情報|

# FIDO2とWebAuthn、CTAPの関係

![スクリーンショット 2020-02-06 23.04.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200963/340e05c6-c267-e258-da9f-49d168bd0d94.png "スクリーンショット 2020-02-06 23.04.37.png")


FIDO2はWebAuthnとCTAPを包含した仕様全体を表します。

サーバーはWebAuthnだけで実装可能です。認証器も究極CTAPだけで実装可能です。

クライアントだけは認証器からCredential情報を受け取るためWebAuthnに加えてCTAPの仕様の理解が必要となります。

# WebAuthnは何をプロトコル化しているのか？

ざっくり言葉で説明すると、RPサーバーへのCredential情報の登録とそれを使った認証の2ユースケースをプロトコル化しています。
セキュリティーポリシー次第で手順の過不足はありますが、一般的には次のような流れで処理が行われます。

## 登録
- クライアントはFIDOベース認証を行いたいRPサーバに対してCredential情報登録の許可を尋ねます
- RPサーバーは要求を受け入れた場合、チャレンジ値と自分が受け付けるポリシーをクライアントに返します
- クライアントは認証器に対して自身の情報とRPサーバーからの情報、ポリシーを伝えてCredential情報を要求します
- 認証器は受け取った情報をもとにCredentialとAttestationを作成します
- クライアントは秘密鍵を除いたCredential情報とAttestationをサーバーへ送信します
- RPサーバーはAttestationを確認し、Credenital情報が問題なければ自身に登録します

Attestationという言葉を聞いたことのない方はよく分からないと思うかもしれませんが、
イメージとしては宅配便で宿泊先の鍵を郵送で受けとるとしたとき、
- 鍵 → Credential情報
- 鍵が信頼できるものだという情報が書かれた署名付きの説明書 → Attestation

## 認証
- クライアントはFIDOベース認証を行いたいRPサーバに対して認証の許可を尋ねます
- RPサーバーは要求を受け入れた場合、チャレンジ値と自分が受け付けるポリシーをクライアントに返します
- クライアントは認証器に対して自身の情報とRPサーバーからの情報、ポリシーを伝えて認証器内の秘密鍵を使った署名を要求します
- 認証器は受け取った情報をもとに署名を作成します
- クライアントは書名をサーバーへ送信します
- RPサーバーは事前に登録されたCredenital情報を使って署名の検証を行い、問題なければサービスを提供します

# シーケンスによる説明
いろいろな説明を見てきましたが、[FIDOアライアンス作成のスライド資料](https://www.slideshare.net/FIDOAlliance/fido-83445442)の図が一番分かり易かったです。

![スクリーンショット 2020-02-07 0.06.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200963/b31472f0-baca-73d5-976d-d3eb7f887079.png "スクリーンショット 2020-02-07 0.06.11.png")


## シーケンス情報の補足
- チャレンジ：サーバが発行するランダムなバイト列でAttestation作成時の味付けに使われる値
- ポリシー：作成時の暗号アルゴリズムやユーザーの所在確認をMUSTとするかなどの指定
- ポリシーの指定によっては発行された秘密鍵の保存場所が認証器内だったりクライアントだったりと変わることがある
- Attestationには信頼がおける認証器によって作成されたものであることを示すための署名が付けられる
- その署名については次の3パターンが存在する
	- 事前に共有した証明書の秘密鍵
	- 事前にした共有鍵に対応する秘密鍵
	- 認証用鍵ペア自身の秘密鍵（Self Attestation)
- どの方法で署名を付けるかは認証器次第
- YubikeyやTitanのような製品では証明書による署名が求められるが、社内システムレベルであればSelf Attestationでも十分（なはず）
- MDSと呼ばれるAttestationを検証するための証明書を登録するサーバが存在する
- RPサーバはその証明書をルート認証局に問い合わせることでAttestationの検証を行う

# WebAuthnを試したい
もしあなたが生体認証付のデバイスで最新のChromeを使っていたら[WebAuthn.io](https://webauthn.io)のページですぐに試すことができます。

尚、登録/ログインボタンの上のパラメータですが、サーバー側のポリシーを一部指定ができるようです。

### Attestation Type
|種類|意味|
|---|----|
|None|Attestationの署名はSelf Attestationで良い（第三者情報による検証をしないでOK）|
|Indirect|Attestationの署名は証明書などの第三者情報を使って欲しいが、Self Attestationでも良い|
|Direct|Attestationの署名は証明書などの第三者情報を使わないとダメ|


### Authenticator Type
|種類|意味|
|---|----|
|Unspecified|指定なし
|Cross platform|Yubikeyなどの着脱可能なものに限定|
|Platform(TPM)|Touch IDやWindows Helloなどのデバイス組み込みのものに限定|

# 最後に
自分が書きためたメモを起こしたので、間違いなどがあるかもしれません。
間違いがあった場合は指摘をお願い致します。

また、近いうちにCTAPのBLEプロトコルについて説明を投稿したいと考えています。