Yubikeyは、セキュアエレメント搭載のセキュリティーキーですが、
そういえばFIDOのU2Fには何件対応しているのだろう、と思いました。
FIDOのU2Fは、認証デバイスが鍵ペアを生成して保管し、
それを認証デバイス側と、サイト側で相互に突き合わせて強固な認証を行います。
Yubikey内のストレージは有限かつ少量で、それは各機能の登録データ数の制限等を見ると明らかです。
しかしながら、U2F認証を要求するサイトは数十、数百と増えるでしょう。
そうした時に、上限に達したらどうなるのか?
これ以上登録できませんとなるのか?削除の仕組みがある?それともまさか古い順に削除される?
調べてみると、公式サイトに回答がありました。
how many services can the u2f-certified YubiKeys be associated with?
https://www.yubico.com/support/knowledge-base/categories/articles/many-services-can-u2f-certified-yubikeys-associated/
「利用できるサービスの数の制限はありません。
鍵ペアは生成されますが、デバイスには保存されず、登録サービスに保存されます。
そのため実質的に無限に登録できます。」
最初これを見たとき、「え?」となりました。
・鍵ペアをサービスに保存したら意味なくない?
・Yubikeyからどうやって認証してるんだ?
・そもそもFIDOの仕様に、サイト側に保存する仕組みなんてあったっけ?
開発者向けサイトに答えがありました。
なかなかおもしろい仕組みを使って実装されています。
Key generation - Yubico Developers
https://developers.yubico.com/U2F/Protocol_details/Key_generation.html
ただしこれも理解に時間がかかったので、自分の理解の結果を以下に示します。
誤りが含まれているかもしれません。上記のURLの内容そのままといえばそのままですので、ご確認ください。
前提
・キーデバイスは、AppID(ドメイン名含む)でサイトを識別する。(これがフィッシング対策になる)
・同じサイトで、違うアカウントの認証情報が必要な場合があり、AppIDでは識別できない。
そのために鍵の識別はKeyHandleを用いて行う。このKeyHandleは、デバイスが生成してサイトに送る。
・しかし、そうしたところで、セキュアなストレージが大量に必要になる。
FIDOは鍵の格納方法を指定していないため、Yubikeyでは違ったアプローチをしている。
登録フェーズ
1. Webサービスは、AppID、Challenge(リプレイ攻撃対策乱数)とともに登録リクエストをする
2. Yubikey内で、乱数からNonceを生成する。
3. Yubikey内で、AppIDとNonceをデバイス内部鍵(固定)で署名ハッシュを取り、
これを秘密鍵とする。
4. Yubikey内で、秘密鍵から公開鍵を生成する。
5. Yubikey内で、AppIDと秘密鍵、デバイス内部鍵(固定)で署名ハッシュを取り、
秘密鍵ハッシュ(MAC)を生成する。
6. Yubikey内で、NonceとMACの一部を結合し、KeyHandleとする。
7. Yubikey内で、公開鍵・KeyHandle・Challenge・AppIDを秘密鍵で署名し、サービスに返す。
8. 内部カウンタを加算する。
認証フェーズ
1. Webサービスは、AppIDとKeyHandle、Challenge(リプレイ攻撃対策乱数)を渡して認証要求する
2. Yubikey内で、KeyHandleから登録時のNonceと秘密鍵MACを取り出す
3. Yubikey内で、AppIDとNonceをデバイス内部鍵(固定)で署名ハッシュを取り、これを秘密鍵とする。
4. Yubikey内で、秘密鍵から公開鍵を生成する。
5. Yubikey内で、AppIDと秘密鍵、デバイス内部鍵(固定)で署名ハッシュを取り、
秘密鍵MACを生成する。これを、KeyHandleから取り出したMACと比較し、正しいか検証する。
(正しくなければ、これはこのYubikeyのものではないか、あるいは改変されている)
6. Yubikey内で、KeyHandle・Challenge・AppIDを署名し、サービスに返す。
7. 内部カウンタを加算する。
結論として、Yubikey内には、秘密鍵も公開鍵もKeyHandleも保存されない。
デバイス内部鍵は、Yubikeyに出荷時に書き込まれているものであり、取り出しも変更もできない。
内部的に変化するのはカウンタだけである。
秘密鍵は、NonceとAppIDと、デバイス内鍵の3つから「毎回」生成されている。
Nonceは、登録時は乱数だが、認証時は登録時に渡したKeyHandleがサービスから帰ってくる。
KeyHandleは、Nonceと秘密鍵MACを結合したものであり、そのためこれで秘密鍵生成データが揃うことになる。
このままだと、全く登録していないサービスなどから要求されても、
無効な署名を渡してしまうが、それはKeyHandleに含まれている秘密鍵MACを使うことで
KeyHandleが自分が生成したものかをチェックできる仕組みになっている。
よくできている。
2017年11月29日
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/181706880
※ブログオーナーが承認したトラックバックのみ表示されます。
※言及リンクのないトラックバックは受信されません。
この記事へのトラックバック
http://blog.sakura.ne.jp/tb/181706880
※ブログオーナーが承認したトラックバックのみ表示されます。
※言及リンクのないトラックバックは受信されません。
この記事へのトラックバック