locutusjs / locutus

Bringing stdlibs of other programming languages to JavaScript for educational purposes
https://locutus.io
MIT License
3.72k stars 1.12k forks source link

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

Closed vidhishri closed 5 months ago

vidhishri commented 7 years ago

Description

@node 6.3

hash--- e81785df79706d08e4080fcbd030f636867d65ef318b7ee63d2ea6649a04da27 vpcUrl--- https://migs-mtf.mastercard.com.au/vpcpay?vpc_AccessCode=D81B08AB&vpc_Amount=10&vpc_Command=pay&vpc_Currency=KES&vpc_Locale=en&vpc_MerchTxnRef=iwlmrsjv-2&vpc_Merchant=00000153&vpc_OrderInfo=iwlmrsjv&vpc_ReturnURL=http://localhost:8080/payment&vpc_Version=1&vpc_SecureHashType=sha256&vpc_SecureHash=e81785df79706d08e4080fcbd030f636867d65ef318b7ee63d2ea6649a04da27

@node 5.5 hash--- 22821dc78871c6c11c297884a757763c86f0cb568ed5da48fcac5b43c4d194ef vpcUrl--- https://migs-mtf.mastercard.com.au/vpcpay?vpc_AccessCode=D81B08AB&vpc_Amount=10&vpc_Command=pay&vpc_Currency=KES&vpc_Locale=en&vpc_MerchTxnRef=iwlnidh5-1&vpc_Merchant=00000153&vpc_OrderInfo=iwlnidh5&vpc_ReturnURL=http://localhost:8080/payment&vpc_Version=1&vpc_SecureHashType=sha256&vpc_SecureHash=22821dc78871c6c11c297884a757763c86f0cb568ed5da48fcac5b43c4d194ef

BarryCarlyon commented 7 years ago

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…

kvz commented 7 years ago

/cc @Reggino

Reggino commented 7 years ago
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?

BarryCarlyon commented 7 years ago

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

Reggino commented 7 years ago

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

BarryCarlyon commented 7 years ago

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";
Reggino commented 7 years ago

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
BarryCarlyon commented 7 years ago

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

Reggino commented 7 years ago

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?

BarryCarlyon commented 6 years ago

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…

Reggino commented 6 years ago

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?

BarryCarlyon commented 6 years ago

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

Reggino commented 6 years ago

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

BarryCarlyon commented 6 years ago

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)

Reggino commented 6 years ago

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

BarryCarlyon commented 6 years ago

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.

Reggino commented 6 years ago

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.

BarryCarlyon commented 6 years ago

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

github-actions[bot] commented 5 months ago

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 14 days.