HMAC SHA-1 Усеченная HOTP Logic

Я пытаюсь посчитать ручное усечение 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. Спасибо

1 ответ

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

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

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

Другие вопросы по тегам