Delphi 2009 中的 MD5 哈希

发布于 2024-07-11 00:18:04 字数 510 浏览 9 评论 0原文

在 borland delphi 7 甚至 delphi 2007 中一切正常,但在 delphi 2009 中它只是返回错误的散列!

我使用 wcrypt2 脚本(http://pastebin.com/m2f015cfd

看看:

string : "123456"

哈希:

Delphi 7:“e10adc3949ba59abbe56e057f20f883e” - 真正的哈希。
Delphi 2007:“e10adc3949ba59abbe56e057f20f883e” - 也是真正的哈希值。
和... 德尔福 2009:“5fa285e1bebe0a6623e33afc04a1fbd5”-WTF?

我已经尝试了很多 md5 脚本,但 delphi 2009 对所有这些脚本都做了同样的事情。 有什么帮助吗? 谢谢。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

夏天碎花小短裙 2024-07-18 00:18:04

您的库不支持 Unicode。 仅向其传递 AnsiString 是不够的,因为它可能在内部使用字符串来存储数据。

您可以尝试更新该库,等待作者更新它,或者仅使用 Delphi 2009 附带的 MessageDigest_5.pas。它位于 source\Win32\soap\wsdlimporter 中 文件夹,您需要将其添加到您的路径中,或者将其显式包含在您的项目中。

以下是在 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;

现在您正在做生意:

MD5(123456) = e10adc3949ba59abbe56e057f20f883e

如果您愿意,您可以将其包装在一个简单的函数调用中。 在转换为 TByteDynArray 之前转换为 RawByteString 非常重要,因为 RawByteString 转换会删除所有额外的 Unicode 字符。 当然,如果编辑包含 Unicode 字符,那么您最终可能会得到错误的数据。

请记住,GetMD5 返回一个接口,因此它是引用计数的,等等。

圣诞快乐!

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!

淡淡的优雅 2024-07-18 00:18:04

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

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

使用字符串时,您唯一需要确保的是哈希库的内部函数在函数中返回 AnsiString,该函数会输出生成的哈希值。 就是这样。 这才是最重要的。

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

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.

东风软 2024-07-18 00:18:04

您是否检查过您的图书馆是否已针对 D2009 和统一编码正确更新?
我有点怀疑相同的代码是否可以为 D7/D2007 和 D2009 执行此类操作。

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.

守不住的情 2024-07-18 00:18:04

很明显,您的 lib 未启用 unicode。

通过声明 temp AnsiString 并将您的 uniode 字符串分配给它,将您的字符串转换为 AnsiString 或 RawByteString 或 UTF8String。

请注意,如果您使用无法转换为单个代码页的 unicode 特定字符,则应将字符串转换为 UTF8。

然后调用 MD5(PAnsiChar(YourTempString))。

检查您的库是否可能有 PWideChar 或 UNICODE 声明,以跳过此操作。

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.

情独悲 2024-07-18 00:18:04

如果您有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;

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;
对不⑦ 2024-07-18 00:18:04

您是否可能将通用字符串(在 Delphi 2009 中是 UnicodeString)转换为 PAnsiChar 并将其传递到哈希函数中? 这是行不通的。 您首先必须将字符串转换为 AnsiString,然后将该字符串转换为 PAnsiChar,a:

PAnsiChar(AnsiString('123456'))

另外,请尝试使用 RawByteString 而不是像 dmajkic 建议的 AnsiString。 避免使用 UTF8String,因为它不是 AnsiString,并且 ASCII 范围 (0..127) 之外的任何字符都可能会被重新解释为多字节字符。

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.

濫情▎り 2024-07-18 00:18:04

在吉姆的回答中:

如果我们更改

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文