转义整个字符串的小问题


Little issue with escaping a whole string

我有以下代码执行XOR编码/解码过程:

<?php
/*
 * Simple XOR encoder/decoder, Inkubus
 *
 */
$key = pack("H*","3cb37efae7f4f376ebbd76cd");
//$encoded = ")5/Y+F8'0P$/;"; // <- OK, Working
//$decoded = 'hM5cf$350';
$encoded = "-?^<]TLV.GQV)B4[YQ   "; // <- BAD, Not working
$decoded = "CTC(*zlkb4848";
//$encoded = ')3'8?E(21@$;='; // <- OK, Working
//$decoded = 'suances06';
function decode($encoded,$key) {
  $cipher = convert_uudecode($encoded);
  $plain = $cipher ^ $key;
  $result = substr($plain, 0, strlen($cipher));
  return $result;
}
function encode($decoded,$key) {
  $plain = $decoded ^ $key;
  $result = convert_uuencode(substr($plain, 0, strlen($decoded)));
  $result = preg_replace("/'n/m","",$result);
  $result = preg_replace("/`$/m","",$result);
  return $result;
}
echo "Encoded: " . $encoded . "'n";
echo "Decoded: " . decode($encoded,$key) . "'n";
echo "Encoded: " . encode($decoded,$key) . "'n";
echo "Decoded: " . decode(encode($decoded,$key),$key) . "'n";
?>

标题后面的注释是两个有效的示例,未注释的是有问题的示例。我怎样才能对要解码的 UUEN 编码字符串进行同步注释,使其保持不变并正确解码?注释字符串中的任何有问题的字符不是一个选项,而是整个字符串。

工作运行示例:

bash-$ php xor.php
Encoded: )3'8?E(21@$;=
Decoded: suances06
Encoded: )3'8?E(21@$;=
Decoded: suances06

不工作示例:

bash-$ php xor.php
Encoded: -?^<]TLV.GQV)B4[YQ
Decoded: CTC(*zlkb484
Encoded: ,?^<]TLV.GQV)B4[Y
Decoded: CTC(*zlkb484

一些字符丢失了或其他什么。有什么想法吗?

谢谢!

更新:另一个不起作用的例子:

$encoded = "-!8H<RY67FP';C1+]R@  "; // <- BAD, Not working
$decoded = "99b1rchw00d06";

跑:

bash-$ php xor.php
Encoded: -!8H<RY67FP';C1+]R@
Decoded: 99b1rchw00d0
Encoded: ,!8H<RY67FP';C1+]
Decoded: 99b1rchw00d0

不清楚你在这里实际问的是什么。你的函数包含很多代码,可以/应该简化为:

function decode($encoded,$key) {
  return convert_uudecode($encoded) ^ $key;
}
function encode($decoded,$key) {
  return convert_uuencode($decoded ^ $key);
}

这不能按预期工作的原因是因为 PHP 的 XOR 没有按照您希望的方式工作:

$a = "-?^<]TLV.GQV)B4[YQ   ";
$b = pack("H*","3cb37efae7f4f376ebbd76cd");
$c = ($a ^ $b) ^ $b;
echo $a == $c ? 'OK' : 'NOT OK';

这将输出NOT OK .如果你想要一个简单的字符串 XOR 运算符,请使用以下命令:

function str_xor($a, $b){
    $out = '';
    for ($i=0; $i<strlen($a); $i++){
        $ac = ord($a{$i});
        $bc = ord($b{$i});
        $out .= chr($ac ^ $bc);
    }
    return $out;
}

然后,前面的示例代码将往返:

$c = str_xor(str_xor($a, $b), $b);
echo $a == $c ? 'OK' : 'NOT OK';
# outputs 'OK'
PHP 的 XOR 函数不适用于第二个操作数比第一个操作数短的字符串 - 它会将返回的字符串截断为第二个操作数的长度

(如果第二个操作数比第一个操作数长,这很好 - 它将输出截断为最短操作数的长度)。

另一种可能的解决方案是像这样扩展密钥:

while (strlen($key) < strlen($text)) $key .= $key;

这将确保您的密钥比您正在 XOR 的东西长