I am converting a JS script into PHP.
The script uses the CryptoJS library and generates a hash using the following line:
var sha1 = CryptoJS.SHA1("message");
var sig = sha1.toString(CryptoJS.enc.Base64);
I have tried this php code
$sha1 = sha1("message");
$sig = base64_encode($sha1);
But the signature isn't the same, it's longer in php.
Your help is very much appreciated and needed !
John
Ok I just needed to set $raw_output to true in the sha1 function !
$sha1 = sha1("message", true);
Now I look silly
Related
when there is no chinese character, php and node output the same result.
but when this is chinese character, the output of php is correct, the output of node is not correct
const crypto = require('crypto');
function encodeDesECB(textToEncode, keyString) {
var key = new Buffer(keyString.substring(0, 8), 'utf8');
var cipher = crypto.createCipheriv('des-ecb', key, '');
cipher.setAutoPadding(true);
var c = cipher.update(textToEncode, 'utf8', 'base64');
c += cipher.final('base64');
return c;
}
console.log(encodeDesECB(`{"key":"test"}`, 'MIGfMA0G'))
console.log(encodeDesECB(`{"key":"测试"}`, 'MIGfMA0G'))
node output
6RQdIBxccCUFE+cXPODJzg==
6RQdIBxccCWXTmivfit9AOfoJRziuDf4
php output
6RQdIBxccCUFE+cXPODJzg==
6RQdIBxccCXFCRVbubGaolfSr4q5iUgw
The problem is not the encryption, but a different JSON serialization of the plaintext.
In the PHP code, json_encode() converts the characters as a Unicode escape sequence, i.e. the encoding returns {"key":"\u6d4b\u8bd5"}. In the NodeJS code, however, {"key": "测试"} is applied.
This means that different plaintexts are encrypted in the end. Therefore, for the same ciphertext, a byte-level identical plaintext must be used.
If Unicode escape sequences are to be applied in the NodeJS code (as in the PHP code), an appropriate conversion is necessary. For this the jsesc package can be used:
const jsesc = require('jsesc');
...
console.log(encodeDesECB(jsesc(`{\"key\":\"测试\"}`, {'lowercaseHex': true}), 'MIGfMA0G')); // 6RQdIBxccCXFCRVbubGaolfSr4q5iUgw
now returns the result of the posted PHP code.
If the Unicode characters are to be used unmasked in the PHP code (as in the NodeJS code), an appropriate conversion is necessary. For this the flag JSON_UNESCAPED_UNICODE can be set in json_encode():
$data = json_encode($data, JSON_UNESCAPED_UNICODE); // 6RQdIBxccCWXTmivfit9AOfoJRziuDf4
now returns the result of the posted NodeJS code.
I have a problem to verify a string create by crypto.createHmac with Node.js.
I made some test, first in PHP - everything is OK but I can't find the correct way todo this in Node.js:
PHP CODE:
$jsonData = '"face_url":"https:\/\/"';
echo($jsonData);
echo("\n");
$client_secret = 'kqm6FksaIT';
echo hash_hmac("sha256", $jsonData, $client_secret);
Result:
"face_url":"https:\/\/"
34a4eb09a639c9b80713158ae89e7e8311586e6e6d76e09967f4e42a24759b3e
With Node.js, I have a problem with the interpretation of the string:
var crypto = require('crypto');
var str = '"face_url":"https:\/\/"';
console.log(str);
//OK
var buf1 = crypto.createHmac('sha256','kqm6FksaIT').update(str);
var v = buf1.digest('hex');
console.log(v);
//END
RESULT:
"face_url":"https://"
eb502c4711a6d926eeec7830ff34e021ed62c91e574f383f6534fdd30857a907
=> FAIL.
As you can see, the interpretation of the string is different "face_url":"https:\/\/"** VS **"face_url":"https://"**
I have tried a lot of things, Buffer.From base64, utf8, JSON.stringify, JSON.parse but I can't find a solution.
If you try with another string like: '"face_url":"https"' it's OK Result is the same.
I try to validate the key received in a Netatmo POST packet who contain:
"face_url":"https:\/\/netatmocameraimage.blob.core
You can find an implementation of netatmo webhook in PHP here:
https://github.com/Netatmo/Netatmo-API-PHP/blob/master/Examples/Webhook_Server_Example.php
After reflexion, the only difference between codes was the interpretation of request.body.
In PHP, it seems to be in plain text.
Nodejs parses the request in JSON format ...
After that supposition, i made some test with NodeJS this morning, i configured the expres server with the following option:
var express = require('express');
var crypto = require('crypto');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.text({type:"*/*"}));
After that, the string appears correctly with these famous "/" :
console.log RESULT :
,"face_url":"https://netatmocameraimage.blob.core.windows.net/production/
And voila! The HMAC is now CORRECT!
The HMAC from NETATMO is calculated on brut text and not from JSON!
In the PHP code, only the escape sequences \\ and \' are recognized in a single quoted expression, in all other cases the backslash is interpreted as a literal backslash, i.e. \/ is interpreted as a literal backslash followed by a literal slash (see here, sec. Single quoted). This explains the output of the PHP code:
$jsonData = '"face_url":"https:\/\/"';
...
Output:
"face_url":"https:\/\/"
34a4eb09a639c9b80713158ae89e7e8311586e6e6d76e09967f4e42a24759b3e
In JavaScript, the backslash is ignored for characters that do not represent an escape sequence, (see here, last passage), i.e. an \/ is equivalent to a literal slash. This explains the output of the JavaScript code:
var str = '"face_url":"https:\/\/"';
...
Output:
"face_url":"https://"
eb502c4711a6d926eeec7830ff34e021ed62c91e574f383f6534fdd30857a907
So in order for the JavaScript code to give the same result as the PHP, the backslash must be masked:
var str = '"face_url":"https:\\/\\/"';
...
Output:
"face_url":"https:\/\/"
34a4eb09a639c9b80713158ae89e7e8311586e6e6d76e09967f4e42a24759b3e
Presumably the string with the \/ is the result of a JSON serialization in PHP with json_encode(), which escapes the / by default, i.e. converts it to \/, see also here. In JavaScript, / is simply serialized as /. Note that in PHP the escaping of / can be disabled with JSON_UNESCAPED_SLASHES, see also here.
I have the following script:
hex_string = "c23dba5fcac1048b3c050266ceb6a0e870670021"
hex_bytes = bytearray.fromhex(hex_raw)
print(hex_bytes.reverse())
The problem it prints/returns None. I was wondering, because in this example it works.
Thanks in advance.
I found the issue. The method .reverse() dont return anything, but changes the bytearray, so the code must be:
hex_string = "c23dba5fcac1048b3c050266ceb6a0e870670021"
hex_bytes = bytearray.fromhex(hex_raw)
hex_bytes.reverse()
print(hex_bytes)
I'm calculating SHA1 using the following PHP code:
$hash = base64_encode(sha1($password.$key, true).$key);
But when I do this in Node.js, it does not give me the same result:
var hash = crypto.createHash('sha1').update(password + key).digest('base64');
Why are the results different?
In your PHP code, you're appending the key to the sha1 before passing it to base64:
sha1($password.$key, true).$key
In order to replicate that in Node.js, you'll need to do the same:
var hash = crypto.createHash('sha1').update(password + key).digest('hex');
var result = new Buffer(hash + key).toString('base64');
Edit: after looking at the PHP docs on sha1, it looks like the second parameter being passed to sha1 is going to return non-hex data:
If the optional raw_output is set to TRUE, then the sha1 digest is instead returned in raw binary format with a length of 20, otherwise the returned value is a 40-character hexadecimal number.
So in order for the two snippets to function the same, you'd also need to modify the PHP to not pass that parameter:
$hash = base64_encode(sha1($password.$key).$key);
You need to append key in the nodejs:
// php
$hash = base64_encode(sha1($password.$key, true).$key);
// see this ^^^^
// node
var hash = crypto.createHash('sha1').update(password + key).digest('base64') + key;
// add this ^^^^^^
Have been trying this for 2 days but failed miserably. We are using appcelerator 5.1.0.
I'm able to hash a string using the module Securely . However the result string is in hex format and i need it to be in base64 encoded string.
Tried the Ti.Utils.base64encode function but the result doesn't match what is generated at the backend. Here's my code snippet:
function convertHexToBase64(hexStr){
console.log("hex: "+hexStr);
var hexArray = hexStr
.replace(/\r|\n/g, "")
.replace(/([\da-fA-F]{2}) ?/g, "0x$1 ")
.replace(/ +$/, "")
.split(" ");
var byteString = String.fromCharCode.apply(null, hexArray);
var base64String = Ti.Utils.base64encode(byteString).toString();
console.log("base64 string:"+base64String);
return base64String;
}
Tried to find other modules to use and the node's Buffer is the closest i can get but am not sure how to use a node class in appcelerator...
Anyone can shed a light or two? Thanks.
Finally did it with the help of Forge, putting the steps here for future reference
Create a folder under the lib folder, named it forge
Install the module to local machine (via node), copy the whole contents of the js folder into the forge folder.
In the code, create the object:
var forge = require('forge/forge');
Hash the string first to get a buffer object, then encode it to base64 string.
var md = forge.md.sha512.create();
md.update(saltedText);
var buffer = md.digest();
result = forge.util.encode64(buffer.getBytes());