简体   繁体   English

为什么这个简单的JavaScript XOR加密算法不起作用?

[英]Why is this simple JavaScript XOR encryption algorithm not working?

I am trying to develop a ( very ) simple XOR encryption algorithm in JavaScript. 我正在尝试用JavaScript开发一个( 非常 )简单的XOR加密算法。

In PHP, the following encryption algorithm works as expected: 在PHP中,以下加密算法按预期工作:

function encryptXor($text, $key) {
  $result = '';

  for ($i = 0; $i < strlen($text); $i++)
    $result[$i] = $text[$i] ^ $key[$i % strlen($key)];

  return $result;
}

However, the following JavaScript algorithm does not work properly: 但是,以下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;
}

A test case follows: 测试案例如下:

Text: someRandomText
Key:  123456789
PHP output: B]^QgWY\V\fVLA
JS output:  12345678912345

Apparently, the ^ operator is behaving differently between the two languages. 显然, ^运算符在两种语言之间表现不同。

I have found some questions regarding the difference between PHP's and JavaScript's ^ operators, such as this one , this one or this one , but I still could not resolve this issue. 我发现了一些关于PHP和JavaScript的^运算符之间的区别的问题,比如这个这个或者这个 ,但我仍然无法解决这个问题。

Why is this JavaScript algorithm not working as expected? 为什么这个JavaScript算法没有按预期工作?


Minor note 1: Since it is not possible to iterate over the characters of a string and replace them one by one in JavaScript, I used the += operator inside the for loop in order to append the output of each XOR operation to the result variable. 次要注释1:由于无法迭代字符串的字符并在JavaScript中逐个替换它们,因此我在for循环中使用了+=运算符,以便将每个XOR运算的输出附加到result变量。

Minor note 2: In order to normalize the character set, the functions actually return base64_encode($result) and btoa(result) in PHP and JS, respectively. 次要注释2:为了规范化字符集,函数实际上分别在PHP和JS中返回base64_encode($result)btoa(result) Then, in order to decrypt it, the decryptXor() functions have to decode the result variables before iterating over them. 然后,为了解密它, decryptXor()函数必须在迭代它们之前解码result变量。 Nonetheless, since this is not relevant to the question, I simplified the functions a bit. 尽管如此,由于这与问题无关,我简化了一些功能。 In this case, for the purpuses of testing, it is safer to use only alphanumeric characters in the text variable and only numerals in the key variable (or vice-versa). 在这种情况下,对于测试的例子,在text变量中仅使用字母数字字符并且仅在key变量中使用数字(反之亦然)更安全。

You need some other methods, like String#charCodeAt or String.fromCharCode for getting the same result. 您需要一些其他方法,如String#charCodeAtString.fromCharCode来获得相同的结果。

The main problem is, you need a numerical value instead of the character/string. 主要问题是,您需要一个数值而不是字符/字符串。

 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 

A bit shorter version 有点短版本

 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 

Your main problem is that you are using charAt instead of charCodeAt . 您的主要问题是您使用charAt而不是charCodeAt 'someRandomText'.charAt(0) evaluates to 's' . 'someRandomText'.charAt(0)计算为's' 's' ^ x === x , since the ^ operator attempts to convert both operands to numbers and Number('s') is NaN . 's' ^ x === x ,因为^运算符尝试将两个操作数转换为数字而Number('s')NaN So when you xor with any character other than a numeric one you just get the value of the key. 因此,当你使用除数字之外的任何字符xor时,你只需得到键的值。

You also have another problem regarding Note 1: You can't just append to a string. 关于注1,您还有另一个问题:您不能只是附加到字符串。 If your algorithm results in the string '567' it's impossible to know whether that was created from concatenating '56' and '7' or '5' and '67'. 如果你的算法导致字符串'567',则无法知道它是否是通过连接'56'和'7'或'5'和'67'创建的。 That becomes a much bigger problem as the string gets longer. 随着字符串变长,这成为一个更大的问题。 You could use an array instead of a string or left zero pad each substring to the same length or as Nina suggested, you could convert the result of the XOR back to a single char with String.fromCharCode . 您可以使用数组而不是字符串或将每个子字符串保留为零填充到相同的长度,或者如Nina建议的那样,您可以将XOR的结果转换回使用String.fromCharCode的单个字符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM