【发布时间】:2011-05-17 12:27:03
【问题描述】:
我正在尝试生成一个 6 位/字符不区分大小写的一次性到期密码。
我的来源是https://www.rfc-editor.org/rfc/rfc4226#section-5
先定义参数
C 8-byte counter value, the moving factor. This counter
MUST be synchronized between the HOTP generator (client)
and the HOTP validator (server).
K shared secret between client and server; each HOTP
generator has a different and unique secret K.
T throttling parameter: the server will refuse connections
from a user after T unsuccessful authentication attempts.
那么我们就有了生成 HOTP 的算法
As the output of the HMAC-SHA-1 calculation is 160 bits, we must
truncate this value to something that can be easily entered by a
user.
HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))
然后,我们将 Truncate 定义为
String = String[0]...String[19]
Let OffsetBits be the low-order 4 bits of String[19]
Offset = StToNum(OffsetBits) // 0 <= OffSet <= 15
Let P = String[OffSet]...String[OffSet+3]
Return the Last 31 bits of P
然后提供了一个 6 位 HOTP 的示例
The following code example describes the extraction of a dynamic
binary code given that hmac_result is a byte array with the HMAC-
SHA-1 result:
int offset = hmac_result[19] & 0xf ;
int bin_code = (hmac_result[offset] & 0x7f) << 24
| (hmac_result[offset+1] & 0xff) << 16
| (hmac_result[offset+2] & 0xff) << 8
| (hmac_result[offset+3] & 0xff) ;
我在尝试将其转换为有用的 C# 代码以生成一次性密码时不知所措。我已经有用于创建过期 HMAC 的代码,如下所示:
byte[] hashBytes = alg.ComputeHash(Encoding.UTF8.GetBytes(input));
byte[] result = new byte[8 + hashBytes.Length];
hashBytes.CopyTo(result, 8);
BitConverter.GetBytes(expireDate.Ticks).CopyTo(result, 0);
我只是不确定如何从上述算法中得到 6 位数字。
【问题讨论】:
-
我相信 C 是一个日期时间戳,而 K 是我已经分配给每个用户帐户的密钥。至于我如何正确地对它们进行哈希处理,然后将其截断为 6 位,这让我感到困惑。
-
附录 C 提供了一个 Java 参考实现,应该很容易翻译成 C#。
-
是的,但它只生成一个数字 HOTP。我真的很想要一个字母数字的 HOTP。
标签: c# hmac one-time-password