Indy10で文字列からMD5ハッシュを生成する

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を使えるほうがいいような気がする。