在C#中基于HMAC-一次性密码(RFC 4226 - HOTP) [英] HMAC-based one time password in C# (RFC 4226 - HOTP)
问题描述
我试图环绕产生6位/字符不区分大小写到期一次性密码我的大脑。
I am attempting to wrap my brain around generating a 6 digit/character non case sensitive expiring one-time password.
我的源的 http://tools.ietf.org/html/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
Then we have the algorithm to generate the 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))
然后,我们必须截断定义为
Then, we have Truncate defined as
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
And then an example is offered for a 6 digit 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代码如下:
I am rather at a loss in attempting to convert this into useful C# code for generating one time passwords. I already have code for creating an expiring HMAC as follows:
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位数作为上述算法提出
I'm just not sure how to go from that, to 6 digits as proposed in the above algorithms.
推荐答案
您这里有两个问题:
-
如果要生成的字母数字,你是不是符合RFC - 在这一点上,你可以简单地采取任何N个字节,并将它们变成一个十六进制字符串,并得到字母数字。或者,的将它们转换为基底36 如果你想AZ和0-9。 RFC的5.4节是给你的标准HOTP计算一组
数字
参数(请注意,数字
是一个参数随着C
,K
和T
)。如果您选择忽略这一部分,那么你就需要将代码转换 - 只需使用你想要什么
If you are generating alpha-numeric, you are not conforming to the RFC - at this point, you can simply take any N bytes and turn them to a hex string and get alpha-numeric. Or, convert them to base 36 if you want a-z and 0-9. Section 5.4 of the RFC is giving you the standard HOTP calc for a set
Digit
parameter (notice thatDigit
is a parameter along withC
,K
, andT
). If you are choosing to ignore this section, then you don't need to convert the code - just use what you want.
您结果的字节数组有简单的塞在了前8个字节散列后的到期时间。如果您的截断至6位字母数字不与哈希的部分一起收集这些,它可能也根本无法计算。这也很容易假货或重播 - 散列密一次,然后把你要在它前面的任何蜱 - 不是一个真正的一次性密码。请注意,在RFC该参数 C
意指履行到期窗口,并应被添加到输入的之前的计算散列码。
Your "result" byte array has the expiration time simply stuffed in the first 8 bytes after hashing. If your truncation to 6-digit alphanumeric does not collect these along with parts of the hash, it may as well not be calculated at all. It is also very easy to "fake" or replay - hash the secret once, then put whatever ticks you want in front of it - not really a one time password. Note that parameter C
in the RFC is meant to fulfill the expiring window and should be added to the input prior to computing the hash code.
这篇关于在C#中基于HMAC-一次性密码(RFC 4226 - HOTP)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!