7

borland delphi 7 および delphi 2007 ではすべてが機能しましたが、delphi 2009 では間違ったハッシュが返されるだけです。

wcrypt2 スクリプトを使用します ( http://pastebin.com/m2f015cfd )

ちょっと見てください:

文字列:「123456」

ハッシュ:

Delphi 7 : "e10adc3949ba59abbe56e057f20f883e" - 実際のハッシュ。
Delphi 2007 : "e10adc3949ba59abbe56e057f20f883e" - 実際のハッシュも。
そして... Delphi 2009: "5fa285e1bebe0a6623e33afc04a1fbd5" - WTF??

多くの md5 スクリプトを試しましたが、delphi 2009 はそれらすべてで同じことを行います。何か助けはありますか?ありがとう。

4

7 に答える 7

31

ライブラリはUnicodeに対応していません。AnsiStringを渡すだけでは、データを格納するために内部的に文字列を使用する可能性があるため、十分ではありません。

そのライブラリを更新するか、作成者が更新するのを待つか、Delphi2009に付属のMessageDigest_5.pasを使用することができます。これはsource\ Win32 \ soap \ wsdlimporterフォルダーにあり、次のいずれかに追加する必要があります。パス、またはプロジェクトに明示的に含めます。

Delphi2009で使用しているサンプルコードは次のとおりです。

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

必要に応じて、単純な関数呼び出しでラップすることもできます。RawByteStringキャストは余分なUnicode文字をすべて削除するため、TByteDynArrayにキャストする前にRawByteStringにキャストすることが重要です。編集にUnicode文字が含まれている場合は、データが不良になる可能性があります。

GetMD5はインターフェースを返すため、参照カウントなどであることに注意してください。

メリークリスマス!

于 2008-12-25T11:11:37.717 に答える
5

誰かがハッシュ アルゴリズムについてコメントする前に、基礎となる概念と原則について少なくとも基本的な理解があれば役に立ちます。無限の型キャストに焦点を当てたこれまでのすべての応答は完全にやり過ぎですが、さらに悪いことに、Unicode 文字列がハッシュされている場合は信頼できない結果になります。

最初に理解する必要があるのは、ハッシュ アルゴリズムと暗号化アルゴリズムがバイト レベルで動作することです。つまり、彼らはあなたが何をハッシュまたは暗号化しているかを気にしません。整数、文字、プレーン ASCII、完全な Unicode、バイト、ロングワードなどをハッシュできます。アルゴリズムは気にしません。

文字列を操作する場合、唯一確認しなければならないことは、ハッシュ ライブラリの内部関数が、結果のハッシュを吐き出す関数で AnsiString を返すことです。それでおしまい。それは重要なことのすべてです。

あなたのプロジェクトの実際のコードは、Delphi 2009 では unicodestring にマップされる通常の文字列入力に基づくことができます (そしてそうすべきです)。これにより、ユーザーが ANSI 文字セットの範囲外のものをハッシュしようとすると、すぐに壊れたハッシュが作成されます。そしてハッシュの世界では、壊れたハッシュは信頼性が低く、安全ではありません。

于 2009-04-09T23:23:41.950 に答える
1

libがUnicode対応ではないことは明らかです。

temp AnsiStringを宣言して文字列をAnsiString、RawByteString、またはUTF8Stringに変換し、それにユニオード文字列を割り当てます。

単一のコードページに変換できないUnicode固有の文字を使用している場合は、文字列をUTF8に変換する必要があることに注意してください。

次に、MD5(PAnsiChar(YourTempString))を呼び出します。

これをスキップするには、ライブラリにPWideCharまたはUNICODE宣言が含まれている可能性があることを確認してください。

于 2008-12-25T10:41:20.633 に答える
1

ライブラリが D2009 とユニコード化のために正しく更新されていることを確認しましたか? この種のことに対して、同じコードが D7/D2007 と D2009 を実行するとは思えません。

于 2008-12-25T09:45:42.943 に答える
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 に答える
0

一般的な文字列 (Delphi 2009 では UnicodeString) を PAnsiChar にキャストし、それをハッシュ関数に渡す可能性がありますか? それはうまくいきません。最初に文字列を AnsiString にキャストし、次にその文字列を PAnsiChar にキャストする必要があります。

PAnsiChar(AnsiString('123456'))

また、dmajkic のように AnsiString の代わりに RawByteString を使用してみてください。UTF8String は AnsiString ではなく、ASCII 範囲 (0..127) 外の文字はマルチバイト文字に再解釈される可能性があるため、避けてください。

于 2008-12-25T09:37:11.963 に答える
-3

ジムの答えでは:

私たちが変われば

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

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

漢字が存在する間はより適切にサポートされます。

于 2009-03-18T08:59:09.020 に答える