【问题标题】:Why is this simple JavaScript XOR encryption algorithm not working?为什么这个简单的 JavaScript XOR 加密算法不起作用?
【发布时间】:2018-09-22 04:29:32
【问题描述】:

我正在尝试在 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 onethis onethis one,但我仍然无法解决这个问题。

为什么这个 JavaScript 算法没有按预期工作?


小注 1: 由于无法在 JavaScript 中遍历字符串的字符并逐个替换它们,因此我在 for 循环中使用了 += 运算符为了将每个 XOR 操作的输出附加到 result 变量。

小注2:为了规范化字符集,函数在PHP和JS中实际上分别返回base64_encode($result)btoa(result)。然后,为了解密它,decryptXor() 函数必须在迭代它们之前解码result 变量。尽管如此,由于这与问题无关,因此我稍微简化了功能。在这种情况下,出于测试目的,在text 变量中仅使用字母数字字符,在key 变量中仅使用数字(反之亦然)会更安全。

【问题讨论】:

    标签: javascript xor


    【解决方案1】:

    您需要一些其他方法,例如 String#charCodeAtString.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

    【讨论】:

      【解决方案2】:

      您的主要问题是您使用的是charAt 而不是charCodeAt'someRandomText'.charAt(0) 计算结果为 's''s' ^ x === x,因为^ 运算符尝试将两个操作数都转换为数字,而Number('s')NaN。因此,当您与除数字以外的任何字符进行异或运算时,您只会得到键的值。

      关于注释 1,您还有另一个问题:您不能只附加到字符串。如果您的算法生成字符串“567”,则无法知道它是由连接“56”和“7”还是“5”和“67”创建的。随着字符串变长,这将成为一个更大的问题。您可以使用数组而不是字符串,或者将每个子字符串的长度用零填充到相同的长度,或者按照 Nina 的建议,您可以使用 String.fromCharCode 将 XOR 的结果转换回单个字符。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-25
        • 2012-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多