Javascript 的 JSON.stringfy 和 PHP 的 json_encode 一样吗?

jjw*_*ign 5 javascript php json cryptojs

我正在尝试使用 JavaScript(CryptoJS 库)和 PHP(内置 HMAC 函数)对字符串化数据进行 HMAC SHA256 哈希。我担心 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>
Run Code Online (Sandbox Code Playgroud)

其他想法:我担心与 JSON 方法的间距/引用差异。也许我应该遍历对象/数组并仅使用“值”来生成要进行 HMAC 处理的数据字符串?假设这可以保留在单个数组/对象中,那应该会产生一致的“值”字符串。但是,那么你如何保持一致的排序。我认为它可以先按钥匙订购。

Mr.*_*ama 2

正如@Pointy在评论中提到的,JSON.stringify和的输出json_encode在两种情况下可能略有不同:

  1. 对象的键/值排序(对象是无序的
  2. “简单”的价值观

关于“简单”值,PHP 文档是这样说的:

与参考 JSON 编码器一样,如果给定string、或作为输入,json_encode() 将生成简单值 JSON(即既不是对象也不是数组)。虽然大多数解码器会接受这些值作为有效的 JSON,但有些解码器可能不会,因为规范在这一点上不明确。 总而言之,请始终测试您的 JSON 解码器是否可以处理从 json_encode() 生成的输出。integerfloatbooleanvalue

如果您担心数据是否 100% 忠实地重新创建,请考虑在存储数据之前对其进行编码(即对其进行 base64 编码)。

PS如果您要对数据进行 HMAC,则需要 1)仅对值进行 HMAC 并 2)确保每次始终以相同的顺序访问值,因为 JSON 对除数组之外的任何内容都没有排序承诺。