メモ。正しさはもちろん保証されない
課題
HOTP的にカウンターをシェアしたくない
HOTPではサーバとクライアントのカウンタがズレると認証できなくなる。一般ユーザで目にするのは「何回もOTPを空撃ちすると役に立たなくなる」という現象。自分はこれが大変嫌いで自分で雑に使う際は時間ベースのTOTPにしたくなる。銀行等で配布されるトークンは耐タンパ性も考えて作りこまれたトークンだが、こういうものはHOTPを採用していて、またボタンにロック機構があるわけでもないのでカウンタのズレが容易に起こる。先日バッグに入れてしばらく置いておいたら振込できなくなった。次の小学生のいたずらはバッグの外にふらふらしているOTPトークンの空打ちかもしれない。
TOTP以外の方法にOCRAがある。これは秘密情報を共有した後、サーバがChallengeを発行してクライアントがそれに基づいたResponseを返して認証するというChallenge-ResponseをOTPに導入したもの。
RFC6287として仕様が記述される。ただしこれはCategoryとしてはInformational。HOTPもそうみたいなんだけど。
構成の概要
最初に秘密情報を共有する方法自体については特に規定はないようだ。秘密情報のフォーマットについてとその交換のされ方には規定がある。個人的にメモしときたいところを書く
OCRA = CryptoFunction(K, DataInput)
DataInput = {OCRASuit | 00 | C | Q | P | S | T}
- OCRASuite ... レスポンス生成に用いるアルゴリズムを指定する値。後述
- C ... 8バイトカウンタ。認証する側で共有
- Q ... 128バイトのChallenge
- P ... 認証する側が保持するPIN/passwordのハッシュ
- S ... セッション情報を記述する512バイト文字列。UTF-8
- T ... UTCの1970年1月1日からの秒・分・時間によるカウント。timestampっぽいが単位は変えられる
OCRASuiteに応じてCを使うか使わないか、Tの単位は何か、といったことを指定できる。RFC内の一例では"OCRA-1:HOTP-SHA512-8:C-QN08-PSHA1"とある。OCRA version 1を用い、sha512をハッシュ関数として使い、Cも用いた上でそれを8文字の数字に切り詰める、など。
CやPは認証を要求する側が解釈しなければならない(MUST)フィールドで、認証フロー自体に影響を与えるかはOCRASuiteによるようだ。
Sはオプショナルで使う必要はない。ただ、TLSのセッション情報を含めるといった対応でセキュリティを強化するのに使うことが勧められてはいる (Page 18のIC8)
その他
何らかの形でChallengeをそのクライアントに都度ぶちこむ必要がある。そのChallengeを人に入力させるのはしんどいだろうから、ネットワーク接続なり他の方法で入れることになる。
より安全を期するなら、クライアントはまずそのChallengeを発行した主体自体も認証したい。というわけでRFCには双方向Challenge-Responseの規定もある。このレベルだとネットワーク接続で直接クライアントが秘密を取りに行く、といった方が自然に見えるかもしれない。「てめぇのChallenge解いてやるから俺のChallengeをまず解け」という俺様クライアントを実装することになる。こちらの事例は見たことがまだない。
最終的にユーザが認証を要求した側に送信するものはPINコード数桁で、ここはHOTP等と同じように出来る (数字に切り詰めない方法もある)。
OCRAでは2要素認証はMUST。単に1つのボタンを押せばPINが出ることは許されない。上記のChallenge入力も有り、ハードウェアトークンでの実装は少々難しい印象を受ける。