我正在尝试在JavaScript中开发一种(非常)简单的XOR加密算法。
在PHP中,以下加密算法可以正常工作:
function encryptXor($text, $key) {
$result = '';
for ($i = 0; $i < strlen($text); $i++)
$result[$i] = $text[$i] ^ $key[$i % strlen($key)];
return $result;
}
但是,以下JavaScript算法无法正常工作:
function encryptXor(text, key) {
var result = '';
for(var i = 0; i < text.length; i++)
result += text.charAt(i) ^ key.charAt(i % key.length);
return result;
}
一个测试用例如下:
Text: someRandomText
Key: 123456789
PHP output: B]^QgWY\V\fVLA
JS output: 12345678912345
显然,^
运算符在两种语言之间的行为有所不同。
我发现了一些有关PHP和JavaScript的^
运算符之间的区别的问题,例如this one,this one或this one,但我仍然无法解决此问题
为什么此JavaScript算法无法按预期工作?
次要注意事项1:由于无法遍历字符串的字符并在JavaScript中将它们一一替换,因此我在{{1内使用了+=
}}循环,以便将每个XOR操作的输出附加到for
变量。
次要注意事项2:为了规范字符集,这些函数实际上分别在PHP和JS中返回result
和base64_encode($result)
。然后,为了对其解密,btoa(result)
函数必须在对decryptXor()
变量进行迭代之前对其进行解码。但是,由于这与问题无关,因此我对功能进行了一些简化。在这种情况下,出于测试目的,在result
变量中仅使用字母数字字符,而在text
变量中仅使用数字是安全的(反之亦然)。
答案 0 :(得分:6)
您需要其他一些方法,例如String#charCodeAt
或String.fromCharCode
来获得相同的结果。
主要问题是,您需要一个数字值而不是字符/字符串。
function encryptXor(text, key) {
var result = '';
for (var i = 0; i < text.length; i++) {
result += String.fromCharCode(text.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}
return result;
}
console.log(encryptXor('someRandomText', '123456789')); // B]^QgWY\V\fVLA
版本短一些
function encryptXor(text, key) {
return Array.from(
text,
(c, i) => String.fromCharCode(c.charCodeAt() ^ key.charCodeAt(i % key.length))
).join('');
}
console.log(encryptXor('someRandomText', '123456789')); // B]^QgWY\V\fVLA
答案 1 :(得分:3)
您的主要问题是您使用的是charAt而不是charCodeAt。 'someRandomText'.charAt(0)
的值为's'
。 's' ^ x === x
,因为^
运算符试图将两个操作数都转换为数字,并且Number('s')
为NaN
。因此,当您将非数字字符与任何其他字符进行异或运算时,您只需获取键的值即可。
关于注释1,您还有另一个问题:您不能仅附加到字符串。如果您的算法的结果为字符串“ 567”,则无法知道该字符串是由“ 56”和“ 7”或“ 5”和“ 67”串联而成的。随着字符串变长,这成为一个更大的问题。您可以使用数组而不是字符串,或者使用零填充每个子字符串相同的长度,或者按照Nina的建议,可以使用String.fromCharCode将XOR的结果转换回单个字符。