Xor шифрование в PHP

Я новичок в шифровании Xor, и у меня возникли проблемы со следующим кодом:

function xor_this($string) {

// Let's define our key here
 $key = ('magic_key');

 // Our plaintext/ciphertext
 $text =$string;

 // Our output text
 $outText = '';

 // Iterate through each character
 for($i=0;$i<strlen($text);)
 {
     for($j=0;$j<strlen($key);$j++,$i++)
     {
         $outText .= $text{$i} ^ $key{$j};
         //echo 'i='.$i.', '.'j='.$j.', '.$outText{$i}.'<br />'; //for debugging
     }
 }  
 return $outText;
}

Когда я запускаю это, оно работает для обычных строк, например, "собака", но только частично работает для строк, содержащих числа, например, "12345".

Показывать...

xor_this('dog') = 'UYV'

xor_this('123') знак равно

Также интересно отметить, что xor_this( xor_this('123') ) = '123', как я ожидаю. Я почти уверен, что проблема кроется где-то в моем шатком понимании побитовых операторов, ИЛИ, возможно, способа, которым PHP обрабатывает строки, содержащие числа. Бьюсь об заклад, есть кто-то умный там, кто точно знает, что здесь не так. Благодарю.

РЕДАКТИРОВАТЬ #1: Это не совсем "шифрование". Я думаю, что запутывание является правильным термином, который я и делаю. Мне нужно передать код, содержащий неважные данные от пользователя, чтобы они не могли легко его изменить. Они завершают задание по времени в автономном режиме и отправляют свое время в онлайн-табло с помощью этого кода. Автономная активность будет запутывать их время (в миллисекундах). Мне нужно написать скрипт для получения этого кода и вернуть его обратно в строку, содержащую их время.

9 ответов

Решение

Несмотря на все мудрые предложения, я решил эту проблему гораздо проще:

Я изменил ключ! Оказывается, изменив ключ на что-то более похожее на это:

$key = 'ISINUS0478331006';

... он будет генерировать запутанный вывод печатных символов.

Как я это сделал, может кому-то помочь...

$msg = 'say hi!';
$key = 'whatever_123';

// print, and make unprintable chars available for a link or alike.
// using $_GET, php will urldecode it, if it was passed urlencoded
print "obfuscated, ready for url: " . urlencode(obfuscate($msg, $key)) . "\n";
print "deObfuscated: " . obfuscate(obfuscate($msg, $key), $key);


function obfuscate($msg, $key) {
    if (empty($key)) return $msg;
    return $msg ^ str_pad('', strlen($msg), $key);
}

Я думаю, что у вас может быть несколько проблем здесь, я попытался обрисовать, как, я думаю, вы можете это исправить:

  • Вам нужно использовать ord(..)чтобы получить значение ASCII символа, чтобы вы могли представить его в двоичном виде. Например, попробуйте следующее:

    printf("%08b ", ord('A')); // outputs "01000001"
    
  • Я не уверен, как вы делаете XOR-шифр с многобайтовым ключом, поскольку страница википедии по XOR-шифру не указывает. Но я предполагаю, что для данного ключа, такого как "123", ваш ключ начинает "выравниваться по левому краю" и распространяется на длину текста, например так:

    function xor_this($text) {
        $key = '123';
        $i = 0;
        $encrypted = '';
        foreach (str_split($text) as $char) {
            $encrypted .= chr(ord($char) ^ ord($key{$i++ % strlen($key)}));
        }
        return $encrypted;
    }
    print xor_this('hello'); // outputs "YW_]]"
    

    Который шифрует 'hello' ширина ключ '12312',

Я считаю, что вы столкнулись с проблемой вывода на консоль и кодирования, а не с XOR. Попробуйте вывести результаты функции xor в текстовый файл и посмотрите набор сгенерированных символов. Я считаю, что HEX-редактор будет лучшим выбором для наблюдения и сравнения созданного набора символов.

В основном, чтобы вернуть текст обратно (даже четные числа), вы можете использовать ту же функцию:

var $textToObfuscate = "Some Text 12345";
var $obfuscatedText = $xor_this($textToObfuscate);
var $restoredText = $xor_this($obfuscatedText);

Нет никакой гарантии, что результат операции XOR приведет к печатному символу. Если вы дадите нам лучшее представление о причине, по которой вы это делаете, мы, вероятно, можем указать вам на что-то разумное, чтобы сделать вместо этого.

Используйте этот код, он отлично работает

function scramble($inv) {
  $key=342244;  // scramble key
  $invarr=str_split($inv);
  for($index=0;$index<=strlen($inv)-1;$index++) {
    srand($key);
    $var=rand(0,255);
    $res=$res.(chr(ord($var)) ^ chr(ord($invarr[$index])));
    $key++;
  }
  return($res);
}

Исходя из того, что вы получаете xor_this( xor_this('123') ) = '123'Я готов предположить, что это всего лишь выходной вопрос. Вы отправляете данные в браузер, браузер распознает их как нечто, что должно быть отображено в HTML (скажем, первые полдюжины символов ASCII). Попробуйте посмотреть на странице источника, чтобы увидеть, что на самом деле там. Еще лучше, перебрать вывод и повторить ord значения в каждой позиции.

Попробуй это:

$outText .= (string)$text{$i} ^ (string)$key{$j};

Если один из двух операндов является целым числом, PHP преобразует другой в целое число и XOR их для числового результата.

В качестве альтернативы вы можете использовать это:

$outText .= chr(ord($text{$i}) ^ ord($key{$j}));
// Iterate through each character
for($i=0; $i<strlen($text); $i++)
{
    $outText .= chr(ord($text{$i}) ^ ord($key{$i % strlen($key)))};
}

примечание: это, вероятно, создаст некоторые странные персонажи...

Другие вопросы по тегам