Почему 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.)

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
5 406
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

Как это могло

secret key hex: abcd...1234

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

_ascii_to_hex("blahblahblah")

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

Ответ принят как подходящий

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

  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

1. Данные («открытый текст») и ключ («секретный ключ») одинаковы в обоих сравнениях 2. Я использую строки UTF8 в обоих случаях 3. Как показывают результаты _ascii_to_hex, байты для секрета одинаковы. ключ и открытый текст, используемые в качестве входных данных для экземпляра HMAC. Возможно, вам поможет другой модуль Perl.

Alex Reynolds 12.12.2008 15:58

AFAIK, Digest :: HMAC_SHA1 внутренне использует Digest :: SHA.

innaM 13.12.2008 15:28

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

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

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

The encoding subroutine is virtually identical in both scripts (except for an unused argument passed to the subroutine, which I remove from my custom version).

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

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

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