今日は最近、ポテンシャルを感じていたのに実装に着手して詳しく調べてみると残念だったことの話です。
皆さんはスマートフォンで指紋認証やFace IDを利用されているでしょうか。ワンタッチで認証できてパスワードよりセキュアという、非常に便利な技術ですよね。銀行などのお堅めなアプリでも指紋認証だけでログインできるところもあります。
今日はそのようにとても身近になった生体認証と、仮想通貨を用いたWebアプリの話です。
WebauthnというAPI
アプリやブラウザから生体認証を行う際、多くの場合WebauthnというAPIを使ってアプリやブラウザが端末とやり取りしています。
ご存知の方がほとんどとは思いますが、指紋認証やFace IDは使用しているサービスに指紋や顔写真を送っているわけではなく、指紋や顔面を利用してスマホ内にあるセキュア領域(認証器)へのアクセスを制御しています。具体的には、ウェブサイトやアカウントごとに鍵を生成したり、その鍵を指定して認証情報に署名するなどです。
ブラウザと端末の認証器の間の通信規格を定めたWebauthn APIはほとんどのブラウザにサポートされており、さらに例えばPCのChromeでGoogleアカウントにログインしている場合はAndroidスマホにタッチして認証できたりと、非常に便利になっています。
浅い理解の段階では、端末内にあるセキュア領域とのやり取りを通して鍵を生成したり、署名を出力させたりできるこの機能に、認証以外にも使い道がありそうだと期待しました。しかし、やがてその期待は裏切られたのです。
困ったこと:認証に「しか」使えない
認証器に鍵を生成できるということは、認証器をハードウェアウォレットとして、あるいはせめて鍵の保管庫として、たとえ取り出せたのが公開鍵だけだったとしても活用方法があるように考えていました。
実際、Webauthn APIはブラウザ~認証器のやり取りの話であり、実際にサーバーに認証情報を投げたりする必要はないためです。言い換えると、Webアプリケーションを開いて指紋認証しても、その認証情報を送信せずローカルだけで利用するという使い方もできるのです。
しかし、試しに実装してみると、生成した公開鍵が出力されるのは最初に登録時のみで、以後はサーバー側で保管した公開鍵で署名を検証するというスタイルでした。そしてもちろん署名も、内容を固定しても結果は毎回変わってしまいます。
なんとか自分だけが繰り返し読み出せる、十分にエントロピーのあるバイト列が得られないかと諦めず工夫を重ねていましたが、ついに同じ固有情報を繰り返し出力させることはできませんでした。Webauthnは非常にプライバシーに気を使って、一切他の用途に使う余地がない超特化型の設計をされていました。
せっかく世の大半が持つスマホに認証器という便利な暗号デバイスがあるのに、ブラウザから使う用途が認証に限られていることが非常に勿体なく感じました。
ちなみにハードウェアとの通信規格CTAP自体にはhmac-secretという認証情報とソルトから共通鍵を出力するコマンドやcredBlobという32バイトのデータを保管するコマンドがあり、これらを使えば目的が達成できそうですが、これらの機能はWebauthnにないためブラウザから使うことはできません。
WEB3業界の声と、W3Cの判断
さて、行き詰まったかもしれないと困ったので、見落としていることがないか調べていたら驚きの発見がありました。