Indy10でMD5ハッシュを生成したくて調べていたのだが、古い情報ばっかりだったのでメモ。
古いのと比べて、TIdHashMessageDigest5のクラスはメソッド名が違ったり、増えたりしているようだ。
とりあえずこれでいけた。(Delphi2009)
indy_md5.dpr
program indy_md5; {$APPTYPE CONSOLE} uses SysUtils, IdHash, IdHashMessageDigest; function MD5FromString(AString: string): string; var md5: TIdHashMessageDigest5; begin md5 := TIdHashMessageDigest5.Create; try Result := md5.HashStringAsHex(AString); // これだと日本語はだめらしい finally FreeAndNil(md5); end; end; begin WriteLn(Md5FromString('abc')); end.
実行結果
>indy_md5 900150983CD24FB0D6963F7D28E17F72
追記
どうやら日本語を渡すと正しいハッシュ値?が出てこない様子。少し調べてみる。
エンコーディングの問題かな。Indy側でTIdEncodingのen7bitにされてるぽい。日本語はUTF8のハッシュ値がほしいのでどうにかする。
日本語を渡すと、en7bit(ASCII)でエンコードされてしまって文字列が壊れてるのかな。
Pythonで期待値を出力するコードを書く
# coding: utf8 from md5 import md5 def md5_from_string(s): return md5(s.encode('utf8')).hexdigest() def main(): print md5_from_string(u'あ') print md5_from_string(u'い') print md5_from_string(u'ほげほげ') print md5_from_string(u'ふがふがふが') if __name__ == '__main__': main()
実行結果
>python_md5.py 8c0c3027e3cfc3d644caab3847a505b0 655dcb0e6519c34baf6d9d53e1932389 69e285bae22889ad148c8e81dfeaabdd de62e61510adf02a2f5f78b50c3cac46
で、とりあえずDelphiのほうは、StreamにUTF8で書き込むようにした。
program indy_md5; {$APPTYPE CONSOLE} uses SysUtils, Classes, IdGlobal, IdHash, IdHashMessageDigest; function MD5FromString(AString: string): string; var md5: TIdHashMessageDigest5; stream: TStream; begin md5 := TIdHashMessageDigest5.Create; try stream := TMemoryStream.Create; try WriteStringToStream(stream, AString, enUTF8); stream.Position := 0; Result := LowerCase(md5.HashStreamAsHex(stream)); finally FreeAndNil(stream); end; finally FreeAndNil(md5); end; end; begin WriteLn(Md5FromString('あ')); WriteLn(Md5FromString('い')); WriteLn(Md5FromString('ほげほげ')); WriteLn(Md5FromString('ふがふがふが')); end.
実行結果
>indy_md5 8c0c3027e3cfc3d644caab3847a505b0 655dcb0e6519c34baf6d9d53e1932389 69e285bae22889ad148c8e81dfeaabdd de62e61510adf02a2f5f78b50c3cac46
Indyのハッシュを計算するクラスにTIdEncodingを指定できるとうれしいのかな。でもそれだと、SJISとか困るだろうからTEncodingを使えるほうがいいような気がする。