I'm trying to decode Firefox Sync data using javascript, porting one php library which does it (https://github.com/mikerowehl/firefox-sync-client-php). The idea is to decode sync data without sending sync key to the server. This is just context, the problem I have is much more specific.

One portion of code requires using sha256 to obtain certain key. I would like to replicate it in javascript. The approach I've tried, with CryptoJS, is this:

PHP code:

$key = hash_hmac("sha256",'OLA K ASE','CLAVE', false);
print $key;

Equivalent Javascript code (previously, I've included http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/hmac-sha256.js):

var hash = CryptoJS.HmacSHA256("OLA K ASE", "CLAVE");
console.log(hash.toString());

This works fine. In each case, output is 9591d44df0c8e2d7a1f400f41117c536e10f58d7e28bdc1cad9d81e70290bc1b, which I suppose is correct.

But, when I'm trying to encode non-ascii strings, results differ. For example, with this PHP code:

function hexstring($str){
    return preg_replace('/\\\\x([0-9a-f]{2})/e', 'chr(hexdec(\'$1\'))', $str);
}
$text = hexstring('\x00\x44\xb0\x2c\x0b');
$key = hexstring('\xd6\xf8\xb0\x2c\x0b');
$hash = hash_hmac("sha256",$text,$key, false);
print $hash;

I get 0697f5528c996006ffeb09b9130bf8e9056563245656d405e233bcafdbffb645. But with the 'equivalent' javascript code:

var text = "\x00\x44\xb0\x2c\x0b";
var key = "\xd6\xf8\xb0\x2c\x0b";
hash = CryptoJS.HmacSHA256(text,key);
console.log(hash.toString());

I get 13c983b69f82c277815c03d13e90b1ec1e9cbca2b6912ad1f8224f3de8b82130, a different value.

I thought it could be caused by non-ascii character, so I did a quick test:

$text = '';
for($i = 0;$i < 10; $i++){
    $text .= chr($i);
}
$key = '';
for($i = 0;$i < 10; $i++){
    $key .= chr($i*2);
}
$hash = hash_hmac("sha256",$text,$key, false);
print $hash;

And, javascript equivalent:

var text = '';
for(i = 0;i < 10; i++){
    text += String.fromCharCode(i);
}
var key = '';
for(i = 0;i < 10; i++){
    key += String.fromCharCode(i*2);
}
var hash = CryptoJS.HmacSHA256(text, key);
console.log(hash.toString());

In both cases, output is c5d7adbbabcec5416c6b7a1f01e17e42d95a529f5bcc805d9b04b93f33994c9d.

This is a big WTF? for me. Could somebody give me a piece of advice of how to continue with this?

有帮助吗?

解决方案

Solved. It was a problem with character codes. Instead of this:

var text = "\x00\x44\xb0\x2c\x0b";
var key = "\xd6\xf8\xb0\x2c\x0b";
hash = CryptoJS.HmacSHA256(text,key);

I should indicate CryptoJS that they were Latin-1 encoded strings:

var text = CryptoJS.enc.Latin1.parse("\x00\x44\xb0\x2c\x0b");
var key = CryptoJS.enc.Latin1.parse("\xd6\xf8\xb0\x2c\x0b");
hash = CryptoJS.HmacSHA256(text,key);

I don't know clearly why is this happening, so if somebody could explain it with a little bit of detail it would be great.

其他提示

Try that:

$text = "\x00\x44\xb0\x2c\x0b";
$key = "\xd6\xf8\xb0\x2c\x0b";
$hash = hash_hmac("sha256",$text,$key, false);
print $hash;

It's proabably because the preg_* functions have a problem with these special characters. And PHP supports \x12 hex-encoding without any function.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top