在C#中基于HMAC-一次性密​​码(RFC 4226 - HOTP) [英] HMAC-based one time password in C# (RFC 4226 - HOTP)

查看:346
本文介绍了在C#中基于HMAC-一次性密​​码(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://tool​​s.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.

推荐答案

您这里有两个问题:


  1. 如果要生成的字母数字,你是不是符合RFC - 在这一点上,你可以简单地采取任何N个字节,并将它们变成一个十六进制字符串,并得到字母数字。或者,的将它们转换为基底36 如果你想AZ和0-9。 RFC的5.4节是给你的标准HOTP计算一组数字参数(请注意,数字是一个参数随着 C K T )。如果您选择忽略这一部分,那么你就需要将代码转换 - 只需使用你想要什么

  1. 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 that Digit is a parameter along with C, K, and T). 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆