近日要用到文件校驗算法,查看了一下相關(guān)資料,得到以下理論與實(shí)踐經(jīng)驗。
一、理論部分:
1、預備知識
1.1什么是數據校驗
通俗的說(shuō),就是為保證數據的完整性,用一種指定的算法對原始數據計算出的一個(gè)校驗值。接收方用同樣的算法計算一次校驗值,如果和隨數據提供的校驗值一樣,就說(shuō)明數據是完整的。
1.2最簡(jiǎn)單的檢驗
實(shí)現方法:最簡(jiǎn)單的校驗就是把原始數據和待比較數據直接進(jìn)行比較,看是否完全一樣這種方法是最安全最準確的。同時(shí)也是效率最低的。
適用范圍:簡(jiǎn)單的數據量極小的通訊。
應用例子:龍珠CPU在線(xiàn)調試工具bbug.exe。它和龍珠cpu間通訊時(shí),bbug發(fā)送一個(gè)字節cpu返回收到的字節,bbug確認是剛才發(fā)送字節后才繼續發(fā)送下一個(gè)字節的。
1.3奇偶校驗ParityCheck
實(shí)現方法:在數據存儲和傳輸中,字節中額外增加一個(gè)比特位,用來(lái)檢驗錯誤。校驗位可以通過(guò)數據位異或計算出來(lái)。
應用例子:?jiǎn)纹瑱C串口通訊有一模式就是8位數據通訊,另加第9位用于放校驗值。
1.4bcc異或校驗法(blockcheckcharacter)
實(shí)現方法:很多基于串口的通訊都用這種既簡(jiǎn)單又相當準確的方法。它就是把所有數據都和一個(gè)指定的初始值(通常是0)異或一次,最后的結果就是校驗值,通常
把她附在通訊數據的最后一起發(fā)送出去。接收方收到數據后自己也計算一次異或和校驗值,如果和收到的校驗值一致就說(shuō)明收到的數據是完整的。
校驗值計算的代碼類(lèi)似于:
unsigneduCRC=0;//校驗初始值
for(inti=0;i<DataLenth;i )uCRC^=Data[i];
適用范圍:適用于大多數要求不高的數據通訊。
應用例子:ic卡接口通訊、很多單片機系統的串口通訊都使用。
1.5crc循環(huán)冗余校驗(CyclicRedundancyCheck)
實(shí)現方法:這是利用除法及余數的原理來(lái)進(jìn)行錯誤檢測的.將接收到的碼組進(jìn)行除法運算
,如果除盡,則說(shuō)明傳輸無(wú)誤;如果未除盡,則表明傳輸出現差錯。crc校驗
具還有自動(dòng)糾錯能力。
crc檢驗主要有計算法和查表法兩種方法,網(wǎng)上很多實(shí)現代碼。
適用范圍:CRC-12碼通常用來(lái)傳送6-bit字符串;CRC-16及CRC-CCITT碼則用是來(lái)傳送
8-bit字符。CRC-32:硬盤(pán)數據,網(wǎng)絡(luò )傳輸等
應用例子:rar,以太網(wǎng)卡芯片、MPEG解碼芯片中
1.6md5校驗和數字簽名
實(shí)現方法:主要有md5和des算法。
適用范圍:數據比較大或要求比較高的場(chǎng)合。如md5用于大量數據、文件校驗,des用于保密數據的校驗(數字簽名)等等。
應用例子:文件校驗、銀行系統的交易數據
2、具體的實(shí)現理論
2.1算法概述
MD5算法是MD4算法的改進(jìn)算法。RonRivest于1990年提出MD4單向散列函數,MD表示消息摘要(MessageDigest),對輸入消息,算法產(chǎn)生128位散列值。該算法首次公布之后,BertdenBoer和AntoonBosselaers對算法三輪中的后兩輪進(jìn)行了成功的密碼分析。在一個(gè)不相關(guān)的分析結果中,RalphMerKle成功地攻擊了前兩輪。盡管這些攻擊都沒(méi)有擴展到整個(gè)算法,但Rivest還是改進(jìn)了其算法,結果就是MD5算法。
MD5算法是MD4的改進(jìn)算法,它比MD4更復雜,但設計思想相似,輸入的消息可任意長(cháng),輸出結果也仍為128位,特別適用于高速軟件實(shí)現,是基于32-位操作數的一些簡(jiǎn)單的位操作。
2.2算法步驟
l 將輸入消息按512-位分組,最后要填充成為512位的整數倍,且最后一組的后64位用來(lái)填充消息長(cháng)度(填充前)。填充方法為附一個(gè)1在消息后,后接所要求的多個(gè)0。這樣可以確保不同消息在填充后不相同。
l 由于留出64位用來(lái)表示消息長(cháng)度,那么消息的長(cháng)度最多可達264字節,相當于4G×4G字節,文件的長(cháng)度是不可能達到這么大,因此通常都是只采用64位中的低32位來(lái)表示消息長(cháng)度,高32位填充0。
l 初始化MD變量。由于每輪輸出128位,這128位可用下面四個(gè)32位字A,B,C,D來(lái)表示。其初始值設為:
A=0x01234567 二、實(shí)現方法 //ConstantsforTransformroutine. //TransformationConstants-Round1 //TransformationConstants-Round2 //TransformationConstants-Round3 //TransformationConstants-Round4 protected: //RSAMD5implementation //utilityfunctions private: #endif//!defined(AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_) //checksumthefileinblocksof1024bytes //finalisethechecksumandreturnit //reportanyfileexceptionsindebugmodeonly //calculateandreturnthechecksum //rotateandreturnx //initialisations //transferthedatabyshiftingandcopying /***************************************************************************************** //copyBYTESfrominput'Block'toanarrayofULONGS'X' //PerformRound1ofthetransformation //PerformRound2ofthetransformation //PerformRound3ofthetransformation //PerformRound4ofthetransformation //addthetransformedvaluestothecurrentchecksum //Loadmagicstateinitializationconstants /***************************************************************************************** //transferthedatabyshiftingandcopying //Padoutto56mod64. //Appendlength(beforepadding) //Storefinalstatein'lpszMD5' //ConvertthehexadecimalchecksumtoaCString ASSERT(Str.GetLength()==2); //Updatenumberofbits //Transformasmanytimesaspossible. //Bufferremaininginput
B=0x89ABCDEF
C=0xFEDCBA98
D=0x76543210
l 開(kāi)始進(jìn)入算法主循環(huán),循環(huán)的次數是消息中512位消息分組的數目。先將上面A、B、C、D四個(gè)變量分別復制到另外四個(gè)變量a、b、c、d中去。主循環(huán)有四輪,每輪很相似。每輪進(jìn)行16次操作,每次操作對a、b、c、d四個(gè)變量中的三個(gè)作一次非線(xiàn)性函數運算,然后將所得結果加上第四個(gè)變量,消息的一個(gè)子分組和一個(gè)常數。再將所得結果向右環(huán)移一個(gè)不定的數,并加上a,b,c或d中之一。最后用該結果取代a,b,c或d中之一。
以下是每次操作中用到的四個(gè)非線(xiàn)性函數(每輪一個(gè))。
F(X,Y,Z)=(X∧Y)∨((X)∧Z)
G(X,Y,Z)=(X∧Z)∨(Y∧(Z))
H(X,Y,Z)=X⊕Y⊕Z
I(X,Y,Z)=Y⊕(X∨(Z))
其中,⊕是異或,∧是與,∨是或,是反符號。
這些函數是這樣設計的:如果X、Y和Z的對應位是獨立和均勻的,那么結果的每一位也應是獨立和均勻的。函數F是按逐位方式操作:如果X,那么Y,否則Z。函數H是逐位奇偶操作符。
設Mj表示消息的第j個(gè)子分組(從0到15),<<<s表示循環(huán)左移s,則四種操作為:
FF(a,b,c,d,Mj,s,ti)表示a=b ((a F(b,c,d) Mj ti)<<<s)
GG(a,b,c,d,Mj,s,ti)表示a=b ((a G(b,c,d) Mj ti)<<<s)
HH(a,b,c,d,Mj,s,ti)表示a=b ((a H(b,c,d) Mj ti)<<<s)
II(a,b,c,d,Mj,s,ti)表示a=b ((a I(b,c,d) Mj ti)<<<s)
四輪(64步)結果略。
注:常數ti的選擇:
第i步中,ti是232×abs(sin(i))的整數部分,i的單位是弧度。
所有這些完成之后,將A,B,C,D分別加上a,b,c,d。然后用下一分組數據繼續運行算法,最后的輸出是A,B,C和D的級聯(lián)。
l 最后得到的A,B,C,D就是輸出結果,A是低位,D為高位,DCBA組成128位輸出結果。
2.3MD5的安全性
RonRivest概述了MD5安全性[8]:
l 與MD4相比,增加了第四輪。
l 每一步均有唯一的加法常數。
l 為減弱第二輪中函數G的對稱(chēng)性從((X∧Y)∨(X∧Z)∨(Y∧Z))變?yōu)?(X∧Z)∨(Y∧(Z)))。
l 每一步加上了上一步的結果,引起更快的雪崩效應。
l 改變了第二輪和第三輪中訪(fǎng)問(wèn)消息子分組的次序,使其形式更不相似。
l 近似優(yōu)化了每一輪中的循環(huán)左移位移量以實(shí)現更快的雪崩效應。各輪的位移量互不相同。
從安全角度講,MD5的輸出為128位,若采用純強力攻擊尋找一個(gè)消息具有給定Hash值的計算困難性為2128,用每秒可試驗1000000000個(gè)消息的計算機需時(shí)1.07×1022年。若采用生日攻擊法,尋找有相同Hash值的兩個(gè)消息需要試驗264個(gè)消息,用每秒可試驗1000000000個(gè)消息的計算機需時(shí)585年。
由于此處的文件校驗用到要求比較高的場(chǎng)合,故采用了方法6,md5校驗算法,從CodeGuru下載了一個(gè)md5校驗算法的實(shí)現模塊,加入自己要校驗的文件名,實(shí)現完成。下面具體描述一下實(shí)現過(guò)程:
1、創(chuàng )建一個(gè)簡(jiǎn)單的對話(huà)框程序;
2、設置CString類(lèi)型的變量m_filename和m_strFileChecksum以存放要校驗的文件名和校驗和;
3、在對話(huà)框類(lèi)中創(chuàng )建ChecksumSelectedFile()函數,調用md5校驗和類(lèi)(附錄中有其實(shí)現文件)中的GetMD5計算文件校驗和。
4、使用定時(shí)器定時(shí)巡檢該文件的校驗和,一旦發(fā)現校驗和發(fā)生變化,立刻出現提示。
三、附錄(md5算法實(shí)現的源碼)
以下代碼實(shí)現均來(lái)自www.codeguru.com。
1、MD5ChecksumDefines.h(定義相關(guān)常量的頭文件)
//Magicinitializationconstants
#defineMD5_INIT_STATE_00x67452301
#defineMD5_INIT_STATE_10xefcdab89
#defineMD5_INIT_STATE_20x98badcfe
#defineMD5_INIT_STATE_30x10325476
#defineMD5_S11 7
#defineMD5_S1317
#defineMD5_S1422
#defineMD5_S21 5
#defineMD5_S22 9
#defineMD5_S2314
#defineMD5_S2420
#defineMD5_S31 4
#defineMD5_S3211
#defineMD5_S3316
#defineMD5_S3423
#defineMD5_S41 6
#defineMD5_S4210
#defineMD5_S4315
#defineMD5_S4421
#defineMD5_T01 0xd76aa478//TransformationConstant1
#defineMD5_T02 0xe8c7b756//TransformationConstant2
#defineMD5_T03 0x242070db//TransformationConstant3
#defineMD5_T04 0xc1bdceee//TransformationConstant4
#defineMD5_T05 0xf57c0faf//TransformationConstant5
#defineMD5_T06 0x4787c62a//TransformationConstant6
#defineMD5_T07 0xa8304613//TransformationConstant7
#defineMD5_T08 0xfd469501//TransformationConstant8
#defineMD5_T09 0x698098d8//TransformationConstant9
#defineMD5_T10 0x8b44f7af//TransformationConstant10
#defineMD5_T11 0xffff5bb1//TransformationConstant11
#defineMD5_T12 0x895cd7be//TransformationConstant12
#defineMD5_T13 0x6b901122//TransformationConstant13
#defineMD5_T14 0xfd987193//TransformationConstant14
#defineMD5_T15 0xa679438e//TransformationConstant15
#defineMD5_T16 0x49b40821//TransformationConstant16
#defineMD5_T17 0xf61e2562//TransformationConstant17
#defineMD5_T18 0xc040b340//TransformationConstant18
#defineMD5_T19 0x265e5a51//TransformationConstant19
#defineMD5_T20 0xe9b6c7aa//TransformationConstant20
#defineMD5_T21 0xd62f105d//TransformationConstant21
#defineMD5_T22 0x02441453//TransformationConstant22
#defineMD5_T23 0xd8a1e681//TransformationConstant23
#defineMD5_T24 0xe7d3fbc8//TransformationConstant24
#defineMD5_T25 0x21e1cde6//TransformationConstant25
#defineMD5_T26 0xc33707d6//TransformationConstant26
#defineMD5_T27 0xf4d50d87//TransformationConstant27
#defineMD5_T28 0x455a14ed//TransformationConstant28
#defineMD5_T29 0xa9e3e905//TransformationConstant29
#defineMD5_T30 0xfcefa3f8//TransformationConstant30
#defineMD5_T31 0x676f02d9//TransformationConstant31
#defineMD5_T32 0x8d2a4c8a//TransformationConstant32
#defineMD5_T33 0xfffa3942//TransformationConstant33
#defineMD5_T34 0x8771f681//TransformationConstant34
#defineMD5_T35 0x6d9d6122//TransformationConstant35
#defineMD5_T36 0xfde5380c//TransformationConstant36
#defineMD5_T37 0xa4beea44//TransformationConstant37
#defineMD5_T38 0x4bdecfa9//TransformationConstant38
#defineMD5_T39 0xf6bb4b60//TransformationConstant39
#defineMD5_T40 0xbebfbc70//TransformationConstant40
#defineMD5_T41 0x289b7ec6//TransformationConstant41
#defineMD5_T42 0xeaa127fa//TransformationConstant42
#defineMD5_T43 0xd4ef3085//TransformationConstant43
#defineMD5_T44 0x04881d05//TransformationConstant44
#defineMD5_T45 0xd9d4d039//TransformationConstant45
#defineMD5_T46 0xe6db99e5//TransformationConstant46
#defineMD5_T47 0x1fa27cf8//TransformationConstant47
#defineMD5_T48 0xc4ac5665//TransformationConstant48
#defineMD5_T49 0xf4292244//TransformationConstant49
#defineMD5_T50 0x432aff97//TransformationConstant50
#defineMD5_T51 0xab9423a7//TransformationConstant51
#defineMD5_T52 0xfc93a039//TransformationConstant52
#defineMD5_T53 0x655b59c3//TransformationConstant53
#defineMD5_T54 0x8f0ccc92//TransformationConstant54
#defineMD5_T55 0xffeff47d//TransformationConstant55
#defineMD5_T56 0x85845dd1//TransformationConstant56
#defineMD5_T57 0x6fa87e4f//TransformationConstant57
#defineMD5_T58 0xfe2ce6e0//TransformationConstant58
#defineMD5_T59 0xa3014314//TransformationConstant59
#defineMD5_T60 0x4e0811a1//TransformationConstant60
#defineMD5_T61 0xf7537e82//TransformationConstant61
#defineMD5_T62 0xbd3af235//TransformationConstant62
#defineMD5_T63 0x2ad7d2bb//TransformationConstant63
#defineMD5_T64 0xeb86d391//TransformationConstant64
//Nulldata(exceptforfirstBYTE)usedtofinalisethechecksumcalculation
staticunsignedcharPADDING[64]={
0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
2、CountChecksum.h(md5校驗和類(lèi)的頭文件)
classCMD5Checksum
{
public:
//interfacefunctionsfortheRSAMD5calculation
staticCStringGetMD5(BYTE*PBuf,UINTnLength);
staticCStringGetMD5(CFile&File);
staticCStringGetMD5(constCString&strFilePath);
//constructor/destructor
CMD5Checksum();
virtual~CMD5Checksum(){};
voidTransform(BYTEBlock[64]);
voidUpdate(BYTE*Input,ULONGnInputLen);
CStringFinal();
inlineDWORDRotateLeft(DWORDx,intn);
inlinevoidFF(DWORD&A,DWORDB,DWORDC,DWORDD,DWORDX,DWORDS,DWORDT);
inlinevoidGG(DWORD&A,DWORDB,DWORDC,DWORDD,DWORDX,DWORDS,DWORDT);
inlinevoidHH(DWORD&A,DWORDB,DWORDC,DWORDD,DWORDX,DWORDS,DWORDT);
inlinevoidII(DWORD&A,DWORDB,DWORDC,DWORDD,DWORDX,DWORDS,DWORDT);
voidDWordToByte(BYTE*Output,DWORD*Input,UINTnLength);
voidByteToDWord(DWORD*Output,BYTE*Input,UINTnLength);
BYTE m_lpszBuffer[64]; //inputbuffer
ULONGm_nCount[2]; //numberofbits,modulo2^64(lsbfirst)
ULONGm_lMD5[4]; //MD5checksum
};
3、CountChecksum.cpp(md5校驗和類(lèi)的實(shí)現文件)
/*****************************************************************************************
FUNCTION: CMD5Checksum::GetMD5
DETAILS: static,public
DESCRIPTION: GetstheMD5checksumforaspecifiedfile
RETURNS: CString:thehexadecimalMD5checksumforthespecifiedfile
ARGUMENTS: CString&strFilePath:thefullpathnameofthespecifiedfile
NOTES: ProvidesaninterfacetotheCMD5Checksumclass.'strFilePath'nameshould
holdthefullpathnameofthefile,egC:\MyDocuments\Arcticle.txt.
NB.Ifanyproblemsoccurwithopeningorreadingthisfile,aCFileException
exception.
*****************************************************************************************/
CStringCMD5Checksum::GetMD5(constCString&strFilePath)
{
//openthefileasabinaryfileinreadonlymode,denyingwriteAccess
CFileFile(strFilePath,CFile::shareDenyNone);
//thefilehasbeensuccessfullyopened,sonowgetandreturnitschecksum
returnGetMD5(File);
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::GetMD5
DETAILS: static,public
DESCRIPTION: GetstheMD5checksumforaspecifiedfile
RETURNS: CString:thehexadecimalMD5checksumforthespecifiedfile
ARGUMENTS: CFile&File:thespecifiedfile
NOTES: ProvidesaninterfacetotheCMD5Checksumclass.'File'shouldbeopenin
binaryreadonlymodebeforecallingthisfunction.
NB.CallersofthisfunctionshouldbereadytocatchanyCFileException
thrownbytheCFilefunctions
*****************************************************************************************/
CStringCMD5Checksum::GetMD5(CFile&File)
{
try
{
CMD5ChecksumMD5Checksum; //checksumobject
intnLength=0; //numberofbytesreadfromthefile
constintnBufferSize=1024; //checksumthefileinblocksof1024bytes
BYTEBuffer[nBufferSize]; //bufferfordatareadfromthefile
while((nLength=File.Read(Buffer,nBufferSize))>0)
{
MD5Checksum.Update(Buffer,nLength);
}
returnMD5Checksum.Final();
}
catch(CFileException*e)
{
TRACE0("CMD5Checksum::GetMD5:CFileExceptioncaught");
throwe;
}
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::GetMD5
DETAILS: static,public
DESCRIPTION: GetstheMD5checksumfordatainaBYTEarray
RETURNS: CString:thehexadecimalMD5checksumforthespecifieddata
ARGUMENTS: BYTE*pBuf : pointertotheBYTEarray
UINTnLength: numberofBYTEsofdatatobechecksumed
NOTES: ProvidesaninterfacetotheCMD5Checksumclass.Anydatathatcan
becasttoaBYTEarrayofknownlengthcanbechecksummedbythis
function.Typically,CStringandchararrayswillbechecksumed,
althoughthisfunctioncanbeusedtochecktheintegrityofanyBYTEarray.
Abufferofzerolengthcanbechecksummed;allbuffersofzerolength
willreturnthesamechecksum.
*****************************************************************************************/
CStringCMD5Checksum::GetMD5(BYTE*pBuf,UINTnLength)
{
//entryinvariants
AfxIsValidAddress(pBuf,nLength,FALSE);
CMD5ChecksumMD5Checksum;
MD5Checksum.Update(pBuf,nLength);
returnMD5Checksum.Final();
}
/*****************************************************************************************
DETAILS: private
DESCRIPTION: Rotatesthebitsina32bitDWORDleftbyaspecifiedamount
RETURNS: TherotatedDWORD
ARGUMENTS: DWORDx:thevaluetoberotated
intn :thenumberofbitstorotateby
*****************************************************************************************/
DWORDCMD5Checksum::RotateLeft(DWORDx,intn)
{
//checkthatDWORDis4byteslong-trueinVisualC 6and32bitWindows
ASSERT(sizeof(x)==4);
return(x<<n)|(x>>(32-n));
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::FF
DETAILS: protected
DESCRIPTION: ImplementationofbasicMD5transformationalgorithm
RETURNS: none
ARGUMENTS: DWORD&A,B,C,D:Current(partial)checksum
DWORDX :Inputdata
DWORDS :MD5_SXXTransformationconstant
DWORDT : MD5_TXXTransformationconstant
NOTES: None
*****************************************************************************************/
voidCMD5Checksum::FF(DWORD&A,DWORDB,DWORDC,DWORDD,DWORDX,DWORDS,DWORDT)
{
DWORDF=(B&C)|(~B&D);
A =F X T;
A=RotateLeft(A,S);
A =B;
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::GG
DETAILS: protected
DESCRIPTION: ImplementationofbasicMD5transformationalgorithm
RETURNS: none
ARGUMENTS: DWORD&A,B,C,D:Current(partial)checksum
DWORDX :Inputdata
DWORDS :MD5_SXXTransformationconstant
DWORDT : MD5_TXXTransformationconstant
NOTES: None
*****************************************************************************************/
voidCMD5Checksum::GG(DWORD&A,DWORDB,DWORDC,DWORDD,DWORDX,DWORDS,DWORDT)
{
DWORDG=(B&D)|(C&~D);
A =G X T;
A=RotateLeft(A,S);
A =B;
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::HH
DETAILS: protected
DESCRIPTION: ImplementationofbasicMD5transformationalgorithm
RETURNS: none
ARGUMENTS: DWORD&A,B,C,D:Current(partial)checksum
DWORDX :Inputdata
DWORDS :MD5_SXXTransformationconstant
DWORDT : MD5_TXXTransformationconstant
NOTES: None
*****************************************************************************************/
voidCMD5Checksum::HH(DWORD&A,DWORDB,DWORDC,DWORDD,DWORDX,DWORDS,DWORDT)
{
DWORDH=(B^C^D);
A =H X T;
A=RotateLeft(A,S);
A =B;
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::II
DETAILS: protected
DESCRIPTION: ImplementationofbasicMD5transformationalgorithm
RETURNS: none
ARGUMENTS: DWORD&A,B,C,D:Current(partial)checksum
DWORDX :Inputdata
DWORDS :MD5_SXXTransformationconstant
NOTES: None
*****************************************************************************************/
voidCMD5Checksum::II(DWORD&A,DWORDB,DWORDC,DWORDD,DWORDX,DWORDS,DWORDT)
{
DWORDI=(C^(B|~D));
A =I X T;
A=RotateLeft(A,S);
A =B;
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::ByteToDWord
DETAILS: private
DESCRIPTION: Transfersthedatainan8bitarraytoa32bitarray
RETURNS: void
ARGUMENTS: DWORD*Output:the32bit(unsignedlong)destinationarray
BYTE*Input :the8bit(unsignedchar)sourcearray
UINTnLength :thenumberof8bitdataitemsinthesourcearray
NOTES: FourBYTESfromtheinputarrayaretransferredtoeachDWORDentry
oftheoutputarray.ThefirstBYTEistransferredtothebits(0-7)
oftheoutputDWORD,thesecondBYTEtobits8-15etc.
Thealgorithmassumesthattheinputarrayisamultipleof4byteslong
sothatthereisaperfectfitintothearrayof32bitwords.
*****************************************************************************************/
voidCMD5Checksum::ByteToDWord(DWORD*Output,BYTE*Input,UINTnLength)
{
//entryinvariants
ASSERT(nLength%4==0);
ASSERT(AfxIsValidAddress(Output,nLength/4,TRUE));
ASSERT(AfxIsValidAddress(Input,nLength,FALSE));
UINTi=0; //indextoOutputarray
UINTj=0; //indextoInputarray
for(;j<nLength;i ,j =4)
{
Output[i]=(ULONG)Input[j] |
(ULONG)Input[j 1]<<8 |
(ULONG)Input[j 2]<<16|
(ULONG)Input[j 3]<<24;
}
}
FUNCTION: CMD5Checksum::Transform
DETAILS: protected
DESCRIPTION: MD5basictransformationalgorithm; transforms'm_lMD5'
RETURNS: void
ARGUMENTS: BYTEBlock[64]
NOTES: AnMD5checksumiscalculatedbyfourroundsof'Transformation'.
TheMD5checksumcurrentlyheldinm_lMD5ismergedbythe
transformationprocesswithdatapassedin'Block'.
*****************************************************************************************/
voidCMD5Checksum::Transform(BYTEBlock[64])
{
//initialiselocaldatawithcurrentchecksum
ULONGa=m_lMD5[0];
ULONGb=m_lMD5[1];
ULONGc=m_lMD5[2];
ULONGd=m_lMD5[3];
ULONGX[16];
ByteToDWord(X,Block,64);
FF(a,b,c,d,X[0],MD5_S11,MD5_T01);
FF(d,a,b,c,X[1],MD5_S12,MD5_T02);
FF(c,d,a,b,X[2],MD5_S13,MD5_T03);
FF(b,c,d,a,X[3],MD5_S14,MD5_T04);
FF(a,b,c,d,X[4],MD5_S11,MD5_T05);
FF(d,a,b,c,X[5],MD5_S12,MD5_T06);
FF(c,d,a,b,X[6],MD5_S13,MD5_T07);
FF(b,c,d,a,X[7],MD5_S14,MD5_T08);
FF(a,b,c,d,X[8],MD5_S11,MD5_T09);
FF(d,a,b,c,X[9],MD5_S12,MD5_T10);
FF(c,d,a,b,X[10],MD5_S13,MD5_T11);
FF(b,c,d,a,X[11],MD5_S14,MD5_T12);
FF(d,a,b,c,X[13],MD5_S12,MD5_T14);
FF(c,d,a,b,X[14],MD5_S13,MD5_T15);
FF(b,c,d,a,X[15],MD5_S14,MD5_T16);
GG(a,b,c,d,X[1],MD5_S21,MD5_T17);
GG(d,a,b,c,X[6],MD5_S22,MD5_T18);
GG(c,d,a,b,X[11],MD5_S23,MD5_T19);
GG(b,c,d,a,X[0],MD5_S24,MD5_T20);
GG(a,b,c,d,X[5],MD5_S21,MD5_T21);
GG(d,a,b,c,X[10],MD5_S22,MD5_T22);
GG(c,d,a,b,X[15],MD5_S23,MD5_T23);
GG(b,c,d,a,X[4],MD5_S24,MD5_T24);
GG(a,b,c,d,X[9],MD5_S21,MD5_T25);
GG(d,a,b,c,X[14],MD5_S22,MD5_T26);
GG(c,d,a,b,X[3],MD5_S23,MD5_T27);
GG(b,c,d,a,X[8],MD5_S24,MD5_T28);
GG(a,b,c,d,X[13],MD5_S21,MD5_T29);
GG(d,a,b,c,X[2],MD5_S22,MD5_T30);
GG(c,d,a,b,X[7],MD5_S23,MD5_T31);
GG(b,c,d,a,X[12],MD5_S24,MD5_T32);
HH(a,b,c,d,X[5],MD5_S31,MD5_T33);
HH(d,a,b,c,X[8],MD5_S32,MD5_T34);
HH(c,d,a,b,X[11],MD5_S33,MD5_T35);
HH(b,c,d,a,X[14],MD5_S34,MD5_T36);
HH(a,b,c,d,X[1],MD5_S31,MD5_T37);
HH(d,a,b,c,X[4],MD5_S32,MD5_T38);
HH(c,d,a,b,X[7],MD5_S33,MD5_T39);
HH(b,c,d,a,X[10],MD5_S34,MD5_T40);
HH(a,b,c,d,X[13],MD5_S31,MD5_T41);
HH(d,a,b,c,X[0],MD5_S32,MD5_T42);
HH(c,d,a,b,X[3],MD5_S33,MD5_T43);
HH(b,c,d,a,X[6],MD5_S34,MD5_T44);
HH(a,b,c,d,X[9],MD5_S31,MD5_T45);
HH(d,a,b,c,X[12],MD5_S32,MD5_T46);
HH(c,d,a,b,X[15],MD5_S33,MD5_T47);
HH(b,c,d,a,X[2],MD5_S34,MD5_T48);
II(a,b,c,d,X[0],MD5_S41,MD5_T49);
II(d,a,b,c,X[7],MD5_S42,MD5_T50);
II(c,d,a,b,X[14],MD5_S43,MD5_T51);
II(b,c,d,a,X[5],MD5_S44,MD5_T52);
II(a,b,c,d,X[12],MD5_S41,MD5_T53);
II(d,a,b,c,X[3],MD5_S42,MD5_T54);
II(c,d,a,b,X[10],MD5_S43,MD5_T55);
II(b,c,d,a,X[1],MD5_S44,MD5_T56);
II(a,b,c,d,X[8],MD5_S41,MD5_T57);
II(d,a,b,c,X[15],MD5_S42,MD5_T58);
II(c,d,a,b,X[6],MD5_S43,MD5_T59);
II(b,c,d,a,X[13],MD5_S44,MD5_T60);
II(a,b,c,d,X[4],MD5_S41,MD5_T61);
II(d,a,b,c,X[11],MD5_S42,MD5_T62);
II(c,d,a,b,X[2],MD5_S43,MD5_T63);
II(b,c,d,a,X[9],MD5_S44,MD5_T64);
m_lMD5[0] =a;
m_lMD5[1] =b;
m_lMD5[2] =c;
m_lMD5[3] =d;
}
/*****************************************************************************************
CONSTRUCTOR: CMD5Checksum
DESCRIPTION: Initialisesmemberdata
ARGUMENTS: None
NOTES: None
*****************************************************************************************/
CMD5Checksum::CMD5Checksum()
{
//zeromembers
memset(m_lpszBuffer,0,64);
m_nCount[0]=m_nCount[1]=0;
m_lMD5[0]=MD5_INIT_STATE_0;
m_lMD5[1]=MD5_INIT_STATE_1;
m_lMD5[2]=MD5_INIT_STATE_2;
m_lMD5[3]=MD5_INIT_STATE_3;
}
FUNCTION: CMD5Checksum::DWordToByte
DETAILS: private
RETURNS: void
ARGUMENTS: BYTE*Output :the8bitdestinationarray
DWORD*Input :the32bitsourcearray
UINTnLength :thenumberof8bitdataitemsinthesourcearray
NOTES: OneDWORDfromtheinputarrayistransferredintofourBYTES
intheoutputarray.Thefirst(0-7)bitsofthefirstDWORDare
transferredtothefirstoutputBYTE,bitsbits8-15aretransferredfrom
thesecondBYTEetc.
Thealgorithmassumesthattheoutputarrayisamultipleof4byteslong
sothatthereisaperfectfitof8bitBYTESintothe32bitDWORDs.
*****************************************************************************************/
voidCMD5Checksum::DWordToByte(BYTE*Output,DWORD*Input,UINTnLength)
{
//entryinvariants
ASSERT(nLength%4==0);
ASSERT(AfxIsValidAddress(Output,nLength,TRUE));
ASSERT(AfxIsValidAddress(Input,nLength/4,FALSE));
UINTi=0;
UINTj=0;
for(;j<nLength;i ,j =4)
{
Output[j]= (UCHAR)(Input[i]&0xff);
Output[j 1]=(UCHAR)((Input[i]>>8)&0xff);
Output[j 2]=(UCHAR)((Input[i]>>16)&0xff);
Output[j 3]=(UCHAR)((Input[i]>>24)&0xff);
}
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::Final
DETAILS: protected
DESCRIPTION: ImplementationofmainMD5checksumalgorithm;endsthechecksumcalculation.
RETURNS: CString:thefinalhexadecimalMD5checksumresult
ARGUMENTS: None
NOTES: PerformsthefinalMD5checksumcalculation('Update'doesmostofthework,
thisfunctionjustfinishesthecalculation.)
*****************************************************************************************/
CStringCMD5Checksum::Final()
{
//Savenumberofbits
BYTEBits[8];
DWordToByte(Bits,m_nCount,8);
UINTnIndex=(UINT)((m_nCount[0]>>3)&0x3f);
UINTnPadLen=(nIndex<56)?(56-nIndex):(120-nIndex);
Update(PADDING,nPadLen);
Update(Bits,8);
constintnMD5Size=16;
unsignedcharlpszMD5[nMD5Size];
DWordToByte(lpszMD5,m_lMD5,nMD5Size);
CStringstrMD5;
for(inti=0;i<nMD5Size;i )
{
CStringStr;
if(lpszMD5[i]==0){
Str=CString("00");
}
elseif(lpszMD5[i]<=15) {
Str.Format("0%x",lpszMD5[i]);
}
else{
Str.Format("%x",lpszMD5[i]);
}
strMD5 =Str;
}
ASSERT(strMD5.GetLength()==32);
returnstrMD5;
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::Update
DETAILS: protected
DESCRIPTION: ImplementationofmainMD5checksumalgorithm
RETURNS: void
ARGUMENTS: BYTE*Input :inputblock
UINTnInputLen:lengthofinputblock
*****************************************************************************************/
voidCMD5Checksum::Update(BYTE*Input, ULONGnInputLen)
{
//Computenumberofbytesmod64
UINTnIndex=(UINT)((m_nCount[0]>>3)&0x3F);
if((m_nCount[0] =nInputLen<<3) < (nInputLen<<3))
{
m_nCount[1] ;
}
m_nCount[1] =(nInputLen>>29);
UINTi=0;
UINTnPartLen=64-nIndex;
if(nInputLen>=nPartLen)
{
memcpy(&m_lpszBuffer[nIndex],Input,nPartLen);
Transform(m_lpszBuffer);
for(i=nPartLen;i 63<nInputLen;i =64)
{
Transform(&Input[i]);
}
nIndex=0;
}
else
{
i=0;
}
memcpy(&m_lpszBuffer[nIndex],&Input[i],nInputLen-i);
}
聯(lián)系客服