Reputation: 23
I need to convert this C# function to Delphi. I am converting a function that will generate a string based on the CPU id, BIOS id, and motherboard id.
Can anyone help me, please?
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;
}
I tried several ways to convert the functions, but I still couldn't get the same values that I get in the original function. On my laptop, I get the String '1CB9-0485-D2FD-846C'
but in Delphi, I get the string '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;
Thank you very much for your solution @olivier. In fact, it is very close to what I want.
However, the result I get in C# is "1CB9-0485-D2FD-846C"
and with your solution I get "0126-28BE-D776-1788"
.
I have tried to understand why, since the string that is requested hash is the same.
In C#, the request is as follows
GetHash("CPU >>" + ComputerInfo.CpuId() + "\nBIOS >>" + ComputerInfo.BiosId() + "\nBASE >>" + ComputerInfo.BaseId());
Result
CPU BFEBFBFF000306D4 BIOS INSYDE Corp.5.308F014604C20160325000000.000000 + 000TOSQCI - 1 BASE FF50Base BoardQC0C0Q8F3000710
In Delphi, the request is as follow
const
sLineBreak = {$IFDEF LINUX} AnsiChar (#10) {$ENDIF}
{$IFDEF MSWINDOWS} AnsiString (#13#10) {$ENDIF};
GetHash('CPU >>' + CpuId() + sLineBreak + 'BIOS >>' + BiosId() + sLineBreak + 'BASE >>' + BaseId());
Result
CPU BFEBFBFF000306D4 BIOS INSYDE Corp.5.308F014604C20160325000000.000000 + 000TOSQCI - 1 BASE FF50Base BoardQC0C0Q8F3000710
Upvotes: 1
Views: 742
Reputation: 595369
The C# code is doing the following:
The Delphi code is doing the following:
So, of course you end up with different results, because the final hex string is being encoded from completely different inputs.
The correct translation should look more like this instead:
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;
Also, the '\n'
char in C# is just a line feed. It is not the same as the #13#10
(carriage return + line feed) char sequence in Delphi on Windows. So, your input to GetHash()
is not the same between C# and Delphi, either. You should not be using the sLineBreak
constant at all, use just #10
by itself, eg:
GetHash('CPU >>' + CpuId() + #10'BIOS >>' + BiosId() + #10'BASE >>' + BaseId());
Upvotes: 2
Reputation: 18037
Here's a working implementation. It uses THashMD5
, which is available in recent versions of 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;
Both C# and Delphi implementations output 0CBC-6611-F554-0BD0
for input string Test
.
Upvotes: 1