MD5チェックサムを求めたいケースというのは、案外出てきます。
ちょっとしたパスワードの保存形式に使うこともあれば、ダウンロードしたファイルの誤り検出等々…
アルゴリズム自体難しいものではないので自作したクラスがあるのですが、その算出スピードということになると…どうかなぁ?
ま、とりあえず上げておきますので、入用でしたらご活用を。
TswMD5.h
//--------------------------------------------------------------------------- // MD5 (Message Digest 5) Algorithm Class // by Shue // 2004.09.10 //--------------------------------------------------------------------------- #ifndef MD5H #define MD5H //--------------------------------------------------------------------------- class TswMD5 : TObject { private: //----- 関数 ------------------------------------------------------------ unsigned int __fastcall funcF(unsigned int X, unsigned int Y, unsigned int Z); unsigned int __fastcall funcG(unsigned int X, unsigned int Y, unsigned int Z); unsigned int __fastcall funcH(unsigned int X, unsigned int Y, unsigned int Z); unsigned int __fastcall funcI(unsigned int X, unsigned int Y, unsigned int Z); unsigned int __fastcall funcJ(unsigned int A, unsigned int B, unsigned int C, unsigned int D, int K, int S, int i); unsigned int __fastcall funcK(unsigned int A, unsigned int B, unsigned int C, unsigned int D, int K, int S, int i); unsigned int __fastcall funcL(unsigned int A, unsigned int B, unsigned int C, unsigned int D, int K, int S, int i); unsigned int __fastcall funcM(unsigned int A, unsigned int B, unsigned int C, unsigned int D, int K, int S, int i); unsigned int __fastcall funcROTATE(unsigned int V, int S); //----- 変数 ------------------------------------------------------------ unsigned char *cSDAT; unsigned int T[64]; unsigned int X[16]; public: //----- 関数 ------------------------------------------------------------ __fastcall TswMD5(); // コンストラクタ __fastcall ~TswMD5(); // デストラクタ bool __fastcall MakeCheckSum(); // チェックサムの生成 bool __fastcall Reset(); // リセット bool __fastcall SetString(AnsiString strDATA); // 文字列データのセット bool __fastcall SetFile(AnsiString strPATH); // ファイルのセット //----- 変数 ------------------------------------------------------------ unsigned char Answer[16]; // チェックサムが納められる配列 unsigned char *Data; // 元データへのポインタ unsigned int DataLength; // 元データの長さ AnsiString CheckSum; // チェックサムを文字列形式で格納 }; //--------------------------------------------------------------------------- #endif
TswMD5.cpp
//--------------------------------------------------------------------------- // MD5 (Message Digest 5) Algorithm Class // by Shue // 2004.09.10 // ※このクラスの対象のデータはバイト単位とします。 //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include <math.h> #include "MD5.h" //--------------------------------------------------------------------------- #pragma package(smart_init) //--------------------------------------------------------------------------- __fastcall TswMD5::TswMD5() { // コンストラクタ // 配列、変数を初期化する cSDAT = NULL; for (int i = 0; i < 16; i++) { Answer[i] = 0; } // テーブルを生成 for (int i = 1; i < 65; i++) { if (sin(i) < 0) { T[i - 1] = (unsigned int)((double)4294967296 * (-1) * sin(i)); } else { T[i - 1] = (unsigned int)((double)4294967296 * sin(i)); } } } //--------------------------------------------------------------------------- __fastcall TswMD5::~TswMD5() { // デストラクタ delete cSDAT; } //--------------------------------------------------------------------------- bool __fastcall TswMD5::MakeCheckSum() { // チェックサムの生成 unsigned int A, B, C, D; unsigned int AA, BB, CC, DD; unsigned int iNEWL, iTMP, iCNT; unsigned int iCN1, iCN2, iPLEN; AnsiString strTMP; try { //********** Step1 ********** // データ全体にパディングを施す if ((DataLength % 64) > 55) { iPLEN = 120 - (DataLength % 64); } else { iPLEN = 56 - (DataLength % 64); } iNEWL = DataLength + iPLEN + 8; Data = (char*)realloc(Data, iNEWL); for (unsigned int j = DataLength; j < iNEWL; j++) { Data[j] = 0; } Data[DataLength] = 0x80; //********** Step2 ********** // データ長を付加する iCN1 = iCN2 = 0; if (((DataLength >> 29) & 0x07) != 0) { iCN2 = (DataLength >> 29) & 0x07; } else { iCN2 = 0; } iCN1 = DataLength << 3; memcpy(&Data[iNEWL - 8], &iCN1, 4); memcpy(&Data[iNEWL - 4], &iCN2, 4); //********** Step3 ********** // バッファを初期化する A = 0x67452301; B = 0xefcdab89; C = 0x98badcfe; D = 0x10325476; //********** Step4 ********** // 全てのデータを処理する for (unsigned int j = 0; j < iNEWL; j += 64) { // データを処理バッファにセットする //memcpy(X, &Data[j], 64); for (int k = 0; k < 64; k++) { iTMP = Data[j + k]; switch (k % 4) { case 3: iTMP = iTMP << 24; break; case 2: iTMP = iTMP << 16; break; case 1: iTMP = iTMP << 8; } iCNT = k / 4; if ((k % 4) == 0) { X[iCNT] = iTMP; } else { X[iCNT] = X[iCNT] | iTMP; } } // AをAAとし、BをBBとし、CをCCとし、DをDDとして保存する AA = A; BB = B; CC = C; DD = D; //----- Round 1 ----- A = funcJ(A, B, C, D, 0, 7, 1); D = funcJ(D, A, B, C, 1, 12, 2); C = funcJ(C, D, A, B, 2, 17, 3); B = funcJ(B, C, D, A, 3, 22, 4); A = funcJ(A, B, C, D, 4, 7, 5); D = funcJ(D, A, B, C, 5, 12, 6); C = funcJ(C, D, A, B, 6, 17, 7); B = funcJ(B, C, D, A, 7, 22, 8); A = funcJ(A, B, C, D, 8, 7, 9); D = funcJ(D, A, B, C, 9, 12, 10); C = funcJ(C, D, A, B, 10, 17, 11); B = funcJ(B, C, D, A, 11, 22, 12); A = funcJ(A, B, C, D, 12, 7, 13); D = funcJ(D, A, B, C, 13, 12, 14); C = funcJ(C, D, A, B, 14, 17, 15); B = funcJ(B, C, D, A, 15, 22, 16); //----- Round 2 ----- A = funcK(A, B, C, D, 1, 5, 17); D = funcK(D, A, B, C, 6, 9, 18); C = funcK(C, D, A, B, 11, 14, 19); B = funcK(B, C, D, A, 0, 20, 20); A = funcK(A, B, C, D, 5, 5, 21); D = funcK(D, A, B, C, 10, 9, 22); C = funcK(C, D, A, B, 15, 14, 23); B = funcK(B, C, D, A, 4, 20, 24); A = funcK(A, B, C, D, 9, 5, 25); D = funcK(D, A, B, C, 14, 9, 26); C = funcK(C, D, A, B, 3, 14, 27); B = funcK(B, C, D, A, 8, 20, 28); A = funcK(A, B, C, D, 13, 5, 29); D = funcK(D, A, B, C, 2, 9, 30); C = funcK(C, D, A, B, 7, 14, 31); B = funcK(B, C, D, A, 12, 20, 32); //----- Round 3 ----- A = funcL(A, B, C, D, 5, 4, 33); D = funcL(D, A, B, C, 8, 11, 34); C = funcL(C, D, A, B, 11, 16, 35); B = funcL(B, C, D, A, 14, 23, 36); A = funcL(A, B, C, D, 1, 4, 37); D = funcL(D, A, B, C, 4, 11, 38); C = funcL(C, D, A, B, 7, 16, 39); B = funcL(B, C, D, A, 10, 23, 40); A = funcL(A, B, C, D, 13, 4, 41); D = funcL(D, A, B, C, 0, 11, 42); C = funcL(C, D, A, B, 3, 16, 43); B = funcL(B, C, D, A, 6, 23, 44); A = funcL(A, B, C, D, 9, 4, 45); D = funcL(D, A, B, C, 12, 11, 46); C = funcL(C, D, A, B, 15, 16, 47); B = funcL(B, C, D, A, 2, 23, 48); //----- Round 4 ----- A = funcM(A, B, C, D, 0, 6, 49); D = funcM(D, A, B, C, 7, 10, 50); C = funcM(C, D, A, B, 14, 15, 51); B = funcM(B, C, D, A, 5, 21, 52); A = funcM(A, B, C, D, 12, 6, 53); D = funcM(D, A, B, C, 3, 10, 54); C = funcM(C, D, A, B, 10, 15, 55); B = funcM(B, C, D, A, 1, 21, 56); A = funcM(A, B, C, D, 8, 6, 57); D = funcM(D, A, B, C, 15, 10, 58); C = funcM(C, D, A, B, 6, 15, 59); B = funcM(B, C, D, A, 13, 21, 60); A = funcM(A, B, C, D, 4, 6, 61); D = funcM(D, A, B, C, 11, 10, 62); C = funcM(C, D, A, B, 2, 15, 63); B = funcM(B, C, D, A, 9, 21, 64); // 加算の実行 A += AA; B += BB; C += CC; D += DD; } // 結果をセットする strTMP = IntToHex((int)A, 8); for (int i = 0; i < 4; i++) { Answer[3 - i] = (char)(("0x" + strTMP.SubString((i * 2) + 1, 2)).ToInt()); } strTMP = IntToHex((int)B, 8); for (int i = 0; i < 4; i++) { Answer[7- i] = (char)(("0x" + strTMP.SubString((i * 2) + 1, 2)).ToInt()); } strTMP = IntToHex((int)C, 8); for (int i = 0; i < 4; i++) { Answer[11 - i] = (char)(("0x" + strTMP.SubString((i * 2) + 1, 2)).ToInt()); } strTMP = IntToHex((int)D, 8); for (int i = 0; i < 4; i++) { Answer[15 - i] = (char)(("0x" + strTMP.SubString((i * 2) + 1, 2)).ToInt()); } // 文字列も生成 CheckSum = ""; for (int i = 0; i < 16; i++) { CheckSum += IntToHex((int)Answer[i], 2); } return true; } catch(...) { return false; } } //--------------------------------------------------------------------------- bool __fastcall TswMD5::Reset() { // リセット try { free(cSDAT); cSDAT = Data = NULL; DataLength = 0; CheckSum = ""; return true; } catch(...) { return false; } } //--------------------------------------------------------------------------- bool __fastcall TswMD5::SetString(AnsiString strDATA) { // 文字列データのセット try { // 既存領域の破棄 free(cSDAT); cSDAT = Data = NULL; // メモリの確保 cSDAT = (unsigned char*)malloc(strDATA.Length() + 1); Data = cSDAT; DataLength = strDATA.Length(); CheckSum = ""; // データの複写 memcpy(cSDAT, strDATA.c_str(), DataLength); cSDAT[DataLength] = 0; return true; } catch(...) { free(cSDAT); cSDAT = Data = NULL; DataLength = 0; CheckSum = ""; return false; } } //--------------------------------------------------------------------------- bool __fastcall TswMD5::SetFile(AnsiString strPATH) { // ファイルのセット char cPATH[MAX_PATH]; HANDLE hFILE; unsigned long iFSIZE, iGSIZE; try { // パス名を変換 strcpy(cPATH, strPATH.c_str()); // ファイルを開く hFILE = ::CreateFile(cPATH, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); // ファイルサイズの取得 iFSIZE = (int)(::GetFileSize(hFILE, NULL)); // ファイルサイズが0xFFFFFFFFの場合はファイルオープン失敗 if (iFSIZE != 0xFFFFFFFF) { // メモリを確保する cSDAT = (unsigned char*)malloc(iFSIZE); Data = cSDAT; DataLength = iFSIZE; CheckSum = ""; // 変換元ファイルを一括で読込む ::ReadFile(hFILE, cSDAT, iFSIZE, &iGSIZE, NULL); // ファイルを閉じる ::CloseHandle(hFILE); return true; } else { // ファイルが開けなかった return false; } } catch(...) { return false; } } //--------------------------------------------------------------------------- unsigned int __fastcall TswMD5::funcF(unsigned int X, unsigned int Y, unsigned int Z) { // 補助関数F return ((X & Y) | ((~X) & Z)); } //--------------------------------------------------------------------------- unsigned int __fastcall TswMD5::funcG(unsigned int X, unsigned int Y, unsigned int Z) { // 補助関数G return ((X & Z) | (Y & (~Z))); } //--------------------------------------------------------------------------- unsigned int __fastcall TswMD5::funcH(unsigned int X, unsigned int Y, unsigned int Z) { // 補助関数H return (X ^ Y ^ Z); } //--------------------------------------------------------------------------- unsigned int __fastcall TswMD5::funcI(unsigned int X, unsigned int Y, unsigned int Z) { // 補助関数I return (Y ^ (X | (~Z))); } //--------------------------------------------------------------------------- unsigned int __fastcall TswMD5::funcJ(unsigned int A, unsigned int B, unsigned int C, unsigned int D, int K, int S, int i) { // 関数 a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s) return B + funcROTATE(A + funcF(B, C, D) + X[K] + T[i - 1], S); } //--------------------------------------------------------------------------- unsigned int __fastcall TswMD5::funcK(unsigned int A, unsigned int B, unsigned int C, unsigned int D, int K, int S, int i) { // 関数 a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s) return B + funcROTATE(A + funcG(B, C, D) + X[K] + T[i - 1], S); } //--------------------------------------------------------------------------- unsigned int __fastcall TswMD5::funcL(unsigned int A, unsigned int B, unsigned int C, unsigned int D, int K, int S, int i) { // 関数 a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s) return B + funcROTATE(A + funcH(B, C, D) + X[K] + T[i - 1], S); } //--------------------------------------------------------------------------- unsigned int __fastcall TswMD5::funcM(unsigned int A, unsigned int B, unsigned int C, unsigned int D, int K, int S, int i) { // 関数 a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s) return B + funcROTATE(A + funcI(B, C, D) + X[K] + T[i - 1], S); } //--------------------------------------------------------------------------- unsigned int __fastcall TswMD5::funcROTATE(unsigned int V, int S) { // 左ローテート関数 return ((V << S) | (V >> (32 - S))); } //---------------------------------------------------------------------------