Как я могу преобразовать эту функцию XOR-шифрования из Delphi в C #? - PullRequest
8 голосов
/ 20 июля 2011

Следующая подпрограмма Delphi взята из давней публикации CompuServe и используется для шифрования различной информации в нашей базе данных.Ниже приведены и Delphi 2007, и (благодаря некоторой SO-помощи с различиями в Юникоде) версии Delphi XE.

Мы пытались преобразовать это в C # и получили близкую ишу, но нам не хватаетчто-то где-тоК сожалению, наш парень из Delphi (я) не знает C #, а парень из C # - новичок в Delphi.В C # нет (кажется, что) концепции AnsiString, поэтому решение, вероятно, будет включать байтовые или символьные массивы?

Мы были бы очень признательны за любую помощь в преобразовании этого в C #.Версия Delphi 2007 (ASCII)

function EncodeDecode(Str: string): string;
const
  Hash: string = '^%12hDVjED1~~#29afdmSD`6ZvUY@hbkDBC3fn7Y7euF|R7934093*7a-|-  Q`';
var
  I: Integer;
begin
  for I := 1 to Length (Str) do
    Str[I] := chr (ord (Str[I]) xor not (ord (Hash[I mod Length (Hash) + 1])));
  Result := Str;
end;

Версия Delphi XE (Unicode)

function TfrmMain.EncodeDecode(Str: AnsiString): AnsiString;
const
  Hash: string = '^%12hDVjED1~~#29afdmSD`6ZvUY@hbkDBC3fn7Y7euF|R7934093*7a-|-  Q`';
var
  I: Integer;
begin
  Result := Str;
  for I := 1 to Length (Result) do
    Result[I] := AnsiChar (ord (Result[I]) xor not (Ord (Hash[I mod Length (Hash) + 1])));
end;

Ответы [ 2 ]

11 голосов
/ 21 июля 2011

Я тоже не знаю C #, так что это, вероятно, серьезно не идиоматично.

static string EncodeDecode(string str)
{
    byte[] hash = new byte[63] { 94, 37, 49, 50, 104, 68, 86, 106, 69, 68, 49, 126, 
        126, 35, 50, 57, 97, 102, 100, 109, 83, 68, 96, 54, 90, 118, 85, 89, 64, 
        104, 98, 107, 68, 66, 67, 51, 102, 110, 55, 89, 55, 101, 117, 70, 124, 82, 
        55, 57, 51, 52, 48, 57, 51, 42, 55, 97, 45, 124, 45, 32, 32, 81, 96 };

    Encoding ANSI = Encoding.GetEncoding(1252);
    byte[] input = ANSI.GetBytes(str);
    byte[] output = new byte[input.Length];
    for (int i = 0; i < input.Length; i++)
        output[i] = (byte)(input[i] ^ ~hash[(i + 1) % hash.Length]);
    return ANSI.GetString(output);
}

Я предположил, что ваши строки ANSI закодированы в Windows 1252, но если вы случайно закодировали свои устаревшие данные с другой кодовой страницей, то вполне очевидно, как это изменить.

Поскольку C # не имеет эквивалента 8-битных строковых типов Delphi, мне лично очень хотелось бы использовать byte[] вместо string.

Сделано так, это выглядит так:

static byte[] EncodeDecode(byte[] input)
{
    byte[] hash = new byte[63] { 94, 37, 49, 50, 104, 68, 86, 106, 69, 68, 49, 126, 
        126, 35, 50, 57, 97, 102, 100, 109, 83, 68, 96, 54, 90, 118, 85, 89, 64, 
        104, 98, 107, 68, 66, 67, 51, 102, 110, 55, 89, 55, 101, 117, 70, 124, 82, 
        55, 57, 51, 52, 48, 57, 51, 42, 55, 97, 45, 124, 45, 32, 32, 81, 96 };

    byte[] output = new byte[input.Length];
    for (int i = 0; i < input.Length; i++)
        output[i] = (byte)(input[i] ^ ~hash[(i + 1) % hash.Length]);
    return output;
}

@ Groo замечательно показывает, что хеш можно инициализировать более четко, перечислите это:

byte[] hash = ANSI.GetBytes(@"^%12hDVjED1~~#29afdmSD`6ZvUY@hbkDBC3fn7Y7euF|R7934093*7a-|-  Q`");
2 голосов
/ 21 июля 2011

String в C # - это последовательность символов, закодированная в UTF-16, как объяснено в этой статье Джоном Скитом . Это на самом деле не должно беспокоить вас, пока вы не решите сериализовать его в двоичном формате (т.е. преобразовать его в байтовый массив). В этом случае существует класс с именем Encoding в пространстве имен System.Text, который поддерживает кодирование String в любую нужную кодировку.

AnsiString в Delphi - это , в основном строка ASCII (нет, это действительно строка ANSI, как говорит название), где каждый символ гарантированно имеет ровно 8 бит. Это относительно «простая» кодировка для работы с кодировкой, поскольку она имеет фиксированный размер, широко принята и совместима с унаследованными системами (но она не позволяет кодировать более 255 символов).

Другими словами, обе ваши версии имеют дело с одним и тем же типом кодирования, но версия Unicode теперь явно определяет устаревшие строки как AnsiString s. Это означает, что последняя версия на самом деле не поддерживает строки Unicode, но тип должен быть изменен с новой версией Delphi.

То, что делал @David, когда я писал эту длинную чепуху, в основном то, что я собирался написать, за исключением того, что вместо этого я использовал бы кодировку Encoding.ASCII ( [править] и с треском провалился бы из-за того, что ASCII использует только младшие 7 бит для кодирования символов, как упомянуто Дэвидом ниже ). Windows-1252 - это кодировка, чаще всего называемая «ANSI» (хотя, если вы проверите эту статью в вики, вы обнаружите, что, согласно Microsoft, термин ANSI, используемый для означает, что кодовые страницы Windows - это историческая справка, но в настоящее время это неправильное название, которое продолжает существовать в сообществе Windows ).

...