MFC
MD5ハッシュを生成する


HomeProgramming TipsMFC Tips[MFC-029]

 ダウンロード : MD5ハッシュ生成プログラムサンプル(2008/04/05) 

POP3 クラスの開発に必要な MD5 ハッシュの生成についてです。
今までは海外のクラスに頼っていたのですが、MFC なら何か方法があるはずだと思って探していました。
そしてなるほど、こうすればよいという方法が見つかりましたので記載しておきます。

その方法とは Crypt 関連 API を使用することです。
なんと嬉しい事に Windows98 OSR2 以降で使用できるため、事実上全ての Windows 環境で動作すると言っても良いでしょう。

まず、この API を使用するために次のヘッダーをインクルードします。


#include "wincrypt.h"


これで準備が出来ました。
最初にキーコンテナを準備します。
準備が出来ると HCRYPTPROV ハンドルが得られます。
このハンドルを使って CALG_MD5 を指定して MD5 ハッシュ計算のインスタンスを生成します。
インスタンス生成に成功すると HCRYPTHASH ハンドルが得られます。
このハンドルを使って任意の文字列のハッシュ値を計算します。
インスタンス内部に生成されたハッシュ値を CryptGetHashParam() にて取り出します。
取り出しに成功したら、あとは、各種リソースを開放します、
※ 深いです…


  BYTE        pbyHash[0x7f];
  HCRYPTPROV  hCryptProv  = NULL;
  HCRYPTHASH  hHash       = NULL;
  DWORD       dwHashLen   = 16;

  // キーコンテナを準備する
  if (::CryptAcquireContext(
        &hCryptProv, NULL, NULL, PROV_RSA_FULL,
        CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)
  ) {

      // MD5 ハッシュ計算のインスタンスを生成する
      if (::CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash)) {

          // ハッシュ値を計算する
          if (::CryptHashData(hHash, (BYTE*)c_pbySource, dwLen, 0)) {

              // 計算されたハッシュ値を取り出す
              if (::CryptGetHashParam(hHash, HP_HASHVAL, pbyHash, &dwHashLen, 0)) {

                  // 取り出しに成功したのでその文字列を指定の配列にコピーする
                  ::memcpy(pbyMD5Hash, pbyHash, dwHashLen);
              }
          }
      }
  }

  // 各種リソースを開放する
  if (hHash)      ::CryptDestroyHash(hHash);
  if (hCryptProv) ::CryptReleaseContext(hCryptProv, 0);


さて、このハッシュ計算に与える文字列は UTF-8 が一般的のようです。
そのため、Shift-JIS から UTF-8 にコンバートしなければ正しい値が得られません。
ネットで探したら下記のプログラムコードを拾いました。
一部手直ししましたが基本は全く同じです。
原理的には一旦 Unicode にしてから、UTF-8 に再変換するというモノです。


// ---------------------------------------------------------------------
// Shift-JIS を UTF-8 に変換する
// 参考/http://www.atmark.gr.jp/~s2000/r/rtl/encode.html
// ---------------------------------------------------------------------
BOOL SJIStoUTF8(CString& r_strText)
{
    if (r_strText.IsEmpty()) return FALSE;

    USES_CONVERSION;

    // ShiftJIS 文字列を Unicode に変換する
    LPWSTR lpw = T2W(static_cast<LPCTSTR>(r_strText));

    // Unicode 文字列を UTF-8 に変換する
    const int c_nMultiByte = (lstrlenW(lpw) + 1) * 3;
    LPSTR lpa = reinterpret_cast<LPSTR>(_alloca(c_nMultiByte));
    *lpa = '\0';
    const int nBytes = ::WideCharToMultiByte(
        CP_UTF8, 0, lpw, -1, lpa, c_nMultiByte, NULL, NULL
    );
    ATLASSERT(nBytes > 0);
    if (nBytes == 0) return FALSE;

    // 変換結果を反映する
    r_strText = lpa;

    return TRUE;
}


まあ、サンプルプログラムを見て頂いた方が簡単なんですけどね(汗)。


 Copyright 2008 VALGUS. All Rights Reserved.