将 C# 函数转换为 Delphi 函数

Convert C# function to Delphi function

我需要将此 C# 函数转换为 Delphi。我正在转换一个函数,它将根据 CPU id、BIOS id 和主板 id 生成一个字符串。

有人能帮帮我吗?

private string GetHash(string s)
{
    return ComputerInfo.GetHexString(new MD5CryptoServiceProvider().ComputeHash(new ASCIIEncoding().GetBytes(s)));
}

private string GetHexString(byte[] bt)
{
    string str1 = string.Empty;
    int myLenght = bt.Length - 8;
    for (int index = 0; index < myLenght; ++index)
    {
        int num1 = (int)bt[index];
        int num2 = num1 & 15;
        int num3 = num1 >> 4 & 15;
        string str2 = num3 <= 9 ? str1 + num3.ToString() : str1 + ((char)(num3 - 10 + 65)).ToString();
        str1 = num2 <= 9 ? str2 + num2.ToString() : str2 + ((char)(num2 - 10 + 65)).ToString();
        if (index + 1 != myLenght && (index + 1) % 2 == 0)
            str1 += "-";
    }

    return str1;
}

我尝试了几种方法来转换函数,但我仍然无法获得与原始函数相同的值。在我的笔记本电脑上,我得到字符串 '1CB9-0485-D2FD-846C' 但在 Delphi 中,我得到字符串 '3237-3939-3232-4433-4141-3835-4342-4536-4145-3344-3933-383736'.

function TAppForm.GetHexString(bt : TBytes) : string;
var
  str1: string;
  str2: string;
  myLength: Integer;
  index: Integer;
  num1: Integer;
  num2: Integer;
  num3: Integer;
begin
  str1 := string.Empty;
  myLength := Length(bt) - 8;
  for index := 0 to myLength do
  begin
    num1 := Integer(bt[index]);
    num2 := num1 and 15;
    num3 := num1  shr  4 and 15;
    If num3 <= 9 then
      str2 := str1 + num3.ToString()
    else
      str2 := str1 + Chr(num3 - 10 + 65);
    If num2 <= 9 then
      str1 := str2 + num2.ToString()
    else
      str1 := str2 + Chr(num2 - 10 + 65);

    if ((index + 1) <> myLength) and ((index + 1) mod 2 = 0) then
      str1  := str1 + '-';
  end;
  Result := str1;
end;

function TAppForm.MyGetMD5(Value : String) : String;
var
  workHash : TIdHashMessageDigest5;
begin
  workHash := TIdHashMessageDigest5.Create;
  try
    Result := workHash.HashStringAsHex(Value);
  finally
    FreeAndNil(workHash);
  end;
end;

function TAppForm.GetHash(s : string) : string;
var
  //bytes: TBytes;
  bytes: TBytes;
  smd5: string;
begin
  smd5 := MyGetMD5(s);
  bytes := TEncoding.ASCII.GetBytes(smd5);
  smd5 := GetHexString(bytes);
  Result := smd5;
end;

非常感谢@olivier 的解决方案。其实和我想要的很接近

然而,我在 C# 中得到的结果是 "1CB9-0485-D2FD-846C",而使用你的解决方案我得到 "0126-28BE-D776-1788"。 我试图理解为什么,因为请求哈希的字符串是相同的。

在C#中,请求如下

GetHash("CPU >>" + ComputerInfo.CpuId() + "\nBIOS >>" + ComputerInfo.BiosId() + "\nBASE >>" + ComputerInfo.BaseId());

结果

CPU BFEBFBFF000306D4
BIOS INSYDE Corp.5.308F014604C20160325000000.000000 + 000TOSQCI - 1
BASE FF50Base BoardQC0C0Q8F3000710

在Delphi中,请求如下

const
  sLineBreak = {$IFDEF LINUX} AnsiChar (#10) {$ENDIF}
               {$IFDEF MSWINDOWS} AnsiString (#13#10) {$ENDIF};

GetHash('CPU >>' + CpuId() + sLineBreak + 'BIOS >>' + BiosId() + sLineBreak + 'BASE >>' + BaseId());

结果

CPU BFEBFBFF000306D4
BIOS INSYDE Corp.5.308F014604C20160325000000.000000 + 000TOSQCI - 1
BASE FF50Base BoardQC0C0Q8F3000710

这是一个有效的实现。它使用 THashMD5,在 Delphi.

的最新版本中可用。
uses
  System.Hash;

function GetHexString(const b: TBytes): string;
var
  len: Integer;
  index: Integer;
  num1: Byte;
  num2: Byte;
  num3: Byte;
begin
  Result := '';
  len := Length(b) - 8;
  for index := 0 to len - 1 do
  begin
    num1 := b[index];
    num2 := num1 and 15;
    num3 := (num1 shr 4) and 15;
    If num3 <= 9 then
      Result := Result + num3.ToString()
    else
      Result := Result + Chr(num3 - 10 + 65);
    If num2 <= 9 then
      Result := Result + num2.ToString()
    else
      Result := Result + Chr(num2 - 10 + 65);
    if ((index + 1) <> len) and ((index + 1) mod 2 = 0) then
      Result := Result + '-';
  end;
end;

function GetHash(const s: string): string;
var
    b, hash: TBytes;
    md5: THashMD5;
begin
    b := TEncoding.ASCII.GetBytes(s);

    md5 := THashMD5.Create;
    md5.update(b);
    hash := md5.HashAsBytes;

    Result := GetHexString(hash);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(GetHash('Test'));
end;

C# 和 Delphi 实现输出 0CBC-6611-F554-0BD0 输入字符串 Test

Delphi 逻辑与 C# 逻辑不匹配。

C# 代码正在执行以下操作:

  • 将 Unicode 字符串转换为 ASCII 字节数组
  • 然后对这些字节进行 MD5 哈希处理
  • 然后将该散列的字节编码为格式化的十六进制字符串

Delphi 代码执行以下操作:

  • (隐式)将 Unicode 字符串转换为 ASCII 字节数组
  • 然后对这些字节进行 MD5 哈希处理
  • 然后将该散列的字节编码为普通的十六进制字符串
  • 然后将该十六进制字符串转换为 ASCII 字节数组
  • 然后将这些字节编码为格式化的十六进制字符串

因此,您当然会得到不同的结果,因为最终的十六进制字符串是根据完全不同的输入进行编码的。

正确的翻译应该看起来更像这样:

function TAppForm.GetHash(const s: string): string;
var
  workHash : TIdHashMessageDigest5;
begin
  workHash := TIdHashMessageDigest5.Create;
  try
    Result := GetHexString(workHash.HashString(s, IndyTextEncoding_ASCII));
  finally
    workHash.Free;
  end;
end;

function TAppForm.GetHexString(bt: TIdBytes): string;
var
  str1, str2: string;
  myLenght,
  index,
  num1, num2, num3: Integer;
begin
  str1 := '';
  myLenght := Length(bt) - 8;
  for index := 0 to myLenght-1 do
  begin
    num1 := Integer(bt[index]);
    num2 := num1 and 15;
    num3 := (num1 shr 4) and 15;
    if num3 <= 9 then
      str2 := str1 + IntToStr(num3)
    else
      str2 := str1 + Char(num3 - 10 + 65);
    if num2 <= 9 then
      str1 := str2 + IntToStr(num2)
    else
      str1 := str2 + Char(num2 - 10 + 65);
    if ((index + 1) <> myLenght) and ((index + 1) mod 2 = 0) then
      str1 := str1 + '-';
  end;
  Result := str1;
end;

此外,C# 中的 '\n' 字符只是一个换行符。它与 Windows 上 Delphi 中的 #13#10(回车 return + 换行)字符序列不同。因此,您对 GetHash() 的输入在 C# 和 Delphi 之间也不相同。你根本不应该使用 sLineBreak 常数,只使用 #10 本身,例如:

GetHash('CPU >>' + CpuId() + #10'BIOS >>' + BiosId() + #10'BASE >>' + BaseId());