views:

3659

answers:

10

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

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

Just have a look:

string : "123456"

hash:

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

I've tried a lot of md5 scripts, but delphi 2009 does the same with all of them. Any help? Thanks.

A: 

MD5 is a hash algorithm, not a cipher. As for why your script doesn't work in Delphi 2009, I have no idea.

Matthew Flaschen
A: 

Are you perchance casting a generic string (which in Delphi 2009 is a UnicodeString) to a PAnsiChar and passing that into the hash function? That will not work. You first must cast the string into an AnsiString and then cast that one to PAnsiChar, a la:

PAnsiChar(AnsiString('123456'))

Also, try using RawByteString instead of AnsiString like dmajkic suggested. Avoid UTF8String since that's not an AnsiString and any characters outside the ASCII range (0..127) might get reinterpreted into multibyte characters.

Mihai Limbășan
A: 

OK, I tried PChar(Ansistring('123456')), so now its.. "202cb962ac59075b964b07152d234b70" :D

Silly me, it should have been PAnsiChar instead of PChar. I edited my answer - try it with that. Also, if your string contains characters not in the ASCII range you'll probably be better off using RawByteString like dmajkic suggested.
Mihai Limbășan
Also, you should not use answers to your own question as comments for various reasons - one of which is that your answers will make no sense at all when using the default StackOverflow sort order (by Votes). Use comments to the provided answer or to your question to comment on them (or edit your q.)
Mihai Limbășan
+1  A: 

Have you checked that your library has been correctly updated for D2009 and unicodification? I kinda doubt the same code would do D7/D2007 and D2009 for this sort of things.

François
A: 

Heh, maybe it's not, I didn't know about that unicode at all... So how can I use md5 in Delphi 2009?

+1  A: 

It is obvious that your lib is not unicode enabled.

Convert your string to AnsiString or RawByteString or UTF8String by declaring temp AnsiString and assign your uniode string to it.

Note that if you are using unicode specific chars that can't be translated to single codepage, you should convert your string to UTF8.

Then call MD5(PAnsiChar(YourTempString)).

Check that your lib may have PWideChar or UNICODE declarations, to skip this.

dmajkic
+21  A: 

Your library is not Unicode aware. Just passing it an AnsiString won't be enough because it probably uses strings internally to store data.

You could try to update that library, wait for the author to update it, or just use the MessageDigest_5.pas that ships with Delphi 2009. It is in the source\Win32\soap\wsdlimporter folder, which you will need to either add to your path, or explicitly include it in your project.

Here is some sample 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 could wrap it in a simple function call if you wanted to. It is important you cast to a RawByteString before casting to a TByteDynArray since the RawByteString cast drops all the extra Unicode characters. Granted if the edit contains Unicode characters then you could end up with bad data.

Keep in mind that GetMD5 is returning an interface, so it is reference counted, etc.

Merry Christmas!

Jim McKeeth
A: 

Jim McKeeth, THANK YOU ! Finally :) Thanks you all for trying to help.

MERRY CHRISTMAS !

If Jim's answer helped you, you might want to consider to upvote it or, better yet, to, you know, choose it as the answer to the question... :) Common courtesy.
Mihai Limbășan
A: 

In Jim's answer:

if we change

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

to

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

will support better while Chinese characters exists.

+1  A: 

Before someone can comment on hashing algorithms, it helps if they have at least a fundamental understanding of the underlying concepts and principles. All of the responses so far which have focused on endless typecasting are completely overkill, but even worse, will result in unreliable results if a unicode string is being hashed.

The first thing you need to understand is that hashing and encryption algorithms operate at the byte-level. That means they don't care what you're hashing or encrypting. You can hash integers, chars, plain ASCII, full unicode, bytes, longwords, etc etc. The algorithm doesn't care.

When working with strings, the ONLY thing you have to ensure is that the internal function of your hashing library returns an AnsiString in the function which spits out your resulting hash. That's it. That's all that matters.

Your actual code for YOUR project can (and should) be based on normal string input, which maps to unicodestring in Delphi 2009. You shouldn't be typecasting anything to ansistring or rawbytestring. By doing so, you immediately create a broken hash if and when the user tries to hash anything outside the scope of the ANSI character set. And in the world of hashing, a broken hash is both unreliable AND insecure.

Thanks for the voice of reason. +1.
mghie