自前のシステムでも多要素認証やりたい
画面に表示されたQRコードをスマホアプリにぴっと読み込み。
すると、30秒ごとにワンタイムパスワードが生成されるようになります。
あれを自前のシステムでもやりたいです。
QRコードの内容
QRコードの内容は otpauth:// で始まるURIになっています。
まずはこれを作れればスマホアプリで読み込めますね。
otpauth URI スキームの構造
こういうものの仕様は、RFCにあるかと思えば見つかりません。stackexchangeに質問がありました。回答によると、otpauth URIはBlackberryのソースコードに由来するようです。
URIの一般構造(引用元 RFC 3986)を眺めながらソースを追ってみます。
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
ソースによると otpauth と totp の2つのスキームと、普通のURLが使えます。
それぞれのスキームごとにURIの使い道をまとめてみます。
scheme | authority | path | query | fragment |
---|---|---|---|---|
otpauth | totp | ユーザ名 | シークレット(secretキー) | - |
otpauth | hotp | ユーザ名 | カウンター(counterキー)、シークレット(secretキー) | - |
totp | ユーザ名 | - | - | シークレット |
上記以外 | - | - | ユーザ名(userキー) | シークレット |
シークレットはBase32エンコードされた文字列です。
サンプルURI
こんなURIを作ればよさそうです。
otpauth://totp/anonymous@example.com?secret=NFWG65TFPFXXK===
otpauth://hotp/anonymous@example.com?counter=100&secret=NFWG65TFPFXXK===
totp://anonymous@example.com#NFWG65TFPFXXK===
http://example.com/?user=anonymous@example.com#NFWG65TFPFXXK===
QRコードにしてみました。
(QRコードは https://www.cman.jp/QRcode/qr_make/ で生成しました。感謝!)
読み込めますか?
Authyアプリでは、otpauthスキーマのtotpしか読み込めませんでした。
ここまでくれば
あとは、以下のことをすれば実装できそうです。
- QRコード発行時
- 暗号論的にランダムなシークレットを生成
- シークレットを保管
- ログイン時
- Unix timeとシークレットからワンタイムパスワードを生成
- ユーザが入力したワンタイムパスワードと、生成したワンタイムパスワードを比較して認証
気になること
シークレットを生のまま保管しておくのって、なんかパスワードを生のまま保管するみたいで気になります。
追記
さらに探したら、otpauth URIのフォーマットありました。
こんなフォーマットです。
otpauth://TYPE/LABEL?PARAMETERS
PARAMETERSには以下の項目があります。
パラメータ | 必須? | 既定値 | 説明 |
---|---|---|---|
secret | 必須 | - | シークレット |
issuer | 強く推奨 | - | シークレットの発行者 |
algorithm | オプション | SHA1 | SHA1、SHA256、SHA512のいずれか |
digits | オプション | 6 | OTPの桁数 |
counter | hotpの時必須 | - | カウンター |
period | totpのときオプション | 30 | totpの生成間隔(秒) |
全部入りだとこんなURIになります。
otpauth://totp/anonymous@example.com?secret=NFWG65TFPFXXK===&issuer=example&algorithm=sha256&digits=8&period=15