Is Javascript's JSON.stringfy the same as PHP's json_encode?

833

I'm trying to do an HMAC SHA256 hash of stringified data using both JavaScript (CryptoJS Libraries) and PHP (built in HMAC function). I'm concerned that the JavaScript JSON.stringify will not be consistent/identical to the PHP json_encode() function. Is there a better approach to this stringifying of the data (object/array)?

Here's my test, which works. But, I'm concerned about Spanish characters and other encodings/entities that the code may encounter.

<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>

Additional thoughts: I'm worried about spacing/quoting differences with JSON methods. Perhaps I should loop thru the object/array and use the "values" only to produce the string of data to be HMAC'ed? Assuming this can be kept to a single array/object, that should produce a consistent "values" string. But, then how do you keep a consistent ordering. I assume it could be ordered by key first.

396

Answer

Solution:

As @Pointy mentioned in the comments, the output ofJSON.stringify andjson_encode may have slight differences in two scenarios:

  1. An object's key/value ordering (objects are unordered)
  2. "Simple" values

On "simple" values, the PHP documentation has this to say:

Like the reference JSON encoder, json_encode() will generate JSON that is a simple value (that is, neither an object nor an array) if given astring,integer,float orboolean as an inputvalue. While most decoders will accept these values as valid JSON, some may not, as the specification is ambiguous on this point.
To summarise, always test that your JSON decoder can handle the output you generate from json_encode().

If you're worried about the data being 100% faithfully recreated, consider encoding the data before storing it (i.e. base64_encode it).

P.S. If you're going to HMAC the data, you need to 1) only HMAC the values and 2) make sure you always access the values in the same order every time because JSON makes no ordering promises for anything except arrays.

People are also looking for solutions to the problem: javascript - JQuery table in php

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.