【问题标题】:Converting Delphi 2007 string encryption routine to Delphi XE将 Delphi 2007 字符串加密例程转换为 Delphi XE
【发布时间】:2011-07-07 19:05:32
【问题描述】:

我们有一个 Delphi 2007 例程用于加密表中的密码。该例程最初是从十年或更长时间前的 CompuServe 帖子中获取的,并且存在大量使用此例程加密的数据。

原套路的核心是这样的:

chr(ord(Str[I]) xor not(ord(Id[I mod length(Id) + 1])));

我知道转换到 Delphi XE 会因为 Unicode 而出现问题,所以我将代码分解成一个函数,在备忘录中显示计算的每个步骤:

function TfrmMain.EncodeDecode(AString: string): string;
const
  Hash: string = '^%12h2DBC3f41~~#6093fn7mY7eujEhbFD3DZ|R9aSDVvUY@dk79*7a-|-  Q';
var
  I: Integer;
  IMod: Integer;
  HMod: Char;
  OMod: Integer;
  AStrI: Char;
  OStrI: Integer;
  ResultStr: string;
  XOrNot: Integer;
  ChrXN: AnsiChar;
begin
  Memo1.Clear;
  Memo1.Lines.Add ('AStrI' + TAB + 'IMod' + TAB + 'HMod' +
    TAB + 'OMod' + TAB + 'OStrI' + TAB + 'XOrNot' + TAB + 'ChrXN');

  for I := 1 to Length (AString) do
  begin
    IMod := I mod Length (Hash) + 1;
    HMod := Hash [IMod];
    OMod := Ord (HMod);
    AStrI := AString[I];
    OStrI := Ord (AStrI);  // This is where things go south
    XOrNot := OStrI xor not OMod;
    ChrXN := AnsiChar (XOrNot);
    ResultStr := ResultStr + ChrXN;

    Memo1.Lines.Add (AStrI  + TAB +
      IntToStr (IMod)   + TAB +
      HMod              + TAB +
      IntToStr (OMod)   + TAB +
      IntToStr (OStrI)  + TAB +
      IntToStr (XOrNot) + TAB +
      ChrXN);
  end;
  Memo1.Lines.Add (ResultStr);
  Result := ResultStr;
end;

与 ROT13 一样,加密和解密都使用相同的例程。如果我给它输入一个像 'ABCDEFGHI' 这样的字符串,Delphi 2007 版本可以获取生成的加密字符串,通过相同的例程运行它,然后取回原始字符串。然而,Delphi XE 中的版本并完全工作。我做了一些调整(包括在上面)来改进它,但是在 OstrI 步骤中它分崩离析。我认为这与在(宽)字符上执行 Ord 有关,但这是我能得到的最接近的。

非常感谢任何建议。


编辑

这是原始的 Delphi 2007 代码:

function EncodeDecode(Str: string): string;
const
  Id: string = '^%12h2DBC3f41~~#6093fn7mY7eujEhbFD3DZ|R9aSDVvUY@dk79*7a-|-  Q';
var
  I: Integer;
begin
  for I := 1 to Length (Str) do
    Str[I] := chr (ord (Str[I]) xor not (ord (Id[I mod Length (Id) + 1])));
  Result := Str;
end;

实际上,我们不仅必须将其转换为 Delphi XE 以用于我们现有软件的新版本,而且还必须将其转换为 C# 以用于新的基于 Web 的前端。

【问题讨论】:

  • 更简洁地说:函数是一个involution(= 它自己的逆)。
  • 我没有详细研究过上面的代码,但是我看到你正在混合stringAnsiString(以及charAnsiChar),这通常不是很好处理原始的二进制数据。但也许您已经意识到这一点,并且只是在以正确的方式做事?
  • 与其发布不起作用的代码,不如只发布 D2007 代码,其中一位用户将能够向您展示如何将其移植到 XE。
  • 原始帖子已编辑以包含起始 D2007 代码。谢谢@DavidHeffernan,祝你好运:-)
  • @Eric:你肯定知道如何让事情变得复杂! ;)

标签: delphi unicode delphi-xe


【解决方案1】:

简单的方法,本质上如下:

  1. 从 Delphi 2007 代码开始。
  2. string 更改为AnsiString
  3. Char 更改为AnsiChar
  4. 可能将Chr() 更改为AnsiChar()

您的代码可能存在更多细微差别。理想情况下,我希望看到原始 Delphi 2007 版本的代码。


已经发布了原始代码,我想你应该可以在 XE 中使用这个例程:

function EncodeDecode(const Str: AnsiString): AnsiString;
const
  Id: AnsiString = '^%12h2DBC3f41~~#6093fn7mY7eujEhbFD3DZ|R9aSDVvUY@dk79*7a-|-  Q';
var
  I: Integer;
begin
  Result := Str;
  for I := 1 to Length(Result) do
    Result[I] := AnsiChar(ord(Result[I]) xor not (ord(Id[I mod Length (Id) + 1])));
end;

请注意,我将代码更改为将输入作为const 字符串并使用Result 作为工作缓冲区。这对于您的 ANSI/Unicode 需求不是必需的,但对我来说感觉更自然!

【讨论】:

  • 这是始终使 Unicode 之前的 Delphi 代码在现代版本的 Delphi 中工作的一种方式。唯一(也是显而易见的)缺点是您没有获得 Unicode 支持。
  • @Andreas 我想在这种情况下对于 OP 来说没问题,因为 OP 将数据锁定在仅限于 ANSI 的文件中。
  • 哇,我想太多了。谢谢大卫的快速回答!
  • @David:为了更进一步,我建议将输入/输出值从AnsiString 更改为RawByteString。在 D2009 之前,AnsiString 并没有真正对用于编码字符的代码页做出任何假设。从 D2009 开始,它确实如此,而 RawByteString 继承了传递给它的任何 Ansi 字符串的代码页。
  • @Remy 我认为将 AnsiString 用作字节缓冲区时,代码页不会成为问题。但我不是这种细微差别的专家。使用 AnsiString 而不是 RawBytesString 会出现什么问题?
猜你喜欢
  • 1970-01-01
  • 2011-05-31
  • 1970-01-01
  • 2014-11-05
  • 2010-09-21
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多