Base64 hash MD5 is different when compiling in Delphi as 32-bit or 64-bit - how can I make them the same?

I am using Delphi XE2 and the code below to create an MD5 base5 hash for use with Amazon MWS. It works if I compile it for 32-bit Windows, but if I compile for 64-bit windows, the hash is returned. What causes this and how can I change this so that they return the same hash?

function getMd5HashString(value: string): string; var MessageDigest: TIdHashMessageDigest5; Content: TBytes; begin Content := TEncoding.UTF8.GetBytes(value); MessageDigest:=TIdHashMessageDigest5.Create; Result:=Data.Cloud.CloudAPI.EncodeBytes64(MessageDigest.HashBytes(Content)); end; 

Thansk in advance.

Edit:

I use the above function in the following test:

 procedure Button1Click(Sender: TObject); begin Edit2.Text := getMd5HashString(Edit1.Text); end; 

Skipping

 <?xml version="1.0" encoding="utf-8"?> 

as a string, just for verification. If I compile a program with a 32-bit Windows target platform, the returned hash will be:

I3pK / R + hpYOKY1IQRviZbQ ==

If I compile a program with the target platform of Windows 64-bit, I get:

bmkkAOXGhLdDFCUuNBuSxw ==

Hope David answers you?

Edit2: the complete program proposed by David;

 unit ContentHashTest; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.Cloud.CloudAPI, IdGlobal, IdHash, IdHashMessageDigest, IdCoder, IdCoderMIME, Vcl.StdCtrls; type TForm1 = class(TForm) Edit1: TEdit; Button1: TButton; Edit2: TEdit; procedure Button1Click(Sender: TObject); private function getMd5HashString(value: string): string; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin Edit2.Text := getMd5HashString(Edit1.Text); end; function TForm1.getMd5HashString(value: string): string; var MessageDigest: TIdHashMessageDigest5; Content: TBytes; begin Content := TEncoding.UTF8.GetBytes(value); MessageDigest:=TIdHashMessageDigest5.Create; Result:=Data.Cloud.CloudAPI.EncodeBytes64(MessageDigest.HashBytes(Content)); end; end. 

It was my attempt to start. Following David's suggestion below, I changed this to:

 unit ContentHashTest; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdGlobal, IdHash, IdHashMessageDigest, IdCoder, IdCoderMIME, Vcl.StdCtrls; type TForm1 = class(TForm) Edit1: TEdit; Button1: TButton; Edit2: TEdit; procedure Button1Click(Sender: TObject); private function getMd5HashString(value: string): string; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin Edit2.Text := getMd5HashString(Edit1.Text); end; function TForm1.getMd5HashString(value: string): string; var MessageDigest: TIdHashMessageDigest5; Content: TIdBytes; begin Content := TIdTextEncoding.UTF8.GetBytes(value); MessageDigest := TIdHashMessageDigest5.Create; try Result := TIdEncoderMIME.EncodeBytes(MessageDigest.HashBytes(Content)); finally MessageDigest.Free; end; end; end. 

Unfortunately, with the same different results.

Win32 = I3pK / R + hpYOKY1IQRviZbQ ==

Win64 = bmkkAOXGhLdDFCUuNBuSxw ==

+5
source share
1 answer

I turned the extracts into a question into this complete program:

 {$APPTYPE CONSOLE} uses SysUtils, IdGlobal, IdCoderMIME, IdHashMessageDigest; function getMd5HashString(value: string): string; var MessageDigest: TIdHashMessageDigest5; Content: TIdBytes; begin //Content := TIdTextEncoding.UTF8.GetBytes(value); // for older versions of Indy Content := IndyTextEncoding_UTF8.GetBytes(value); MessageDigest := TIdHashMessageDigest5.Create; try Result := TIdEncoderMIME.EncodeBytes(MessageDigest.HashBytes(Content)); finally MessageDigest.Free; end; end; begin Writeln(getMd5HashString('<?xml version="1.0" encoding="utf-8"?>')); Readln; end. 

I use Indy to do all the conversion: text to UTF-8 bytes, MD5 hashing and base64 encoding. But for this you should use any libraries, since they should give the same result.

This program produces the same output for 32 and 64 bits, as you would expect:

I3pK / R + hpYOKY1IQRviZbQ ==

You report other behavior, so what could be the reason? I can think of the following possible explanations:

  • In fact, you are not passing the same input value to a function in both versions.
  • TEncoding.UTF8.GetBytes defective.
  • TIdHashMessageDigest5.HashBytes defective.
  • Data.Cloud.CloudAPI.EncodeBytes64 defective.

In any case, I see no reason to use Data.Cloud.CloudAPI to perform base64 encoding, although I have no reason to believe that this does not work. Since you are already using the Indy library, it makes sense to do this evenly.

I cannot say from here which of the above explanations is the reason that you are reporting. You must be able to debug this further in order to find out. Look at the result of each step of the process to find out where the behavior changes.


Update: Now I was able to reproduce the error, but only using the version of Indy that comes with XE2. In my initial experiments, I used a more modern version of Indy.

The problem is paragraph 3 on my list. This gives incorrect results with the x64 compiler.

You must solve the problem by finding another MD5 implementation. My recommendation is to do this by updating Indy.

+7
source

Source: https://habr.com/ru/post/1265950/


All Articles