HMAC SHA-1截断HOTP逻辑

时间:2014-12-01 07:51:43

标签: arrays truncate hmacsha1 one-time-password rfc-4226

我正在尝试为HOTP计算手动HMAC SHA-1截断,但它不会返回与我用源代码计算相同的结果。例如,我有生成HMAC SHA-1的代码:

$ hash = hash_hmac('sha1','375317186160478973','test');

它会给我HMAC = c359e469b8ef0939f83e79a300b20a6ef4b53a05

并将其划分为[19]数组,因此它将是:

c3 59 e4 69 b8 ef 09 39 f8 3e 79 a3 00 b2 0a 6e f4 b5 3a 05

从最后一个数组我得到05(二进制为101),然后做了101& 0xf = 5

所以我算从第5阵列ef(11101111)09(1001)39(111001)f8(11111000)

之后做(((11101111)& 0x7f)<< 24)| (((1001)& 0xff)<< 16)| (((111001)& 0xff)<< 8)| ((11111000)& 0xff))%pow(10,6)

它给我一个结果: 56024

但是如果我使用这段代码:

$offset = ($hash[19]) & 0xf;
$otp    = (((($hash[$offset + 0]) & 0x7f) << 24) |
          ((($hash[$offset + 1]) & 0xff) << 16) |
          ((($hash[$offset + 2]) & 0xff) << 8) |
          (($hash[$offset + 3]) & 0xff)) % pow(10, 6);

它给我一个结果: 599808

如果我将二进制或十进制值写为数组中的值,则会显示相同的不同结果。有人可以帮我解释我的错在哪里,所以我可以计算手册和源代码,并给我一个相同的HOTP值。谢谢

1 个答案:

答案 0 :(得分:0)

Apa kabar :)首先,SHA-1是160位(20字节),大小不是19.你正在使用PHP吗? 问题是,访问这样的数组并不起作用,因为你总是只在字符上阅读:

$hash[5] // (4)
$hash[6] // (6)
$hash[7] // (9)
$hash[8] // (b)

以下应该工作:

((intval(substr($hash, ($offset + 0) * 2, 2), 16) & 0x7f) << 24) |
((intval(substr($hash, ($offset + 1) * 2, 2), 16) & 0xff) << 16) |
((intval(substr($hash, ($offset + 2) * 2, 2), 16) & 0xff) << 8) |
(intval(substr($hash, ($offset + 3) * 2, 2), 16) & 0xff);

重要的是,由于$hash似乎是一个字符串,你可能不会简单地将其作为数组访问,因为这将返回错误的值。但是你可以借助substr方法获得字符串的组成部分。您总是必须读取2个字节并将其转换为整数。该字符串包含六进制十进制值,您必须使用intval中的基数16。

PS:我假设哈希字符串正好是20个字节长。

摘要:例如$ hash [5]不会给你预期的数组值0xEF,但它会给你第5个字符串字符&#39; 4&#39; (子串E4的一部分)。