MD5 Hashing in Delphi 2009

In borland delphi 7 and even in delphi 2007 everything worked, but in delphi 2009 it just returns the wrong hash!

I am using wcrypt2 script ( http://pastebin.com/m2f015cfd )

Just look:

string: "123456"

Hash:

Delphi 7: "e10adc3949ba59abbe56e057f20f883e" is a real hash.
Delphi 2007: "e10adc3949ba59abbe56e057f20f883e" is a real hash too.
And also ... Delphi 2009: "5fa285e1bebe0a6623e33afc04a1fbd5" - WTF ??

I have tried many md5 scripts, but delphi 2009 does the same with all of them. Any help? Thanks.

+6
unicode delphi delphi-2009 hash md5
source share
7 answers

Your library does not support Unicode. Just passing it to AnsiString will not be enough, because it probably uses internal strings to store data.

You can try updating this library, waiting for the author to update it, or just use the MessageDigest_5.pas that comes with Delphi 2009. It is in the original \ Win32 \ soap \ wsdlimporter which you will need to either add to your path or explicitly enable into the project.

Here is an example of the code using it in Delphi 2009:

uses Types, MessageDigest_5; procedure TForm16.Edit1Change(Sender: TObject); var MD5: IMD5; begin MD5 := GetMD5; MD5.Init; MD5.Update(TByteDynArray(RawByteString(Edit1.Text)), Length(Edit1.Text)); Edit2.Text := LowerCase(MD5.AsString); end; 

And you are in business:

MD5 (123456) = e10adc3949ba59abbe56e057f20f883e

You can wrap it with a simple function call if you want. It is important that before you make TByteDynArray , before casting RawByteString , because when you click RawByteString, all the extra Unicode characters. If editing contains Unicode characters, you may get bad data.

Keep in mind that GetMD5 returns an interface, so a link is calculated, etc.

Merry Christmas!

+30
source share

Before anyone can comment on hashing algorithms, it will help if they have at least a fundamental understanding of fundamental concepts and principles. All answers that focused on infinite typecasting are completely crowded, but even worse, will lead to unreliable results if a Unicode string is hashed.

The first thing you need to understand is that hashing and encryption algorithms work at the byte level. This means they don’t care if you haveh or encrypt it. You can hash integers, characters, ASCII primes, full unicode, bytes, words, etc. Otherwise, the algorithm does not care.

When working with strings ONLY you need to make sure that the internal function of your hash library returns AnsiString in the function that spits out your hash. It. That is all that matters.

Your actual code for YOUR project can (and should) be based on the normal input of a string that maps to unicodestring in Delphi 2009. You should not attribute anything to anyone who does nothing or is not processed. By doing so, you immediately create a broken hash if and when the user tries to hash something outside the ANSI character set. And in the hashing world, a broken hash is unreliable and insecure.

+5
source share

Have you verified that your library has been updated correctly for D2009 and unicodification? I doubt that the same code will do D7 / D2007 and D2009 for such things.

+1
source share

Obviously your lib is not included in unicode.

Convert your string to AnsiString or RawByteString or UTF8String by declaring a temporary AnsiString and assigning it a uniode string.

Please note that if you use unique unicode characters that cannot be translated into a single code page, you must convert your string to UTF8.

Then call MD5 (PAnsiChar (YourTempString)).

Make sure your library can have PWideChar or UNICODE declarations to skip this.

+1
source share

If you have wcrypt2.pas , use this function.

 function md5ansi(const Input: AnsiString): AnsiString; var hCryptProvider: HCRYPTPROV; hHash: HCRYPTHASH; bHash: array[0..$7f] of Byte; dwHashBytes: Cardinal; pbContent: PByte; i: Integer; begin dwHashBytes := 16; pbContent := Pointer(PAnsiChar(Input)); Result := ''; if CryptAcquireContext(@hCryptProvider, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT or CRYPT_MACHINE_KEYSET) then begin if CryptCreateHash(hCryptProvider, CALG_MD5, 0, 0, @hHash) then begin if CryptHashData(hHash, pbContent, Length(Input) * sizeof(AnsiChar), 0) then begin if CryptGetHashParam(hHash, HP_HASHVAL, @bHash[0], @dwHashBytes, 0) then begin for i := 0 to dwHashBytes - 1 do begin Result := Result + AnsiString(Format('%.2x', [bHash[i]])); end; end; end; CryptDestroyHash(hHash); end; CryptReleaseContext(hCryptProvider, 0); end; Result := AnsiString(AnsiLowerCase(String(Result))); end; 
+1
source share

Do you list the common string (which is UnicodeString in Delphi 2009) in PAnsiChar and pass it into a hash function? This will not work. You must first enter a string in AnsiString, and then pass it to PAnsiChar, a la:

 PAnsiChar(AnsiString('123456')) 

Also, try using RawByteString instead of AnsiString, as dmajkic suggested. Avoid UTF8String as it is not AnsiString and any characters outside the ASCII range (0..127) can be reinterpreted into multibyte characters.

0
source share

In response, Jim:

if we change

MD5.Update (TByteDynArray (RawByteString (Edit1.Text)), Length (Edit1.Text));

to

MD5.Update (TByteDynArray (RawByteString (Edit1.Text)), Length (RawByteString (Edit1.Text)));

will be supported better as long as the characters exist.

-3
source share

All Articles