Below is the password hashing algorithm that I have to use for the control panel that I create. The original function is in PHP, but I rewrite it for use with Node.js in JavaScript.
Everything seems fine, but then I call in fModand get a failure:
RangeError: toFixed() digits argument must be between 0 and 20
The function fModworks correctly, but with different values. I highlighted the line in fModwhich throws an exception.
The correct password hash should be:
0x31c7296631df873d0891b7b77ae0c6c6
the code:
var pass = "Cake99";
console.log(pCrypt2(pass));
function pCrypt2(plain) {
var array_mul = [213119, 213247, 213203, 213821];
var array_add = [2529077, 2529089, 2529589, 2529997];
var dst = Array.apply(null, new Array(16)).map(Number.prototype.valueOf,0);
var key = Array.apply(null, new Array(16)).map(Number.prototype.valueOf,0);
for (var i = 0; i < plain.length; i++ ) {
dst[i] = key[i] = ord(plain.substr(i, 1));
}
var val = [];
for (var i = 0; i <= 3; i++ ) {
val[i] = fmod((key[i * 4 + 0] + key[i * 4 + 1] * 0x100 + key[i * 4 + 2] * 0x10000 + key[i * 4 + 3] * 0x1000000) * array_mul[i] + array_add[i], 4294967296 );
}
for (i = 0; i <= 3; i++ ) {
key[i * 4 + 0] = val[i] & 0xff;
key[i * 4 + 1] = val[i] / 0x100 & 0xff;
key[i * 4 + 2] = val[i] / 0x10000 & 0xff;
key[i * 4 + 3] = val[i] / 0x1000000 & 0xff;
}
dst[0] = dst[0] ^ key[0];
for (var i = 1; i <= 15; i++ ) {
dst[i] = dst[i] ^ dst[i - 1] ^ key[i];
}
for (var i = 0; i <= 15; i++ ) {
if (dst [i] == 0 ) {
dst [i] = 0x66;
}
}
var encrypted = "0x";
for (var i = 0; i <= 15; i++ ) {
if (dst [i] < 16 ) {
encrypted = encrypted + "0";
}
encrypted = encrypted + dst[i].toString(16);
}
return (encrypted);
}
function ord(string) {
var str = string + '',
code = str.charCodeAt(0);
if (0xD800 <= code && code <= 0xDBFF) {
var hi = code;
if (str.length === 1) {
return code;
}
var low = str.charCodeAt(1);
return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
}
if (0xDC00 <= code && code <= 0xDFFF) {
return code;
}
return code;
}
function fmod(x, y) {
var tmp, tmp2, p = 0,
pY = 0,
l = 0.0,
l2 = 0.0;
tmp = x.toExponential()
.match(/^.\.?(.*)e(.+)$/);
p = parseInt(tmp[2], 10) - (tmp[1] + '')
.length;
tmp = y.toExponential()
.match(/^.\.?(.*)e(.+)$/);
pY = parseInt(tmp[2], 10) - (tmp[1] + '')
.length;
if (pY > p) {
p = pY;
}
tmp2 = (x % y);
if (p < -100 || p > 20) {
l = Math.round(Math.log(tmp2) / Math.log(10));
l2 = Math.pow(10, l);
return (tmp2 / l2)
.toFixed(l - p) * l2;
} else {
return parseFloat(tmp2.toFixed(-p)); <<< ---- FAILS HERE ---------
}
}
// PHP Original --------------------------------
function encrypt( $plain )
{
$array_mul = array ( 0 => 213119, 1 => 213247, 2 => 213203, 3 => 213821 );
$array_add = array ( 0 => 2529077, 1 => 2529089, 2 => 2529589, 3 => 2529997 );
$dst = $key = array ( 0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0, 10 => 0, 11 => 0, 12 => 0, 13 => 0, 14 => 0, 15 => 0 );
for ( $i = 0; $i < strlen ( $plain ); $i++ ) {
$dst [ $i ] = $key [ $i ] = ord ( substr ( $plain, $i, 1 ) );
}
for ( $i = 0; $i <= 3; $i++ ) {
$val [ $i ] = fmod ( ( $key [ $i * 4 + 0 ] + $key [ $i * 4 + 1 ] * 0x100 + $key [ $i * 4 + 2 ] * 0x10000 + $key [ $i * 4 + 3 ] * 0x1000000 ) * $array_mul [ $i ] + $array_add [ $i ], 4294967296 );
}
for ( $i = 0; $i <= 3; $i++ ) {
$key [ $i * 4 + 0 ] = $val [ $i ] & 0xff;
$key [ $i * 4 + 1 ] = $val [ $i ] / 0x100 & 0xff;
$key [ $i * 4 + 2 ] = $val [ $i ] / 0x10000 & 0xff;
$key [ $i * 4 + 3 ] = $val [ $i ] / 0x1000000 & 0xff;
}
$dst [ 0 ] = $dst [ 0 ] ^ $key [ 0 ];
for ( $i = 1; $i <= 15; $i++ ) {
$dst [ $i ] = $dst [ $i ] ^ $dst [ $i - 1 ] ^ $key [ $i ];
}
for ( $i = 0; $i <= 15; $i++ ) {
if ( $dst [ $i ] == 0 ) {
$dst [ $i ] = 0x66;
}
}
$encrypted = "0x";
for ( $i = 0; $i <= 15; $i++ ) {
if ( $dst [ $i ] < 16 ) {
$encrypted .= "0";
}
$encrypted .= dechex($dst[$i]);
}
return ( $encrypted );
}