Я попытался выполнить XOR для двух строк в 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 / html; charset = UTF-8 и с метатегом UTF-8, если что-то из этого имеет значение.
Мой веб-сервер - Mongoose 6.7 с php 5.6 (cgi) в комплекте. Я также попробовал последнюю версию 7.3 (x86 и x64) с теми же результатами, однако @apokryfos в комментариях проверил ее с правильным шестым битом.