node.js - PHP function in node js ← (PHP, JavaScript, Node.js, HTML)

Tried to convert the following PHP function to Node.js but both are showing different output. The out of node.js function should be equal to that of PHP. Below is the code I have tried. I have also attached the hexdump value.

PHP

function hextobin() {

    $hexString = md5(''); //d41d8cd98f00b204e9800998ecf8427e
    $length = strlen($hexString);
    $binString = "";
    $count = 0;
    while ($count < $length) {
        $subString = substr($hexString, $count, 2);
        $packedString = pack("H*", $subString);

        if ($count == 0) {
            $binString = $packedString;
        } else {
            $binString .= $packedString;
        }

        $count += 2;
    }
    return $binString;
}

Output = пїЅпїЅЩЏпїЅпїЅ пїЅпїЅпїЅB~

Hexdump -C value of above output = 

00000000  ef bf bd 1d ef bf bd d9  8f ef bf bd 04 ef bf bd  |................|
00000010  20 ef bf bd ef bf bd ef  bf bd 42 7e 0a           | .........B~.|
0000001d

Node.JS

exports.hex2bin = (key) => {
    const m = crypto.createHash('md5');
    m.update(key);
    const hexString = m.digest('hex');
    let binString ="";
    let length = hexString.length;
    let count = 0;

    while (count < length) {

        const sub = hexString.substr(count, 2);
        let packedString =  Buffer.from(sub, "hex");

        if (count === 0) {
            binString = packedString;
        } else {
            binString += packedString;
        }

        count += 2;
    }

    return binString;
};

Output = пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅB~

Hexdump -C value of above output = 

00000000  ef bf bd 1d ef bf bd ef  bf bd ef bf bd ef bf bd  |................|
00000010  04 ef bf bd ef bf bd 20  ef bf bd ef bf bd ef bf  |....... ........|
00000020  bd 42 7e 0a                                       |.B~.|
00000024

Any help will be appreciated.

Answer



Solution:

In PHP a string has no intrinsic encoding. It's just a series of bytes. In Javascript strings are UTF-16.

To deal with something equivalent to a php string in node the Buffer class is already an array of unsigned 8 bit bytes. See the node manual on Buffer for this quote:

In Node.js, Buffer objects are used to represent binary data in the form of a sequence of bytes. Many Node.js APIs, for example streams and file system operations, support Buffers, as interactions with the operating system or other processes generally always happen in terms of binary data.

The Buffer class is a subclass of the Uint8Array class that is built into the JavaScript language. A number of additional methods are supported that cover additional use cases. Node.js APIs accept plain Uint8Arrays wherever Buffers are supported as well.

The Buffer.from utility function you are using will read the entire hex string in one go rather than converting each pair of hex characters.

Proof of concept:

let hex2bin = () => {
    let hexString = 'd41d8cd98f00b204e9800998ecf8427e';
    let packedString =  Buffer.from(hexString, "hex");
    return packedString;
};

process.stdout.write(hex2bin());

hexdump

$ node test.js | hexdump -C
00000000  d4 1d 8c d9 8f 00 b2 04  e9 80 09 98 ec f8 42 7e  |..............B~|
00000010

PHP Script (based on your original code):

function hextobin() {
    //
    //$hexString = 'd41d8cd98f00b204e9800998ecf8427e';
    $hexString = md5('');
    $length = strlen($hexString);
    $binString = "";
    $count = 0;
    while ($count < $length) {
        $subString = substr($hexString, $count, 2);
        $packedString = pack("H*", $subString);

        if ($count == 0) {
            $binString = $packedString;
        } else {
            $binString .= $packedString;
        }

        $count += 2;
    }
    return $binString;
}
echo hextobin();

hexdump

$ php -f hex2bin.php | hexdump -C
00000000  d4 1d 8c d9 8f 00 b2 04  e9 80 09 98 ec f8 42 7e  |..............B~|
00000010

Source