HOTP
RFC 4226 HOTP: An HMAC-based one-time password algorithm
https://doi.org/10.17487/RFC4226
https://tex2e.github.io/rfc-translater/html/rfc4226.html
HMAC-SHA-1なOTP
単純な出力値は Section 5
OATHが作成
RFC 2104 HMAC
RFC 4086 Randomness Requirements for Security
RFC 6238 TOTP
RFC 6287 OCRA: OATH Challenge-Response algorithm
RFC 4226の一部訳
errata 未反映
5. HOTPアルゴリズム
このセクションでは、表記法を紹介し、HOTP アルゴリズムの基本ブロック (HMAC-SHA-1 値を計算するための基本関数と HOTP 値を抽出するための切り捨て方法) について説明します。
5.1. 表記法と記号
string (文字列)は常にバイナリ文字列、つまり 0 と 1 のシーケンスを意味します。
s がstring(文字列)の場合、|s| はその長さを表します。
n がnumber(数値)の場合、|n| はその絶対値を表します。
s が文字列の場合、s[i] はその i 番目のビットを表します。ビットの番号付けは 0 から始まるため、s = s[0]s[1]...s[n-1] となり、n = |s| は s の長さです。
StToNum (String to Number) は、文字列 s を入力として、バイナリ表現が s である数値を返す関数を表します。(たとえば、StToNum(110) = 6。)
このドキュメントで使用されているシンボルの一覧を次に示します。
table:記号
記号 意味
C 8 バイトのカウンター値、移動係数。このカウンターは、HOTP ジェネレータ (クライアント) と
HOTP バリデータ (サーバー) の間で同期される必要があります。
K クライアントとサーバー間の共有秘密。各 HOTP ジェネレーターには異なる固有の秘密 K があります。
T スロットルパラメータ: T 回の認証試行が失敗すると、サーバーはユーザーからの接続を拒否します。
s 再同期パラメータ: サーバーは、連続するカウンタ値にわたって受信した認証子を検証しようとします。
Digit HOTP の値の桁数。システム パラメーター。
5.2. 説明
HOTP アルゴリズムは、増加するカウンタ値と、トークンと検証サービスのみが知っている静的対称キーに基づいています。HOTP 値を作成するには、RFC 2104 BCK2 で定義されている HMAC-SHA-1 アルゴリズムを使用します。
HMAC-SHA-1 計算の出力は 160 ビットなので、この値をユーザーが簡単に入力できる値に切り捨てる必要があります。
HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))
ここで:
Truncate は、セクション 5.3 で定義されているように、HMAC-SHA-1 値を HOTP 値に変換する関数を表します。
鍵 (K)、カウンター (C)、およびデータ値は、上位バイトから順にハッシュされます。
HOTP ジェネレータによって生成された HOTP 値は、ビッグ エンディアンとして扱われます。
5.3. HOTP値の生成
操作は 3 つのステップで説明できます:
ステップ 1: HMAC-SHA-1 値を生成する HS = HMAC-SHA-1(K,C) とします // HS は 20 バイトの文字列です
ステップ 2: 4 バイトの文字列を生成する (動的切り捨て)
Let Sbits = DT(HS) // DT (以下で定義) は 31 ビットの文字列を返します
ステップ 3: HOTP 値を計算します
Let Snum = StToNum(Sbits) // S を $ 0...2^{31}-1 の数値に変換します
Return D = Snum mod 10^Digit // D は $ 0...10^{Digit}-1 の範囲の数値です
Truncate (切り捨て) 関数は、ステップ 2 とステップ 3、つまり、動的切り捨てと 10^Digit を法とする削減を実行します。動的オフセット切り捨て手法の目的は、160 ビット (20 バイト) の HMAC-SHA-1 結果から 4 バイトの動的バイナリ コードを抽出することです。
DT(String) // String = String[0]...String[19]
OffsetBits を String[19]の下位4bitとします
Offset = StToNum(OffsetBits) // 0 <= OffSet <= 15
P = String[OffSet]...String[OffSet+3] とします
Return Pの下位31bitを返します
訳注: Stringの[]内はビット位置ではなくバイト位置 SHA-256, SHA-512 などではlastが19ではなく31, 63などになる
P の最上位ビットをマスクする理由は、符号付きモジュロ計算と符号なしモジュロ計算の混乱を避けるためです。プロセッサによってこれらの操作は異なりますが、符号付きビットをマスクするとすべての曖昧さが解消されます。
実装では、最低でも 6 桁のコード、場合によっては 7 桁と 8 桁のコードを抽出する必要があります。セキュリティ要件に応じて、より長い HOTP 値を抽出するために、Digit = 7 以上を考慮する必要があります。
次の段落は、この手法を Digit = 6 に使用する例です。つまり、6 桁の HOTP 値は HMAC 値から計算されます。
5.4. Digit = 6 の HOTP 計算の例
次のコード例は、hmac_result が HMAC-SHA-1 結果を含むバイト配列である場合の、動的バイナリ コードの抽出について説明しています:
code:Digit = 6
int offset = hmac_result19 & 0xf ;
int bin_code = (hmac_resultoffset & 0x7f) << 24
| (hmac_resultoffset+1 & 0xff) << 16
| (hmac_resultoffset+2 & 0xff) << 8
| (hmac_resultoffset+3 & 0xff) ;
code:SHA-1 HMAC バイト (例)
-------------------------------------------------------------
| バイト番号 |
-------------------------------------------------------------
|00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|
-------------------------------------------------------------
| バイト値 |
-------------------------------------------------------------
|1f|86|98|69|0e|02|ca|16|61|85|50|ef|7f|19|da|8e|94|5b|55|5a|
-------------------------------***********----------------++-
最後のバイト (バイト 19) の 16 進値は 0x5a です。
下位 4 ビットの値は 0xa (オフセット値) です。
オフセット値はバイト 10 (0xa) です。
バイト 10 から始まる 4 バイトの値は 0x50ef7f19 で、これを動的バイナリ コード DBC1 とします。
DBC1 の MSB は 0x50 なので、DBC2 = DBC1 = 0x50ef7f19 です。
HOTP = DBC2 modulo 10^6 = 872921。
動的バイナリ コードは 31 ビットの符号なしビッグ エンディアン整数として扱います。最初のバイトは 0x7f でマスクされます。
次に、この数値を 1,000,000 (10^6) で割って、6 桁の HOTP 値 872921 (10 進数) を生成します。
6. セキュリティに関する考慮事項
7. セキュリティ要件
7.1. 認証プロトコルの要件
7.2. HOTP値の検証 Validation of HOTP Values
7.3. サーバーでのスロットル
7.4. カウンターの再同期化
7.5.
付録A HOTPアルゴリズムのセキュリティ: 詳細な分析