HMAC SHA-1 Усекает логику HOTP

Я пытаюсь подсчитать ручное усечение HMAC SHA-1 для HOTP, но оно не дает того же результата, что и исходный код. Например, у меня есть код для генерации 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. Спасибо


person Gudang Garam    schedule 01.12.2014    source источник


Ответы (1)


Апа кабар :) Во-первых, 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 кажется строкой php, вы не можете просто получить к ней доступ как к массиву, поскольку это вернет неправильные значения. Но можно получить компоненты строки с помощью метода substr. Вам всегда нужно прочитать 2 байта и преобразовать их в целое число. Поскольку строка содержит шестнадцатеричные значения, вы должны использовать основание 16 в intval.

PS: я предполагаю, что хэш-строка имеет длину ровно 20 байт.

Вывод: $hash[5], например, не даст вам ожидаемого значения массива 0xEF, но даст вам 5-й символ строки '4' (часть подстроки E4).

person bkausbk    schedule 01.12.2014
comment
Кабар байк, Данке :). Спасибо за ваш ответ, сэр. Я не особо разбираюсь в массивах, потому что это моя первая попытка расшифровать, как HOTP (RFC 4226) может быть усечен до 6 цифр. А также я пытаюсь сделать то же самое, что и здесь: goo.gl/LljCZ0 , здесь: goo.gl/ovosgA и здесь: goo.gl/JEEQwW вернет другое значение HOTP, и я не могу изменить формулу усечения, указанную в RFC 4226. Вот мой результат: goo.gl/S0aUqT . Он преобразовал шестнадцатеричное значение в десятичное. Посоветуйте, сэр :) - person Gudang Garam; 01.12.2014
comment
@GudangGaram Я обновил свое объяснение. Я точно не знаю алгоритма HOTP, но похоже, что это не ваша проблема. Проблема в том, как вы получаете доступ к данным, которые хранятся в строке, а не в массиве. - person bkausbk; 01.12.2014
comment
Извините, сэр, я не читал ваше обновленное объяснение в вашем ответе, теперь я его прочитал, теперь я работаю над этим. Позже напишу, получилось или нет. Спасибо за совет сэр. - person Gudang Garam; 01.12.2014