7

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.

4

7 回答 7

31

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!

于 2008-12-25T11:11:37.717 回答
5

在有人可以评论散列算法之前,如果他们至少对基本概念和原理有基本的了解,这会有所帮助。到目前为止,所有关注于无休止类型转换的响应都完全是矫枉过正,但更糟糕的是,如果对 unicode 字符串进行哈希处理,将导致不可靠的结果。

您需要了解的第一件事是散列和加密算法在字节级别上运行。这意味着他们不在乎你在散列或加密什么。您可以散列整数、字符、纯 ASCII、完整的 unicode、字节、长字等。算法不在乎。

使用字符串时,您必须确保的唯一事情是哈希库的内部函数在函数中返回一个 AnsiString,该函数会吐出生成的哈希值。而已。这才是最重要的。

您的项目的实际代码可以(并且应该)基于正常的字符串输入,它映射到 Delphi 2009 中的 unicodestring。您不应该将任何内容强制转换为 ansistring 或 rawbytestring。通过这样做,如果用户尝试散列 ANSI 字符集范围之外的任何内容,您将立即创建一个损坏的散列。在散列的世界中,一个损坏的散列既不可靠又不安全。

于 2009-04-09T23:23:41.950 回答
1

如果有wcrypt2.pas,请使用此功能。

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;
于 2010-12-28T09:36:05.730 回答
1

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.

于 2008-12-25T09:45:42.943 回答
1

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.

于 2008-12-25T10:41:20.633 回答
0

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.

于 2008-12-25T09:37:11.963 回答
-3

在吉姆的回答中:

如果我们改变

MD5.Update(TByteDynArray(RawByteString(Edit1.Text)),长度(Edit1.Text));

MD5.Update(TByteDynArray(RawByteString(Edit1.Text)), 长度(RawByteString(Edit1.Text)));

存在汉字时会更好地支持。

于 2009-03-18T08:59:09.020 回答