Почему HMAC SHA-1 должен возвращать другой дайджест с тем же входом?

Я пытаюсь создать рабочую зашифрованную подпись для веб-сервиса 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, я должен увидеть тот же секретный ключ, открытый текст и байты дайджеста.

Действительно, я получаю одинаковые байты для секретного ключа и открытого текста.

Но для дайджеста (и, конечно, кодировки base64) я получаю что-то другое, например:

$ s3ls --access-key=foobar --secret-key=abcd1234
...
secret key hex: 6162636431323334
cleartext hex: 4745540a0a0a4672692c2031322044656320323030382031303a30383a353120474d542b30303a30300a2f
digest hex: c0da50050c451847de7ed055c5286de584527a22
encoded: wNpQBQxFGEfeftBVxSht5YRSeiI=

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

Что может привести к тому, что дайджест HMAC SHA-1 будет вычисляться по-разному в обоих случаях, если входные байты и подпрограмма _encode одинаковы?

(Я также проверил два сценария на соответствие тестовым примерам в RFC 2201.)


person Alex Reynolds    schedule 12.12.2008    source источник


Ответы (4)


Я считаю, что основные проблемы, с которыми я столкнулся при сравнении хешей, следующие:

  1. убедитесь, что данные и ключ одинаковы в обоих сравнениях
  2. убедитесь, что данные и ключ имеют одинаковую кодировку символов в обоих сравнениях
  3. убедитесь, что ключ и текст передаются одинаково в обоих сценариях, то есть какой из них является ключевым, а какой - текстовым (это меня ловило не раз).

Попробуйте использовать модуль Digest :: SHA, чтобы создать для вас хеш и сравнить результаты с ним.

use Digest::SHA qw(hmac_sha1_hex);
my $hash = hmac_sha1_hex($data, $key);

См. Документацию по адресу http://perldoc.perl.org/Digest/SHA.pdf.

person brofield    schedule 12.12.2008
comment
1. Данные (открытый текст) и ключ (секретный ключ) одинаковы в обоих сравнениях 2. Я использую строки UTF8 в обоих случаях 3. Как показывают результаты _ascii_to_hex, байты для секретного ключа и открытого текста одинаковы. используется в качестве входных данных для экземпляра HMAC. Возможно, вам поможет другой модуль Perl. - person Alex Reynolds; 12.12.2008
comment
AFAIK, Digest :: HMAC_SHA1 внутренне использует Digest :: SHA. - person innaM; 13.12.2008

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

Поскольку вы сравниваете не сами дайджесты, а версии дайджестов в кодировке Base-64, я бы рекомендовал сделать резервную копию одного шага и проверить сами дайджесты. Возможно, подпрограммы кодирования Base-64 неверны.

Если вы не можете сравнить сами дайджесты, используйте одну и ту же процедуру кодирования в обеих программах и посмотрите, что у вас получится.

person Community    schedule 12.12.2008

Боюсь, я ничем не могу здесь помочь, но что-то не так с тем, что вы опубликовали. Ваш пример сценария дает мне другой вывод, и вывод, который вы опубликовали, действительно не может быть правильным.

Как это могло

secret key hex: abcd...1234

когда-либо быть результатом этого

_ascii_to_hex("blahblahblah")

Конечно, весь ascii_to_hex совершенно не имеет отношения к вашей проблеме, но показывает, что вы должны перепроверить свои результаты.

person innaM    schedule 12.12.2008

Разделяй и властвуй?

Лучше всего начать с тестовых векторов в RFC. Они прошли в обоих случаях? Какие из них вы пробовали? Если некоторые из них работают, а другие нет, наиболее вероятная проблема заключается в том, что один из двух API неправильно упорядочивает ввод ключей (подписанные и неподписанные массивы, преобразование кодировки и т. Д.)

Кроме того, вам действительно сложно помочь, когда ваш пример - ерунда. Как уже упоминалось, шестнадцатеричное представление бла-бла не abc..123. Заставляет меня задуматься, что еще в вашем примере неточно?

person Einstein    schedule 12.12.2008