Какова ваша функция hmac-sha1, откуда она? Если он принимает JSON String
в качестве входных данных, то здесь происходит неявный шаг кодирования в байты, поскольку SHA1 работает с байтами, а не с единицами кода UTF-16, такими как JS String
.
Я подозреваю, что ваша JS-функция использует кодирование типа «одна кодовая единица n на байт n» для простых вычислений с помощью таких инструментов, как getCharCodeAt
. Это фактически то же самое, как если бы ввод строки символов был закодирован в ISO-8859-1. Принимая во внимание, что если вы используете encodeURIComponent
или публикуете необработанные символы через XMLHttpRequest, неявная кодировка там - UTF-8.
Вы можете преобразовать String
в формат UTF-8-байтов-хранимых-в-единицах кода для функции JS hmac-sha1, которая может сделать ее соответствующей PHP. Для этого есть хитрая идиома:
var utf8= unescape(encodeURIComponent(s));
При размещении JSON I base64 и в любом случае urlencode
URL-кодирования должно быть достаточно (с encodeURIComponent
, а не escape
, что является неправильным для абсолютно всего , за исключением обратного шага уловки преобразования UTF-8 выше).
Кстати, какова цель этого? Вы знаете, что это никак не защищает соединение между браузером и сервером, да?
Edit:
Я использую jssha.sourceforge.net для sha1-hmac. В PHP я использую hash_hmac.
У меня работает:
var data= '\u017E, \u010D, \u0161'; // 'ž, č, š' in a Unucode string
var utf8bytes= unescape(encodeURIComponent(data));
var hmac= new jsSHA(utf8bytes).getHMAC('foo', 'ASCII', 'SHA-1', 'HEX');
alert(hmac); // 5d15f0b9...
var form= 'message='+encodeURIComponent(data)+'&hmac='+encodeURIComponent(hmac);
xmlhttprequest.send(form);
...
$utf8bytes= $_POST['message']; // "\xc5\xbe, \xc4\x8d, \xc5\xa1"
// which is 'ž, č, š' as UTF-8 in byte string
$hmac= hash_hmac('sha1', $utf8bytes, 'foo');
echo $hmac; // 5d15f0b9...
echo strtolower($hmac)===strtolower($_POST['hmac']); // true
Используется двоичный ('ASCII'
to jsSHA) ключ foo
. Если вы используете двоичный ключ с символами, отличными от ASCII, вам необходимо убедиться, что эти также правильно закодированы, так же, как данные.
Ключ для HMAC - это общий секрет между сервером и клиентом, который ранее был обменен по безопасному соединению.
Это не только ключ, который вы должны будете отправить через безопасное соединение, но и вся страница и все сценарии в ней. В противном случае человек в середине атаки может саботировать ваши скрипты по пути в браузер, чтобы заменить их версией, которая использовала секретный ключ для подписи поддельных сообщений. Если у вас есть HTTPS-сервер для всего этого, хорошо. Я не уверен, что HMAC будет делать в этом случае, хотя, кажется, это немного связано с анти-XSRF-схемой.