Help us understand the problem. What is going on with this article?

YubiKeyの技術検証を任されたので, 検証用のデモサーバを実装した話

はじめに

この記事は, マイナビAdvent Calendar 2020の12/05分の記事です。
昨日は@ekusiadadusさんの強い将棋AIを作るです。

今回, 上司から「アドカレ書かない?」と誘われたのでこの記事を書く運びとなりました。
アルバイト業務はいくつか担当したのですが, その中でYubiKeyの技術検証があまり知られていない内容だと思ったので, これを記事にします。

YubiKeyとは?

一言でいえば, 2段階認証に用いられるハードウェアセキュリティキーです。

YubiKeyの国内ディストリビューターである日本情報システム株式会社によると, 下記の通り説明されています。

YubiKeyはアメリカ・スウェーデンに本社を持つYubico社が製造、販売するハードウェアセキュリティキーです。USB、NFC、Lightningの各インターフェースで接続し、人の指でタッチし静電気によって認証を行います。

渡されたのは, Security Key by Yubicoで, Amazonで1つ当たり4000円程度で購入できる廉価版です。

私に任されたのは, このYubiKey1つ1つが誰のものかを特定できるようにすることでした。

YubiKeyを一意に特定するための調査とデモサーバの実装

シリアルナンバー編

調査すると, 下記のような文が見つかりました。

The serial number, which is printed both literally and in 2D barcode form on every YubiKey is the definitive way to uniquely distinguish one YubiKey from another. Serial numbers are unique across all models of YubiKeys, with the exception of Security Keys, which do not have serial numbers. A YubiKey serial number cannot be changed or overwritten.
ref: Identifying Your YubiKey

ざっくりまとめると, 「全てのYubiKeyは全てのモデルにおいて一意なシリアルナンバーを持ち, このシリアルナンバーは変更や上書きできません。ただし, シリアルナンバーを持たないSecurity Keysは除きます。」

シリアルナンバーは一意だったのですが, Security Key by Yubicoはシリアルナンバーを持たないようです1。そのため, このYubiKeyだとシリアルナンバーを用いた所持者の特定はできませんでした。

しかし, Yubico Demonstration Siteで確認すると, 1つのYubiKeyに対して同じ名前のKeyを1つしか登録できないことから, YubiKey所持者の特定はできると踏みました。

認証方法・プロトコル調査編

次はYubikeyの認証方法と2つのプロトコルを調査しました。

このYubicoの認証は, YubiKey-ブラウザ間のCTAP(Client-to-Authenticator Protocol)およびブラウザ-RPサーバ(Relying Party)間のWebAuthnという2つのプロトコルから成るFIDO2が用いられています。言い換えれば, YubiKey-ブラウザ-RPサーバ間の全てをひっくるめたプロトコルがFIDO2です。

ドキュメントは, Web Authentication API(WebAuthn)Client to Authenticator Protocol(CTAP) - 3. Protocol Structureをご参照ください。

また, YubiKeyのu2f実装について参考にした記事も載せておきます。

- YubiKeyの U2F 実装
- いまさらながらのFIDO U2F

それと, 先日のアドカレでも分かりやすい記事があったので載せておきます。
- FIDOのPIN認証のフローを理解する

調査していくうちに, サーバとクライアント間の認証では単純な公開鍵認証が用いられていることが分かったので, 各公開鍵にYubiKeyの所持者名を紐づけることで認証時に所有者を特定することが出来ると考えました。

デモサーバ実装編

Security Key by Yubicoはシリアルナンバーこそ一意ではないものの, YubiKeyごとの秘密鍵(Device Secret)は一意です。そのため, サーバに保存されている全ての公開鍵で認証を行い, 認証できた公開鍵と紐づけられているユーザがそのYubiKeyの所有者ということになります。サーバに保存される公開鍵の数が多かった場合でも, 個々の認証にかかる時間が短いためこのような実装でも問題ないと判断しました。また, 仮にこの公開鍵が漏洩しても公開鍵が漏洩しただけではYubiKey本体側の秘密鍵のなりすましは出来ないので, リスク的にも問題ないと考えています。

デモ用の実装を一応おいておきます。デモ実装なので酷いコードですが, お許しください。

task4233/YubiKey-Discriminator

おわりに

今回の検証は調査が8割, 実装が2割という内訳で殆どが調査だったと考えています。そもそも検証を始める前はYubiKeyという名前を聞いたことがある程度でしたし, こういった検証系は, 何が正しいかが分からないため非常に苦労しました。しかし, 途中で挫折しかけながらも相談しながら進めることができたのでなんとか形になったと考えています。

こういった検証系は, 知識を広げられる機会でもあるので面白いですね。やっているときは全然進まない時もありましたが, 何かを境に急に出来るようになる瞬間が特に良いです。

さて, 明日は@bake0937さんの「CodeBuild に用意されている Docker イメージ」で AWS CodeBuild 上での docker-compose のインストール作業を省略するです!お楽しみに。

References

YubiKeyに関するライブラリ・実装まとめ

プロトコルのドキュメント

理解のためのページ


  1. 一意でない, シリアルナンバーもどきはありました 

task4233
競プロ(AtCoder, Codeforces) | CTF | seccamp2019 A | SecHack365 2020 研究駆動 | http://github.com/task4233
https://task4233.hatenablog.com/
mynavicorp
「わたし」の日常に、当たり前にある存在へ ... 総合情報サービス企業
https://www.mynavi.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away