Неожиданные результаты Delphi HMAC-SHA1

Я пишу в старой версии Delphi (Delphi 5) по причинам, которые не могу объяснить в этой теме. Я пытаюсь реализовать HOTP, и в настоящее время весь мой код работает без части HMACSHA1, и я не понимаю, почему. Я реализовал HMACSHA в соответствии с RFC 2202 и сравнил свои результаты с многочисленными другими генераторами HMACSHA1. Все это совпало.

Затем я начал реализовывать RFC 4226 для HOTP и был удивлен, увидев, что мои промежуточные результаты HMACSHA1 были неверными по сравнению с образцами данных, которые они предоставили в нижней части RFC (https://www.ietf.org/).rfc/rfc4226.txt).

Вот тестовый вектор из RFC

В следующих тестовых данных для секрета используется строка ASCII «12345678901234567890».

Секрет = 0x3132333435363738393031323334353637383930

В таблице 1 для каждого подсчета приведены промежуточные значения HMAC.

Подсчет Шестнадцатеричный HMAC-SHA-1 (секрет, подсчет)

0 cc93cf18508d94934c64b65d8ba7667fb7cde4b0

Но, используя мою функцию HMACSHA1, как показано ниже:

function HMAC_SHA1(Text, Key: AnsiString): AnsiString;
var
  ipad, opad, s: AnsiString;
  n: Integer;
  SHA1Context: TSHA1Ctx;
begin
  if Length(Key) > 64 then
    Key := SHA1(Key);
  ipad := StringOfChar(#$36, 64);
  opad := StringOfChar(#$5C, 64);
  for n := 1 to Length(Key) do
  begin
    ipad[n] := AnsiChar(Byte(ipad[n]) xor Byte(Key[n]));
    opad[n] := AnsiChar(Byte(opad[n]) xor Byte(Key[n]));
  end;
  SHA1Init(SHA1Context);
  SHA1Update(SHA1Context, ipad);
  SHA1Update(SHA1Context, Text);
  s := SHA1Final(SHA1Context);
  SHA1Init(SHA1Context);
  SHA1Update(SHA1Context, opad);
  SHA1Update(SHA1Context, s);
  Result := SHA1Final(SHA1Context);
end;

Я пытаюсь:

HMAC_SHA1('12345678901234567890', '0');

и мой ответ возвращается как

948d4b44f3e0aac05904d6fd82ab7b8bbe761a4c

Это то же самое, что и онлайн-генератор, указанный ниже.

http://www.freeformatter.com/hmac-generator.html#ad-output

Итак, что я делаю неправильно?


person Kyle Jurick    schedule 11.03.2014    source источник
comment
бумага, на которую вы ссылаетесь, использует счет, а не ключ. Попробуйте передать 0, а не «0».   -  person Red Alert    schedule 12.03.2014
comment
Не проблема, но вам нужен массив байтов, а не строка   -  person David Heffernan    schedule 12.03.2014


Ответы (1)


По крайней мере, одна проблема - вы проверяете ключи> размер блока (64), но вам также нужно проверять ключи короче, чем размер блока (64), которые должны быть дополнены справа нулями.

Что-то вроде этого в вашем коде выше...

//current check if > length
if Length(Key) > 64 then
    Key := SHA1(Key);

//also check < length
if Length(Key) < 64 then
   Key := Key + StringOfChar(#0, 64 - Length(Key));

Примечание. Гораздо лучше с байтовыми массивами.

person Darian Miller    schedule 12.03.2014