Hmac-SHA256 не возвращает ожидаемый хеш - PullRequest
0 голосов
/ 03 октября 2018

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

Используя SHA256 для следующего ввода, я получаюправильный вывод:

var canonString = 'GET\n'+
                    '/\n'+
                    'Action=ListUsers&Version=2010-05-08\n'+
                    'content-type:application/x-www-form-urlencoded; charset=utf-8\n'+
                    'host:iam.amazonaws.com\n'+
                    'x-amz-date:20150830T123600Z\n'+
                    '\n'+
                    'content-type;host;x-amz-date\n'+
                    'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';

console.log(CryptoJS.SHA256(canonString).toString()); //returns the expected value of f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59

Так что SHA256 работает на этом должным образом.Аналогично, используя Hmac-SHA256 на следующем входе, я получаю правильный ответ:

var kDate = CryptoJS.HmacSHA256("20150830", "AWS4wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY");
var kRegion = CryptoJS.HmacSHA256('us-east-1', kDate);
var kService = CryptoJS.HmacSHA256('iam', kRegion);
var kSigning = CryptoJS.HmacSHA256("aws4_request", kService);

console.log(kSigning.toString()); //returns the expected value of c4afb1cc5771d871763a393e44b703571b55cc28424d1a5e86da6ed3c154a4b9

Так что эта функция Hmac-SHA256 работает правильно на этом входе.Однако на следующем входе Hmac-SHA256 НЕ возвращает ожидаемый результат.

var stringToSign = 'AWS4-HMAC-SHA256\n'+
                '20150830T123600Z\n'+
                '20150830/us-east-1/iam/aws4_request\n'+
                CryptoJS.SHA256(canonString).toString();

CryptoJS.HmacSHA256(kSigning.toString(), stringToSign); //Returns 8a96b6691875490d30d05731cc9aa26be1fd64cf611ed929753b6498075aa886
//Expected value is 5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7
//Trying in opposite order just in case
CryptoJS.HmacSHA256(stringToSign, kSigning.toString()); //Returns fe52b221b5173b501c9863cec59554224072ca34c1c827ec5fb8a257f97637b1
//Still not expected value which is 5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7

Итак, что-то явно не так с моим stringToSign, и я не знаю, что это такое.Я думал, что символ новой строки интерпретируется как два разных символа, а не просто как один символ.Тем не менее, экранирование как '\\ n' не исправило это!Я в недоумении здесь.Вот два документа, за которыми я следовал ( doc1 doc2 ).Кто-нибудь знает, почему я не могу получить ожидаемый результат?

1 Ответ

0 голосов
/ 04 октября 2018

Помните, что дайджест sha256 - это последовательность байтов: это не "нормальная строка".Похоже, что CryptoJS преобразует настоящий дайджест sha256 во что-то другое для удобства, поэтому не делайте этого, и все готово.

Использование библиотеки Node's crypto (которая является встроенным API) а не CryptoJS (который имеет абсолютно ужасную документацию, поэтому его использование довольно сомнительно):

const crypto = require("crypto");

function HMAC(key, text) {
    return crypto.createHmac("sha256", key).update(text).digest();
}

А затем мы формируем канонический хеш:

const canonString = [
    'GET',
    '/',
    'Action=ListUsers&Version=2010-05-08',
    'content-type:application/x-www-form-urlencoded; charset=utf-8',
    'host:iam.amazonaws.com',
    'x-amz-date:20150830T123600Z',
    '',
    'content-type;host;x-amz-date',
    'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
].join('\n');

// note: plain hash, not a secret-key-seeded hash
const canonHash = crypto.createHash("sha256").update(canonString).digest();
console.log("Canonical hash is   :", canonHash.toString('hex'));

Это дает f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59.Затем мы продолжаем:

const kSecret = "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY";
const kDate = HMAC("AWS4" + kSecret,"20150830");
const kRegion = HMAC(kDate,"us-east-1");
const kService = HMAC(kRegion,"iam");
const kSigning = HMAC(kService,"aws4_request");
console.log("kSigning hash is    :", kSigning.toString('hex'));

Что дает c4afb1cc5771d871763a393e44b703571b55cc28424d1a5e86da6ed3c154a4b9: обратите внимание, что мы не делаем какое-либо преобразование в шестнадцатеричное, потому что это шестнадцатеричное дайджест , а не дайджест sha256Это совершенно другая строка.Мы преобразуем только в шестнадцатеричную строку, чтобы сделать дайджест разборчивым в журнале консоли.

Затем, наконец:

const stringToSign = [
    'AWS4-HMAC-SHA256',
    '20150830T123600Z',
    '20150830/us-east-1/iam/aws4_request',
    canonHash.toString('hex')
].join('\n');

const signed = HMAC(kSigning, stringToSign);
console.log("Final signed hash is:", signed.toString('hex'));

Что дает 5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7.Обратите внимание, что здесь у нас было , чтобы превратить канонический хеш в шестнадцатеричную строку, согласно инструкциям на страницах, на которые вы ссылаетесь, но мы не касаемся дайджеста kSigning,это должно оставаться настоящей строкой байта sha256.

...