Почему HMAC SHA-1 возвращает другой дайджест с теми же входными данными?
-
21-08-2019 - |
Вопрос
Я пытаюсь создать рабочую зашифрованную подпись для веб-службы Amazon S3, пишу библиотеку подключений с использованием Objective C.
Я столкнулся с проблемами дайджеста HMAC SHA-1 в коде ObjC, поэтому я откладываю это в сторону и смотрю на существующий работающий код Perl, чтобы попытаться устранить неполадки при создании дайджеста.
Я тестирую вывод дайджеста HMAC SHA-1 из s3ls
командование Net::Amazon::S3
пакет и сравнивая его с _encode
подпрограмму, которую я вытащил и поместил в отдельный Perl-скрипт:
#!/usr/bin/perl -w
use MIME::Base64 qw(encode_base64);
use Digest::HMAC_SHA1;
use String::Escape qw( printable unprintable );
sub _ascii_to_hex {
(my $str = shift) =~ s/(.|\n)/sprintf("%02lx", ord $1)/eg;
return $str;
}
sub _encode {
my ( $aws_secret_access_key, $str ) = @_;
print "secret key hex: "._ascii_to_hex($aws_secret_access_key)."\n";
my $hmac = Digest::HMAC_SHA1->new($aws_secret_access_key);
$hmac->add($str);
my $digest = $hmac->digest;
print "cleartext hex: "._ascii_to_hex($str)."\n";
print "digest hex: "._ascii_to_hex($digest)."\n";
my $b64 = encode_base64( $digest, '' );
print "encoded: ".$b64."\n";
}
my $secret = "abcd1234";
my $cleartext = "GET\n\n\nFri, 12 Dec 2008 10:08:51 GMT+00:00\n/";
_encode($secret, $cleartext);
Вот пример вывода этого скрипта:
$ ./testhmac.pl
secret key hex: 6162636431323334
cleartext hex: 4745540a0a0a4672692c2031322044656320323030382031303a30383a353120474d542b30303a30300a2f
digest hex: 63308f9b8a198440d6d8685a3f3f70d0aab02f68
encoded: YzCPm4oZhEDW2GhaPz9w0KqwL2g=
Я проверяю, что если я введу один и тот же секретный ключ и открытый текст в одно и то же _encode
функция Net::Amazon::S3
package, я должен увидеть тот же самый секретный ключ, открытый текст и байты дайджеста.
Действительно, я получаю одни и те же байты для секретного ключа и открытого текста.
Но для дайджеста я получаю что-то другое (и, конечно, кодировку base64), например:
$ s3ls --access-key=foobar --secret-key=abcd1234
...
secret key hex: 6162636431323334
cleartext hex: 4745540a0a0a4672692c2031322044656320323030382031303a30383a353120474d542b30303a30300a2f
digest hex: c0da50050c451847de7ed055c5286de584527a22
encoded: wNpQBQxFGEfeftBVxSht5YRSeiI=
Я проверил, что секретный ключ и открытый текст являются одинаковыми входными данными для обоих сценариев.Процедура кодирования практически идентична в обоих сценариях (за исключением неиспользуемого аргумента, переданного в подпрограмму, который я удалил из своей пользовательской версии).
Что может привести к тому, что дайджест HMAC SHA-1 будет вычисляться по-разному в обоих случаях, если входные байты и _encode
подпрограмма одна и та же?
(Я также проверил эти два сценария на тестовых примерах на РФК 2201.)
Решение
Я считаю, что основные проблемы, с которыми я столкнулся при сравнении хэшей, заключаются в следующем:
- убедитесь, что данные и ключ одинаковы в обоих сравнениях
- убедитесь, что данные и ключ находятся в одной и той же кодировке символов в обоих сравнениях
- убедитесь, что ключ и текст передаются одинаково в обоих сценариях, т.е.какой из них ключевой, а какой текстовый (это меня не раз ловило).
Попробуйте использовать модуль Digest::SHA, чтобы создать хэш и сравнить с ним результаты.
use Digest::SHA qw(hmac_sha1_hex);
my $hash = hmac_sha1_hex($data, $key);
См. документы на http://perldoc.perl.org/Digest/SHA.pdf
Другие советы
Процедура кодирования практически идентична в обоих сценариях (за исключением неиспользуемого аргумента, переданного в подпрограмму, который я удалил из своей пользовательской версии).
Поскольку вы сравниваете не сами дайджесты, а версии дайджестов в кодировке Base-64, я бы рекомендовал сделать резервную копию на один шаг и проверить сами дайджесты.Возможно, процедуры кодирования Base-64 неверны.
Если вы не можете сравнить сами дайджесты, используйте одну и ту же процедуру кодирования в обеих программах и посмотрите, что получится.
Боюсь, я здесь ничем не смогу помочь, но в том, что вы опубликовали, определенно что-то не так.Ваш пример сценария выдает для меня другой результат, и опубликованный вами результат действительно не может быть правильным.
Как это могло
secret key hex: abcd...1234
когда-либо быть результатом этого
_ascii_to_hex("blahblahblah")
Конечно, вся эта штука с ascii_to_hex совершенно не имеет отношения к вашей проблеме, но она показывает, что вам следует перепроверить свои результаты.
Разделяй и властвуй?
Тестовые векторы в RFC — лучшее место для начала.Они прошли в обоих случаях?Какие из них вы пробовали?Если некоторые работают, а другие нет, наиболее вероятная проблема заключается в том, что один из двух API неправильно сортирует ввод ключей (знаковые и беззнаковые массивы, преобразования кодировок и т. д.)
Кстати, очень сложно вам помочь, если ваш пример — ерунда.Как уже упоминалось, шестнадцатеричное представление бла-бла не является abc..123.Заставляет меня задуматься, что еще в вашем примере неточно?