Reputation: 1913
I am trying to "encrypt" a string (js code) with php, and then decode it using javascript.
This is the php function:
function xor_string( $text, $xorKey ) {
$xored = '';
$chars = str_split( $text );
$i = 0;
while ( $i < count( $chars ) ) {
$xored .= chr( ord( $chars[$i] ) ^ $xorKey );
$i++;
}
return $xored;
}
This is the js function:
function xor_string( str, key ) {
var xored = "";
for (i=0; i<str.length;i++) {
var a = str.charCodeAt(i);
var b = a ^ key;
xored = xored+String.fromCharCode(b);
}
console.log(xored);
}
This work way both ways with certain keys but with others it fail, for example:
echo urlencode( xor_string( 'document.location.href.search', 67 ) );
Returns:
%27%2C+6.%26-7m%2F%2C+%227%2A%2C-m%2B1%26%25m0%26%221+%2B
And when I try to "decode" it with javascript using:
var str = decodeURIComponent("%27%2C+6.%26-7m%2F%2C+%227%2A%2C-m%2B1%26%25m0%26%221+%2B");
xor_string( str, 67 );
It returns:
dohument.lohation.href.searhh
Anyone knows why this is happening?
With some "keys" such as 120 and others it works fine, but with many others it fails.
Upvotes: 0
Views: 2193
Reputation: 9130
A better solution is to use rawurlencode()
instead of urleconde()
.
rawurlencode()
will convert a space to '%20' but urlencode()
will convert a space to '+'. '%20' is what decodeURIComponent()
is expecting for a space.
See the following full example:
<?php
function xor_string( $text, $xorKey ) {
$xored = '';
$chars = str_split( $text );
$i = 0;
while ( $i < count( $chars ) ) {
$xored .= chr( ord( $chars[$i] ) ^ $xorKey );
$i++;
}
return $xored;
}
?><html>
<body>
Encoded (php):
<div id="phpUrlEncode">
<?=urlencode( xor_string( 'document.location.href.search', 67 ) )?>
</div>
<div id="phpRawUrlEncode">
<?=rawurlencode( xor_string( 'document.location.href.search', 67 ) )?>
</div>
<br />
Decoded (js):
<div id="jsDecodeUrl"></div>
<div id="jsDecodeRawUrl"></div>
<script type="text/javascript">
function decodeStr(rawId,displayId) {
var raw = document.getElementById(rawId).innerHTML;
document.getElementById(displayId).innerHTML = xor_string(decodeURIComponent(raw),67);
}
function xor_string( str, key ) {
var xored = "";
for (i=0; i<str.length;i++) {
var a = str.charCodeAt(i);
var b = a ^ key;
xored = xored+String.fromCharCode(b);
}
//console.log(xored);
return xored;
}
decodeStr('phpUrlEncode','jsDecodeUrl');
decodeStr('phpRawUrlEncode','jsDecodeRawUrl');
</script>
</body>
</html>
Upvotes: 1
Reputation: 665364
A classic :-)
PHP's urlencode
does not exactly the same as JavaScript's encodeURIComonent
: they handle blanks different; one uses +
, the other %20
.
You'll need to handle that, and e.g. phpjs offers a PHP-compliant decodeURI
function.
> var phpstring = "%27%2C+6.%26-7m%2F%2C+%227%2A%2C-m%2B1%26%25m0%26%221+%2B";
> xor_string(decodeURIComponent(phpstring.replace(/\+/g, "%20")), 67 );
"document.location.href.search"
As you might notice, this error hits only the character that is encoded to a space with your xor
function (and its parameter).
Upvotes: 4