@acidlemonについて
|'-')/ acidlemonです。鎌倉市在住で、鎌倉で働く普通のITエンジニアです。
30年弱住んだ北海道を離れ、鎌倉でまったりぽわぽわしています。
もう3週間ぐらい前の話ですが。
ファイルの改ざんをチェックする方法としてMD5を算出して、オリジナルのファイルとの相違がないことを調べるという方法があります。余談ですが、Winnyで特定のファイルを示すためのハッシュもファイルのMD5らしいですね。
というわけで、ちょっとファイルの改ざんチェックをしようと思ってMD5を算出してみようと思ったのですが、MD5ってどうやって算出するんだろうなぁ、というか、Windowsにファイルハンドル渡したらMD5がぽんと出てくるようなAPIは用意されていないのか!
…用意されてなかったようですが、某所で聞いたらWinNT系で使えるCryptAPIでMD5を算出することができるらしいので、これでやってみることに。ということで、「ファイルハンドルを渡したらぽんっとMD5が出てくるようなAPI」をここに書いておきます。
#include <windows.h> #include <wincrypt.h> char* CalcMD5(HANDLE hFile, char* szBuf){ *szBuf=NULL; if(hFile==INVALID_HANDLE_VALUE){ // fail to open return NULL; } // calc MD5 HCRYPTPROV hCryptProv=NULL; HCRYPTHASH hHash; // PROV_RSA_FULL support MD5 hash if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)){ return NULL; } // create empty md5 hash if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash)){ return NULL; } // read file and add to hashdata BYTE tmpBuf[4096]; DWORD dwRead; while(ReadFile(hFile, tmpBuf, 4096, &dwRead, NULL) && dwRead){ if(!CryptHashData(hHash, tmpBuf, dwRead, 0)){ // add hash return NULL; } } // calculate hash DWORD dwHashLen; BYTE *pbHash; if(!CryptGetHashParam(hHash, HP_HASHVAL, NULL, &dwHashLen, NULL)){ // get hash size return NULL; } if(!(pbHash=new BYTE[dwHashLen])){ return NULL; } if(!CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &dwHashLen, NULL)){ // get hash delete [] pbHash; return NULL; } // print hash char tmp[16]; *szBuf=NULL; for(DWORD i=0;i<dwHashLen; i++){ sprintf(tmp, _t("%2.2x"), pbHash[i]); strcat(szBuf, tmp); } // destroy delete [] pbHash; return szBuf; }
まぁ、たぶんこんな感じで動くと思います。MD5を格納するのに十分な配列(基本的には32バイトぐらいは必要?)と、Read可能なファイルハンドルをわたすと、配列にMD5を突っ込んでくれます。算出に失敗したときはNULL、成功したときは配列の先頭を返します。
…こんな関数を書かなくても、本気になればRFC1321よめばちゃんとCのサンプルコードも載ってるのでそっち使った方が早かったり…とか言っちゃダメですよ。