Я пытаюсь сделать HMAC SHA256 хеш-код строки данных, используя как JavaScript (CryptoJS Libraries), так и PHP (встроенная функция HMAC). Я обеспокоен тем, что JavaScript JSON.stringify не будет согласован / идентичен функции PHP json_encode (). Есть ли лучший подход к этой последовательности данных (объект / массив)?
Вот мой тест, который работает. Но меня беспокоят испанские символы и другие кодировки / сущности, с которыми может столкнуться код.
<h1>Testing HMAC Javascript to PHP Comparison</h1>
<br><br>
<div id="php_mac">
<?php
// Testing HMAC
$security_key = '0123456789';
$obj = array(
'field1' => 1,
'field2' => '2',
'field3' => "'",
);
// Calculate HMAC SHA256
$str_data = json_encode($obj);
echo "PHP str_data: ".$str_data."<br>";
$hash = hash_hmac('sha256', $str_data, $security_key, true);
$hashInBase64 = base64_encode($hash);
echo "PHP hashInBase64: ".$hashInBase64;
?>
</div>
<br><br>
<div id="javascipt_hmac">
<div id="javascript_str_data"></div>
<div id="javascript_hashInBase64"></div>
<script>
var security_key = '0123456789';
var obj = {
'field1': 1,
'field2': '2',
'field3': "'",
};
// Create security hash based on posted data
var str_data = JSON.stringify(obj);
$('#javascript_str_data').html('str_data: '+str_data);
// Using CryptoJS to HMAC SHA256 the str_data
var hash = CryptoJS.HmacSHA256(str_data, security_key);
var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
$('#javascript_hashInBase64').html('JS hashInBase64: '+hashInBase64)
</script>
</div>
Дополнительные мысли: я беспокоюсь о разнице / цитировании различий с помощью методов JSON. Возможно, мне следует пройти через объект / массив и использовать «значения» только для создания строки данных для HMAC? Предполагая, что это может быть сохранено в одном массиве / объекте, это должно привести к согласованной строке «значений». Но тогда как вы соблюдаете постоянный порядок. Я предполагаю, что это может быть заказано сначала ключом.
Как отметил @Pointy в комментариях, вывод JSON.stringify
а также json_encode
могут быть небольшие различия в двух сценариях:
На «простых» значениях PHP документация имеет это сказать:
Как и эталонный кодер JSON, json_encode () сгенерирует JSON, представляющее собой простое значение (то есть ни объект, ни массив), если ему
string
,integer
,float
или жеboolean
в качестве входаvalue
, Хотя большинство декодеров примут эти значения как допустимые JSON, некоторые могут и не принять, поскольку в этом отношении спецификация неоднозначна.
Подводя итог, всегда проверяйте, может ли ваш JSON-декодер обрабатывать вывод, который вы генерируете из json_encode ().
Если вы беспокоитесь о том, что данные на 100% точно воссозданы, рассмотрите возможность кодирования данных перед их сохранением (то есть base64_encode).
Постскриптум Если вы собираетесь обрабатывать данные в HMAC, вам необходимо: 1) только значения HMAC и 2) убедиться, что вы всегда обращаетесь к значениям в одном и том же порядке каждый раз, потому что JSON не дает никаких обещаний упорядочения ни для чего, кроме массивов.
Других решений пока нет …