locutusjs / locutus

Bringing stdlibs of other programming languages to JavaScript for educational purposes

Home Page:https://locutus.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Getting different pack conversion for nodejs 5.5 and 6.3 for the same key

vidhishri opened this issue · comments

I am seeing a somewhat similar issue.

The pack for H* when doing with Node 6.9.1 doesn't match the pack for PHP7

So looks like I'm back to making node do a call over child process to exec php…

var pack = require('locutus/php/misc/pack')
console.log(pack('H*', 'ABCDEFGHIJKLMNOP'));

OUTPUT in node.js 5.5.0 and 6.3.1 and 6.9.1

«Íï

@BarryCarlyon or @vidhishri could you please provide same sample code to reproduce this issue?

node 6.9.1 returns the same output as you post.
PHP 7.0.12 throws a ton of warnings (illegal hex digit)

Sorry, I guess this is a bad example. I tried the same with a valid hex-string, but with the same result: all node versions give the same result...

An example with more data

If I H*

Input
packed H*
to base 64

PHP7

1f68454837028022c9227b89e23a966e83fa02a1
hEH7?"?"{??:?n???
H2hFSDcCgCLJInuJ4jqWboP6AqE=

Node 6.9.1

1f68454837028022c9227b89e23a966e83fa02a1
hEH7�"É"{�â:�n
H2hFSDcCwoAiw4kie8KJw6I6wpZuwoPDugLCoQ==

In this example my input string is the sha1 of something

(The sha1 in this case has something outputted from H* packing to make it up, but that doesn't matter as for this example I'm testing the same input string the sha1 result)

var pack = require('locutus/php/misc/pack')
//console.log(pack('H*', 'ABCDEFGHIJKLMNOP'));
console.log(pack('H*', '1f68454837028022c9227b89e23a966e83fa02a1'));
console.log(new Buffer(pack('H*', '1f68454837028022c9227b89e23a966e83fa02a1')).toString('base64'))

and

<?php
$pack = pack('H*', '1f68454837028022c9227b89e23a966e83fa02a1');
echo $pack . "\n";
$password_digest = base64_encode($pack);
echo $password_digest . "\n";

The base64_encode-function doesn't seem binary safe.

PHP 5-7 and node 4-6.9 output the same result for

bin2hex(pack('H*', '1f68454837028022c9227b89e23a966e83fa02a1'))

>> 1f68454837028022c9227b89e23a966e83fa02a1

The base64 encode doesn't matter in this case as the strings are "wrong"/different before passing to base64, (I'll look into binary safety).

Either way, the remote API I'm talking to rejects the auth string generated with Node/locutus but accepts the PHP Equivalent. (it's a mess of packing and base64'ing), (I've never found a working Pack function is JS that achieves what I need).

Yay for "Web Services Security Username Token Profile"…

I think the binary value and thus the strings are exactly the same, otherwise bin2hex couldn't reproduce the exact same result.

I think the string differences you mention are related to the character-set configuration of the output method. Could you check the default_encoding="utf-8"setting in your php.ini? (and/or other CLI output character-set configuration) Are your running PHP and node.js both through CLI using a terminal with the exact same output settings?

So a year and a bit later…

123123123122018-03-09T11:58:36+00:00]¹rc³NÈTÙ󅶾^ñÔT��{

Is the PHP generated.

123123123122018-03-09T11:58:36+00:00]¹rc³NÈTÙó¶¾^ñÔT��{

The triple elipisisisisis just doesn't seem to appear for any of the methods I've tried.

Is the node generated version.

I've tried a handful of different methods and functions I've found. Retried locutus and same issue.

The PHP generated digest is accepted by the remote server, the node generated is rejected.

And yes same CLI window.

I'm using, in node to fetch from PHP:

    var r = child_process.execSync('php ' + __dirname + '/encrypt.php', {
        encoding: 'utf8'
    });

    r = JSON.parse(r);

PHP correct, everything else isn't. I'm a bit at a loss again…

Can you write the output in both PHP and Node.js to a file (make sure to do that binary) and inspect the difference with a HEX-editor?

Pack test of the concatenated digest:

image

php https://gist.github.com/BarryCarlyon/c2f12b1994a67c671906b924e15bb2f6
node https://gist.github.com/BarryCarlyon/13debcbd6b89520444ede8b39bdd281a

(forgot to set the language on the gists but you get the gist)

$ node -v
v8.9.1
$ php -v
PHP 7.0.25 (cli) (built: Oct 27 2017 12:56:53) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies

Seems that the first pack (of a sha1'ed string) works fine (didn't explicity hex compare here)
But the second pack (of a concatenated string that is sha1'ed) doesn't

Pack test on the sha'ed password

image

@BarryCarlyon . Thanks.

There is a lot of code in gists unrelated to encoding the string. Could you please narrow it down to a fixed, single string that is encoded differently between the two languages?

Not really.

The fault might be the second pack? Since I pack one part, concat three strings, and pack the result.

The issue might be in how locutus is packing a already packed string as the first pack passes the test.

Hence I included my full code for this example use case.

(But I have observed pack faults on the first pack previously but seems ok today where I just pack the password sha1)

Simplified gists:

php https://gist.github.com/Reggino/6c48432489a5ce3979c780b948e88b1a
node https://gist.github.com/Reggino/4ff146d137b9ed72de54df2b78fd0e16

Result:

image

As you can see, the output may LOOK different, because of different character encoding settings and handling between the languages. But when you compare the output as binary, it is exactly the same....

Now compare with my script when I'm packing something packed.

Is the fault in my string concat and repack then?

string a concat string b concat packed(d)
pack the whole thing.

Packing twice has a different result, but shows the following warnings in PHP:

PHP Warning:  pack(): Type H: illegal hex digit ] in /data/scratch/php.php on line 3
PHP Warning:  pack(): Type H: illegal hex digit � in /data/scratch/php.php on line 3
etc.

A non-HEX string cannot be processed by format 'H*'. The result is unpredictable.

Hmm the remote API I'm sending to, accepts the digest that I double pack via PHP but rejects the digest double packed by locutus.

More tinkering needed then, or I need to annoy the API people