XOR 字符串:JS 与 PHP
XOR strings: JS vs PHP
我尝试在 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);
}
那位发生了什么事?
示例input/output:
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 header 生成的text/html;charset=UTF-8 和元标记 UTF-8(如果有任何这些问题)。
我的网络服务器是捆绑了 php 5.6 (cgi) 的 Mongoose 6.7。我也尝试了最新的 7.3(x86 和 x64),结果相同,但是评论中的@apokryfos tested it 第六位正确。
对于 JS,使用缓冲区或类型化数组而不是字符串。否则你需要一些二进制安全字符串编码。
您可以完整地异或 PHP 中的两个字符串:$a ^ $b
(不要忘记长度检查)。
参见:https://developer.mozilla.org/en-US/docs/Web/API/DOMString/Binary
我从 PHP 得到 Bg0HdwB0dQkDDgcAdQR4ew8AcnB0dXtycgIBBHUGAXM= 和你的代码,所以其他事情正在发生。
你能提供 PHP 版本和构建/源代码吗?
问题的根源在于区分大小写:似乎 MD5 的一些错误实现并没有降低 md5 输出的大小写。在客户端和服务器端使用了两个不同的库。
'A' starts at 0x41 = 0100 0001
'a' starts at 0x61 = 0110 0001
^
here is the sixth bit
我尝试在 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);
}
那位发生了什么事?
示例input/output:
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 header 生成的text/html;charset=UTF-8 和元标记 UTF-8(如果有任何这些问题)。
我的网络服务器是捆绑了 php 5.6 (cgi) 的 Mongoose 6.7。我也尝试了最新的 7.3(x86 和 x64),结果相同,但是评论中的@apokryfos tested it 第六位正确。
对于 JS,使用缓冲区或类型化数组而不是字符串。否则你需要一些二进制安全字符串编码。
您可以完整地异或 PHP 中的两个字符串:$a ^ $b
(不要忘记长度检查)。
参见:https://developer.mozilla.org/en-US/docs/Web/API/DOMString/Binary
我从 PHP 得到 Bg0HdwB0dQkDDgcAdQR4ew8AcnB0dXtycgIBBHUGAXM= 和你的代码,所以其他事情正在发生。
你能提供 PHP 版本和构建/源代码吗?
问题的根源在于区分大小写:似乎 MD5 的一些错误实现并没有降低 md5 输出的大小写。在客户端和服务器端使用了两个不同的库。
'A' starts at 0x41 = 0100 0001
'a' starts at 0x61 = 0110 0001
^
here is the sixth bit