【问题标题】:XOR strings: JS vs PHPXOR 字符串:JS 与 PHP
【发布时间】:2020-02-11 20:44:57
【问题描述】:

我尝试在 PHP 和 JS 中对两个字符串进行异或运算,得到了不同的结果:

PHP 函数

function xh($a, $b) {
  $res = ""; $i = strlen($a); $j = strlen($b);
  while($i-->0 && $j-->0) {
    $res.= $a[$i] ^ $b[$j];
  }
  return base64_encode($res);
}

JS函数

function xh(a, b) {
  var res = "", i = a.length, j = b.length;
  while (i-->0 && j-->0) {
    res+= String.fromCharCode(a.charCodeAt(i) ^ b.charCodeAt(j));
  }
  return btoa(res);
}

我检查了字节,发现PHP函数中的第六个字节总是为零,所以我将JS函数更新为

JS函数相当于PHP

function xh2(a, b) {
  var res = "", i = a.length, j = b.length;
  while (i-->0 && j-->0) {
    res+= String.fromCharCode((a.charCodeAt(i) ^ b.charCodeAt(j)) & 95);
  }
  return btoa(res);
}

那么那个位发生了什么?

输入/输出示例:

string a: 5D41402ABC4B2A76B9719D911017C592
string b: FE2D010308A6B3799A3D9C728EE74244
PHP says: Bg0HVwBUVQkDDgcAVQRYWw8AUlBUVVtSUgIBBFUGAVM=
 JS says: Bg0HdwB0dQkDDgcAdQR4ew8AcnB0dXtycgIBBHUGAXM=
JS2 says: Bg0HVwBUVQkDDgcAVQRYWw8AUlBUVVtSUgIBBFUGAVM=

本例中的第一个区别:

C: 0x43  = 0100 0011
4: 0x34  = 0011 0100
C^4 (JS) = 0111 0111 = 0x77 (correct)
C^4 (PHP)= 0101 0111 = 0x57
             ^
             sixth bit wrong

输入是 MD5 哈希,我使用默认编码,我的 OEM 字符集是 CP1250,语言环境 cs-cz,文件以 UTF-8 编码存储,页面使用 HTTP 标头 text/html;charset=UTF- 生成8 和元标记 UTF-8(如果有任何这些问题)。

我的网络服务器是捆绑了 php 5.6 (cgi) 的 Mongoose 6.7。我还尝试了最新的 7.3(x86 和 x64),结果相同,但是 cmets 中的 @apokryfos tested it 第六位正确。

【问题讨论】:

  • -->这是什么黑魔法?
  • @Dominic (i--)>0
  • 意思是(i--)> 0
  • JS 和 PHP 脚本是否都使用相同的字符编码?当您使用 PHP strlen 函数时,我可以推断您正在使用 ASCII,或者您不知道 strlen 不适合多字节编码。
  • 先尝试将字符串作为文字传递,不要让猫鼬参与其中,看看是否有帮助。

标签: javascript php xor mongoose-web-server


【解决方案1】:

问题的根源在于区分大小写:似乎 MD5 的一些错误实现并没有降低 md5 输出的大小写。在客户端和服务器端使用了两个不同的库。

'A' starts at 0x41 = 0100 0001
'a' starts at 0x61 = 0110 0001
                       ^
                       here is the sixth bit

【讨论】:

    【解决方案2】:

    对于 JS,使用缓冲区或类型化数组而不是字符串。否则你需要一些二进制安全的字符串编码。

    您可以在 PHP 中对两个字符串进行整体异或:$a ^ $b(不要忘记长度检查)。

    见:https://developer.mozilla.org/en-US/docs/Web/API/DOMString/Binary

    我从 PHP 中获得 Bg0HdwB0dQkDDgcAdQR4ew8AcnB0dXtycgIBBHUGAXM= 以及您的代码,所以正在发生其他事情。

    能否提供 PHP 版本和构建/源代码?

    【讨论】:

    • 没有区别 - 请参阅问题中的更新示例。
    • 我确信 PHP 不能像您那样在字符串上使用 XOR。 chr(ord($a[$i]) ^ ord($b[$j])); 应该会产生更接近 JS 的东西。 JS 也会有所不同,因为 PHP 字符串是字节数组,但 JS 字符串是 unicode 字符数组。您根本无法像在 PHP 中那样安全地使用 JS 字符串进行二进制操作。但是,您可以使用 mbstring 或类似方法使 PHP 与 JS 执行相同的操作。您可以使用字节数组使 JS 匹配 PHP。
    • 这么说,看起来 xor 确实适用于 PHP 中的字符串字节,这让我想知道您是否可以对整个字符串进行异或而不是循环?
    • 可能需要&255?
    • 查看最新编辑。这个问题比看起来更奇怪。
    猜你喜欢
    • 2016-03-18
    • 1970-01-01
    • 2018-05-04
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    • 1970-01-01
    相关资源
    最近更新 更多