Delphi ‹› Шифрование PHP XOR

Я пытаюсь выполнить шифрование и дешифрование между PHP и Delphi.

Мой PHP-код;

<?php
error_reporting(E_ALL);
$key = "5y';syhl0ngl4st1ngdfvt5tt";

function decrypt1($string, $key){

    $y = 1;
    for ($x = 1;$i < strlen($string); $i++) {
        $a = (ord($string[$x]) and 0x0f) ^ (ord($key[$y]) and 0x0f);
        $string[$x] = chr((ord($string[$x]) and 0xf0) + $a);

        $y++;
        if ($y > strlen($key)) $y = 1;
    }
    return $string;
}

echo decrypt1(base64_decode("cWx0fw=="),$key);
?>

Мой Дельфи;

function Decrypt1(Str : String; Key: string): AnsiString;
var
  X, Y : Integer;
  A : Byte;
begin
  Y := 1;
  for X := 1 to Length(Str) do
  begin
    A := (ord(Str[X]) and $0f) xor (ord(Key[Y]) and $0f);
    Str[X] := char((ord(Str[X]) and $f0) + A);

    Inc(Y);
    If Y > length(Key) then Y := 1;
  end;
  Result := Str;
end;

function Encrypt(Str : String; Key: string): String;
begin
result:= Decrypt1(str,key);
result:= EncodeBase64(result);
end;

Шифрование/дешифрование не работает. При попытке декодировать закодированное значение из Delphi в PHP я получаю кучу мусора.

У меня есть ощущение, что это может быть как-то связано с кодировкой символов?


person Jake Evans    schedule 18.08.2014    source источник
comment
Delphi работает с Ansi или с D2009 с UTF16 и PHP с UTF8. Вы должны убедиться, что работаете с одной и той же кодировкой.   -  person Sir Rufo    schedule 19.08.2014
comment
Шаг 1 — перестать использовать строки для хранения байтовых массивов. Используйте 1_. Это самое большое заблуждение, с которым мы сталкиваемся в отношении шифрования. Шифрование работает с двоичными данными, а не с текстом.   -  person David Heffernan    schedule 19.08.2014


Ответы (2)


Здесь есть несколько проблем:

  • Индексация строк в PHP начинается с нуля, а не с единицы, как предполагает ваш код.
  • Строки Delphi (ну, в современном Delphi) имеют кодировку UTF-16. Ваш код предполагает некоторую неопределенную 8-битную кодировку.
  • Шифрование/дешифрование работает с двоичными данными, а не с текстом, и вы не можете этого распознать.

Вы должны зашифровать так:

  1. Кодируйте текст в определенной четко определенной кодировке. Например, UTF-8. Это дает массив байтов. В Delphi это TBytes.
  2. Зашифруйте этот массив байтов, чтобы получить другой массив байтов.
  3. Закодируйте этот массив байтов, используя base64, чтобы получить текстовое представление.

Расшифровка просто меняет эти шаги на противоположные. Главное, что нужно усвоить, это то, что шифрование/дешифрование работает с двоичными данными, а не с текстом.

person David Heffernan    schedule 19.08.2014

Я собираюсь сделать предположение и сказать, что вы используете версию Delphi, где строка — это UnicodeString. PHP обычно использует некоторую кодировку ANSI, которую можно настроить. Лучший способ справиться с этим — сохранить ваш код Delphi в UTF-8 и загрузить из UTF-8, а также убедиться, что ваш PHP загружается из UTF-8. Стандартизируйте одну кодировку для всех, и тогда подобных проблем не будет.

person Mason Wheeler    schedule 18.08.2014
comment
На самом деле я использую Delphi XE6, так что я бы предположил, что это Ansi? - person Jake Evans; 19.08.2014
comment
@Tom: Все, что относится к D2009 или более поздней версии (включая всю линейку XE), является Unicode. - person Mason Wheeler; 19.08.2014
comment
Итак, как мне сделать кодировку Delphi и PHP совместимой? - person Jake Evans; 19.08.2014
comment
@Tom: Делая именно то, что я сказал. Используйте стандартную кодировку. Например, при записи данных используйте UTF8String вместо строки. - person Mason Wheeler; 19.08.2014
comment
Я пробовал это, я все еще получаю другой результат, когда делаю это в PHP - person Jake Evans; 19.08.2014
comment
@Tom: О, и убедитесь, что вы используете UTF8String и AnsiChar, а не String и Char для своих функций шифрования и дешифрования. - person Mason Wheeler; 19.08.2014
comment
Давайте продолжим обсуждение в чате. - person Jake Evans; 19.08.2014
comment
Совет по использованию UTF-8 неполный. Можно посоветовать получить байты в кодировке UTF-8, а затем зашифровать их в зашифрованные байты. Но в этот момент у вас есть двоичные данные, которые нельзя рассматривать как текст. Возможно, можно было бы кодировать base64 как текст. Но здесь гораздо больше, чем общее предложение стандартизировать UTF-8. - person David Heffernan; 19.08.2014