使用md5校验和算法保护文件

【密码算法 之八】Hash类算法(单向散列函数) MD5 \ SHA1 \ SHA224 \ SHA256 \ SHA384 \ SHA512等浅析 MD5与SHA-1算法已被攻破,不应该再用于新的用途;SHA-2与SHA-3还是安全的,可以使用。SHA-2包括:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。SHA-3包括:SHA3-224、SHA3-256、SHA3-384、SHA3-512。算法分组长度(bytes)输出长度(hash value)(bytes)是否安全SM36432安全MD46416不安全MD56416不安全SHA164。 阅读详情
近日要用到文件校验算法,查看了一下相关资料,得到以下理论与实践经验。
一、理论部分:
1、预备知识
1.1什么是数据校验
通俗的说,就是为保证数据的完整性,用一种指定的算法对原始数据计算出的一个校验值。接收方用同样的算法计算一次校验值,如果和随数据提供的校验值一样,就说明数据是完整的。
1.2最简单的检验
实现方法:最简单的校验就是把原始数据和待比较数据直接进行比较,看是否完全一样这种方法是最安全最准确的。同时也是效率最低的。
适用范围:简单的数据量极小的通讯。
应用例子:龙珠cpu在线调试工具bbug.exe。它和龙珠cpu间通讯时,bbug发送一个字节cpu返回收到的字节,bbug确认是刚才发送字节后才继续发送下一个字节的。
1.3奇偶校验Parity Check
实现方法:在数据存储和传输中,字节中额外增加一个比特位,用来检验错误。校验位可以通过数据位异或计算出来。
应用例子:单片机串口通讯有一模式就是8位数据通讯,另加第9位用于放校验值。
1.4 bcc异或校验法(block check character)
实现方法:很多基于串口的通讯都用这种既简单又相当准确的方法。它就是把所有数据都和一个指定的初始值(通常是0)异或一次,最后的结果就是校验值,通常
把她附在通讯数据的最后一起发送出去。接收方收到数据后自己也计算一次异或和校验值,如果和收到的校验值一致就说明收到的数据是完整的。
校验值计算的代码类似于:
unsigned uCRC=0;//校验初始值
for(int i=0;i<DataLenth;i++) uCRC^=Data[i];
适用范围:适用于大多数要求不高的数据通讯。
应用例子:ic卡接口通讯、很多单片机系统的串口通讯都使用。
1.5 crc循环冗余校验(Cyclic Redundancy Check)
实现方法:这是利用除法及余数的原理来进行错误检测的.将接收到的码组进行除法运算
,如果除尽,则说明传输无误;如果未除尽,则表明传输出现差错。crc校验
具还有自动纠错能力。
crc检验主要有计算法和查表法两种方法,网上很多实现代码。
适用范围:CRC-12码通常用来传送6-bit字符串;CRC-16及CRC-CCITT码则用是来传送
8-bit字符。CRC-32:硬盘数据,网络传输等
应用例子:rar,以太网卡芯片、MPEG解码芯片中
1.6 md5校验和数字签名
实现方法:主要有md5和des算法。
适用范围:数据比较大或要求比较高的场合。如md5用于大量数据、文件校验,des用于保密数据的校验(数字签名)等等。
应用例子:文件校验、银行系统的交易数据

2、具体的实现理论
2.1 算法概述
MD5算法是MD4算法的改进算法。Ron Rivest 于1990年提出MD4单向散列函数,MD表示消息摘要(Message Digest),对输入消息,算法产生128位散列值。该算法首次公布之后,Bert den Boer和Antoon Bosselaers 对算法三轮中的后两轮进行了成功的密码分析。在一个不相关的分析结果中,Ralph MerKle成功地攻击了前两轮。尽管这些攻击都没有扩展到整个算法,但Rivest还是改进了其算法,结果就是MD5算法。
 MD5算法是MD4的改进算法,它比MD4更复杂,但设计思想相似,输入的消息可任意长,输出结果也仍为128位,特别适用于高速软件实现,是基于32-位操作数的一些简单的位操作。
2.2 算法步骤
l 将输入消息按512-位分组,最后要填充成为512位的整数倍,且最后一组的后64位用来填充消息长度(填充前)。填充方法为附一个1在消息后,后接所要求的多个0。这样可以确保不同消息在填充后不相同。
l 由于留出64位用来表示消息长度,那么消息的长度最多可达264字节,相当于4G×4G字节,文件的长度是不可能达到这么大,因此通常都是只采用64位中的低32位来表示消息长度,高32位填充0。
l 初始化MD变量。由于每轮输出128位,这128位可用下面四个32位字A,B,C,D来表示。其初始值设为:
A=0x01234567
B=0x89ABCDEF
C=0xFEDCBA98
D=0x76543210
l 开始进入算法主循环,循环的次数是消息中512位消息分组的数目。先将上面A、B、C、D四个变量分别复制到另外四个变量a、b、c、d中去。主循环有四轮,每轮很相似。每轮进行16次操作,每次操作对a、b、c、d四个变量中的三个作一次非线性函数运算,然后将所得结果加上第四个变量,消息的一个子分组和一个常数。再将所得结果向右环移一个不定的数,并加上a,b,c或d中之一。最后用该结果取代a,b,c或d中之一。
以下是每次操作中用到的四个非线性函数(每轮一个)。
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个子分组(从0到15),<<<s表示循环左移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的级联。
l 最后得到的A,B,C,D就是输出结果,A是低位,D为高位,DCBA组成128位输出结果。
2.3 MD5的安全性
Ron Rivest概述了MD5安全性[8]:
l 与MD4相比,增加了第四轮。
l 每一步均有唯一的加法常数。
l 为减弱第二轮中函数G的对称性从((X∧Y) ∨(X∧Z) ∨(Y∧Z))变为((X∧Z) ∨(Y∧( Z)))。
l 每一步加上了上一步的结果,引起更快的雪崩效应。
l 改变了第二轮和第三轮中访问消息子分组的次序,使其形式更不相似。
l 近似优化了每一轮中的循环左移位移量以实现更快的雪崩效应。各轮的位移量互不相同。
从安全角度讲,MD5的输出为128位,若采用纯强力攻击寻找一个消息具有给定Hash值的计算困难性为2128,用每秒可试验1 000 000 000个消息的计算机需时1.07×1022年。若采用生日攻击法,寻找有相同Hash值的两个消息需要试验264个消息,用每秒可试验1 000 000 000个消息的计算机需时585年。

二、实现方法
 由于此处的文件校验用到要求比较高的场合,故采用了方法6,md5校验算法,从CodeGuru下载了一个md5校验算法的实现模块,加入自己要校验的文件名,实现完成。下面具体描述一下实现过程:
1、创建一个简单的对话框程序;
2、设置CString类型的变量m_filename和m_strFileChecksum以存放要校验的文件名和校验和;
3、在对话框类中创建ChecksumSelectedFile()函数,调用md5校验和类(附录中有其实现文件)中的GetMD5计算文件校验和。
4、使用定时器定时巡检该文件的校验和,一旦发现校验和发生变化,立刻出现提示。
三、附录(md5算法实现的源码)
以下代码实现均来自www.codeguru.com。
1、MD5ChecksumDefines.h(定义相关常量的头文件)
//Magic initialization constants
#define MD5_INIT_STATE_0 0x67452301
#define MD5_INIT_STATE_1 0xefcdab89
#define MD5_INIT_STATE_2 0x98badcfe
#define MD5_INIT_STATE_3 0x10325476

//Constants for Transform routine.
#define MD5_S11  7
#define MD5_S12 12
#define MD5_S13 17
#define MD5_S14 22
#define MD5_S21  5
#define MD5_S22  9
#define MD5_S23 14
#define MD5_S24 20
#define MD5_S31  4
#define MD5_S32 11
#define MD5_S33 16
#define MD5_S34 23
#define MD5_S41  6
#define MD5_S42 10
#define MD5_S43 15
#define MD5_S44 21

//Transformation Constants - Round 1
#define MD5_T01  0xd76aa478 //Transformation Constant 1
#define MD5_T02  0xe8c7b756 //Transformation Constant 2
#define MD5_T03  0x242070db //Transformation Constant 3
#define MD5_T04  0xc1bdceee //Transformation Constant 4
#define MD5_T05  0xf57c0faf //Transformation Constant 5
#define MD5_T06  0x4787c62a //Transformation Constant 6
#define MD5_T07  0xa8304613 //Transformation Constant 7
#define MD5_T08  0xfd469501 //Transformation Constant 8
#define MD5_T09  0x698098d8 //Transformation Constant 9
#define MD5_T10  0x8b44f7af //Transformation Constant 10
#define MD5_T11  0xffff5bb1 //Transformation Constant 11
#define MD5_T12  0x895cd7be //Transformation Constant 12
#define MD5_T13  0x6b901122 //Transformation Constant 13
#define MD5_T14  0xfd987193 //Transformation Constant 14
#define MD5_T15  0xa679438e //Transformation Constant 15
#define MD5_T16  0x49b40821 //Transformation Constant 16

//Transformation Constants - Round 2
#define MD5_T17  0xf61e2562 //Transformation Constant 17
#define MD5_T18  0xc040b340 //Transformation Constant 18
#define MD5_T19  0x265e5a51 //Transformation Constant 19
#define MD5_T20  0xe9b6c7aa //Transformation Constant 20
#define MD5_T21  0xd62f105d //Transformation Constant 21
#define MD5_T22  0x02441453 //Transformation Constant 22
#define MD5_T23  0xd8a1e681 //Transformation Constant 23
#define MD5_T24  0xe7d3fbc8 //Transformation Constant 24
#define MD5_T25  0x21e1cde6 //Transformation Constant 25
#define MD5_T26  0xc33707d6 //Transformation Constant 26
#define MD5_T27  0xf4d50d87 //Transformation Constant 27
#define MD5_T28  0x455a14ed //Transformation Constant 28
#define MD5_T29  0xa9e3e905 //Transformation Constant 29
#define MD5_T30  0xfcefa3f8 //Transformation Constant 30
#define MD5_T31  0x676f02d9 //Transformation Constant 31
#define MD5_T32  0x8d2a4c8a //Transformation Constant 32

//Transformation Constants - Round 3
#define MD5_T33  0xfffa3942 //Transformation Constant 33
#define MD5_T34  0x8771f681 //Transformation Constant 34
#define MD5_T35  0x6d9d6122 //Transformation Constant 35
#define MD5_T36  0xfde5380c //Transformation Constant 36
#define MD5_T37  0xa4beea44 //Transformation Constant 37
#define MD5_T38  0x4bdecfa9 //Transformation Constant 38
#define MD5_T39  0xf6bb4b60 //Transformation Constant 39
#define MD5_T40  0xbebfbc70 //Transformation Constant 40
#define MD5_T41  0x289b7ec6 //Transformation Constant 41
#define MD5_T42  0xeaa127fa //Transformation Constant 42
#define MD5_T43  0xd4ef3085 //Transformation Constant 43
#define MD5_T44  0x04881d05 //Transformation Constant 44
#define MD5_T45  0xd9d4d039 //Transformation Constant 45
#define MD5_T46  0xe6db99e5 //Transformation Constant 46
#define MD5_T47  0x1fa27cf8 //Transformation Constant 47
#define MD5_T48  0xc4ac5665 //Transformation Constant 48

//Transformation Constants - Round 4
#define MD5_T49  0xf4292244 //Transformation Constant 49
#define MD5_T50  0x432aff97 //Transformation Constant 50
#define MD5_T51  0xab9423a7 //Transformation Constant 51
#define MD5_T52  0xfc93a039 //Transformation Constant 52
#define MD5_T53  0x655b59c3 //Transformation Constant 53
#define MD5_T54  0x8f0ccc92 //Transformation Constant 54
#define MD5_T55  0xffeff47d //Transformation Constant 55
#define MD5_T56  0x85845dd1 //Transformation Constant 56
#define MD5_T57  0x6fa87e4f //Transformation Constant 57
#define MD5_T58  0xfe2ce6e0 //Transformation Constant 58
#define MD5_T59  0xa3014314 //Transformation Constant 59
#define MD5_T60  0x4e0811a1 //Transformation Constant 60
#define MD5_T61  0xf7537e82 //Transformation Constant 61
#define MD5_T62  0xbd3af235 //Transformation Constant 62
#define MD5_T63  0x2ad7d2bb //Transformation Constant 63
#define MD5_T64  0xeb86d391 //Transformation Constant 64


//Null data (except for first BYTE) used to finalise the checksum calculation
static unsigned char PADDING[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校验和类的头文件)
class CMD5Checksum 
{
public:
 //interface functions for the RSA MD5 calculation
 static CString GetMD5(BYTE* pBuf, UINT nLength);
 static CString GetMD5(CFile& File);
 static CString GetMD5(const CString& strFilePath);

protected:
 //constructor/destructor
 CMD5Checksum();
 virtual ~CMD5Checksum() {};

 //RSA MD5 implementation
 void Transform(BYTE Block[64]);
 void Update(BYTE* Input, ULONG nInputLen);
 CString Final();
 inline DWORD RotateLeft(DWORD x, int n);
 inline void FF( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T);
 inline void GG( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T);
 inline void HH( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T);
 inline void II( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T);

 //utility functions
 void DWordToByte(BYTE* Output, DWORD* Input, UINT nLength);
 void ByteToDWord(DWORD* Output, BYTE* Input, UINT nLength);

private:
 BYTE  m_lpszBuffer[64];  //input buffer
 ULONG m_nCount[2];   //number of bits, modulo 2^64 (lsb first)
 ULONG m_lMD5[4];   //MD5 checksum
};

#endif // !defined(AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_)
3、CountChecksum.cpp (md5校验和类的实现文件)
/*****************************************************************************************
FUNCTION:  CMD5Checksum::GetMD5
DETAILS:  static, public
DESCRIPTION: Gets the MD5 checksum for a specified file
RETURNS:  CString : the hexadecimal MD5 checksum for the specified file
ARGUMENTS:  CString& strFilePath : the full pathname of the specified file
NOTES:   Provides an interface to the CMD5Checksum class. 'strFilePath' name should
    hold the full pathname of the file, eg C:/My Documents/Arcticle.txt.
    NB. If any problems occur with opening or reading this file, a CFileException
    will be thrown; callers of this function should be ready to catch this
    exception.
*****************************************************************************************/
CString CMD5Checksum::GetMD5(const CString& strFilePath)
{
 //open the file as a binary file in readonly mode, denying write access
 CFile File(strFilePath, CFile::shareDenyNone);
 //the file has been successfully opened, so now get and return its checksum
 return GetMD5(File);
}


/*****************************************************************************************
FUNCTION:  CMD5Checksum::GetMD5
DETAILS:  static, public
DESCRIPTION: Gets the MD5 checksum for a specified file
RETURNS:  CString : the hexadecimal MD5 checksum for the specified file
ARGUMENTS:  CFile& File : the specified file
NOTES:   Provides an interface to the CMD5Checksum class. 'File' should be open in
    binary readonly mode before calling this function.
    NB. Callers of this function should be ready to catch any CFileException
    thrown by the CFile functions
*****************************************************************************************/
CString CMD5Checksum::GetMD5(CFile& File)
{
 try
 {
  CMD5Checksum MD5Checksum;  //checksum object 
  int nLength = 0;    //number of bytes read from the file
  const int nBufferSize = 1024; //checksum the file in blocks of 1024 bytes
  BYTE Buffer[nBufferSize];  //buffer for data read from the file

  //checksum the file in blocks of 1024 bytes
  while ((nLength = File.Read( Buffer, nBufferSize )) > 0 )
  {
   MD5Checksum.Update( Buffer, nLength );
  }

  //finalise the checksum and return it
  return MD5Checksum.Final();
 }

 //report any file exceptions in debug mode only
 catch (CFileException* e )
 {
  TRACE0("CMD5Checksum::GetMD5: CFileException caught"); 
  throw e;
 }
}


/*****************************************************************************************
FUNCTION:  CMD5Checksum::GetMD5
DETAILS:  static, public
DESCRIPTION: Gets the MD5 checksum for data in a BYTE array
RETURNS:  CString : the hexadecimal MD5 checksum for the specified data
ARGUMENTS:  BYTE* pBuf  : pointer to the BYTE array
    UINT nLength : number of BYTEs of data to be checksumed
NOTES:   Provides an interface to the CMD5Checksum class. Any data that can
    be cast to a BYTE array of known length can be checksummed by this
    function. Typically, CString and char arrays will be checksumed,
    although this function can be used to check the integrity of any BYTE array.
    A buffer of zero length can be checksummed; all buffers of zero length
    will return the same checksum.
*****************************************************************************************/
CString CMD5Checksum::GetMD5(BYTE* pBuf, UINT nLength)
{
 //entry invariants
 AfxIsValidAddress(pBuf,nLength,FALSE);

 //calculate and return the checksum
 CMD5Checksum MD5Checksum;
 MD5Checksum.Update( pBuf, nLength );
 return MD5Checksum.Final();
}


/*****************************************************************************************
FUNCTION:  CMD5Checksum::RotateLeft
DETAILS:  private
DESCRIPTION: Rotates the bits in a 32 bit DWORD left by a specified amount
RETURNS:  The rotated DWORD
ARGUMENTS:  DWORD x : the value to be rotated
    int n   : the number of bits to rotate by
*****************************************************************************************/
DWORD CMD5Checksum::RotateLeft(DWORD x, int n)
{
 //check that DWORD is 4 bytes long - true in Visual C++ 6 and 32 bit Windows
 ASSERT( sizeof(x) == 4 );

 //rotate and return x
 return (x << n) | (x >> (32-n));
}


/*****************************************************************************************
FUNCTION:  CMD5Checksum::FF
DETAILS:  protected
DESCRIPTION: Implementation of basic MD5 transformation algorithm
RETURNS:  none
ARGUMENTS:  DWORD &A, B, C, D : Current (partial) checksum
    DWORD X           : Input data
    DWORD S     : MD5_SXX Transformation constant
    DWORD T     : MD5_TXX Transformation constant
NOTES:   None
*****************************************************************************************/
void CMD5Checksum::FF( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
{
 DWORD F = (B & C) | (~B & D);
 A += F + X + T;
 A = RotateLeft(A, S);
 A += B;
}


/*****************************************************************************************
FUNCTION:  CMD5Checksum::GG
DETAILS:  protected
DESCRIPTION: Implementation of basic MD5 transformation algorithm
RETURNS:  none
ARGUMENTS:  DWORD &A, B, C, D : Current (partial) checksum
    DWORD X           : Input data
    DWORD S     : MD5_SXX Transformation constant
    DWORD T     : MD5_TXX Transformation constant
NOTES:   None
*****************************************************************************************/
void CMD5Checksum::GG( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
{
 DWORD G = (B & D) | (C & ~D);
 A += G + X + T;
 A = RotateLeft(A, S);
 A += B;
}


/*****************************************************************************************
FUNCTION:  CMD5Checksum::HH
DETAILS:  protected
DESCRIPTION: Implementation of basic MD5 transformation algorithm
RETURNS:  none
ARGUMENTS:  DWORD &A, B, C, D : Current (partial) checksum
    DWORD X           : Input data
    DWORD S     : MD5_SXX Transformation constant
    DWORD T     : MD5_TXX Transformation constant
NOTES:   None
*****************************************************************************************/
void CMD5Checksum::HH( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
{
 DWORD H = (B ^ C ^ D);
 A += H + X + T;
 A = RotateLeft(A, S);
 A += B;
}


/*****************************************************************************************
FUNCTION:  CMD5Checksum::II
DETAILS:  protected
DESCRIPTION: Implementation of basic MD5 transformation algorithm
RETURNS:  none
ARGUMENTS:  DWORD &A, B, C, D : Current (partial) checksum
    DWORD X           : Input data
    DWORD S     : MD5_SXX Transformation constant
    DWORD T     : MD5_TXX Transformation constant
NOTES:   None
*****************************************************************************************/
void CMD5Checksum::II( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
{
 DWORD I = (C ^ (B | ~D));
 A += I + X + T;
 A = RotateLeft(A, S);
 A += B;
}


/*****************************************************************************************
FUNCTION:  CMD5Checksum::ByteToDWord
DETAILS:  private
DESCRIPTION: Transfers the data in an 8 bit array to a 32 bit array
RETURNS:  void
ARGUMENTS:  DWORD* Output : the 32 bit (unsigned long) destination array
    BYTE* Input   : the 8 bit (unsigned char) source array
    UINT nLength  : the number of 8 bit data items in the source array
NOTES:   Four BYTES from the input array are transferred to each DWORD entry
    of the output array. The first BYTE is transferred to the bits (0-7)
    of the output DWORD, the second BYTE to bits 8-15 etc.
    The algorithm assumes that the input array is a multiple of 4 bytes long
    so that there is a perfect fit into the array of 32 bit words.
*****************************************************************************************/
void CMD5Checksum::ByteToDWord(DWORD* Output, BYTE* Input, UINT nLength)
{
 //entry invariants
 ASSERT( nLength % 4 == 0 );
 ASSERT( AfxIsValidAddress(Output, nLength/4, TRUE) );
 ASSERT( AfxIsValidAddress(Input, nLength, FALSE) );

 //initialisations
 UINT i=0; //index to Output array
 UINT j=0; //index to Input array

 //transfer the data by shifting and copying
 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: MD5 basic transformation algorithm;  transforms 'm_lMD5'
RETURNS:  void
ARGUMENTS:  BYTE Block[64]
NOTES:   An MD5 checksum is calculated by four rounds of 'Transformation'.
    The MD5 checksum currently held in m_lMD5 is merged by the
    transformation process with data passed in 'Block'. 
*****************************************************************************************/
void CMD5Checksum::Transform(BYTE Block[64])
{
 //initialise local data with current checksum
 ULONG a = m_lMD5[0];
 ULONG b = m_lMD5[1];
 ULONG c = m_lMD5[2];
 ULONG d = m_lMD5[3];

 //copy BYTES from input 'Block' to an array of ULONGS 'X'
 ULONG X[16];
 ByteToDWord( X, Block, 64 );

 //Perform Round 1 of the transformation
 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 (a, b, c, d, X[12], MD5_S11, MD5_T13);
 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);

 //Perform Round 2 of the transformation
 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);

 //Perform Round 3 of the transformation
 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);

 //Perform Round 4 of the transformation
 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);

 //add the transformed values to the current checksum
 m_lMD5[0] += a;
 m_lMD5[1] += b;
 m_lMD5[2] += c;
 m_lMD5[3] += d;
}


/*****************************************************************************************
CONSTRUCTOR: CMD5Checksum
DESCRIPTION: Initialises member data
ARGUMENTS:  None
NOTES:   None
*****************************************************************************************/
CMD5Checksum::CMD5Checksum()
{
 // zero members
 memset( m_lpszBuffer, 0, 64 );
 m_nCount[0] = m_nCount[1] = 0;

 // Load magic state initialization constants
 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
DESCRIPTION: Transfers the data in an 32 bit array to a 8 bit array
RETURNS:  void
ARGUMENTS:  BYTE* Output  : the 8 bit destination array
    DWORD* Input  : the 32 bit source array
    UINT nLength  : the number of 8 bit data items in the source array
NOTES:   One DWORD from the input array is transferred into four BYTES
    in the output array. The first (0-7) bits of the first DWORD are
    transferred to the first output BYTE, bits bits 8-15 are transferred from
    the second BYTE etc.
    
    The algorithm assumes that the output array is a multiple of 4 bytes long
    so that there is a perfect fit of 8 bit BYTES into the 32 bit DWORDs.
*****************************************************************************************/
void CMD5Checksum::DWordToByte(BYTE* Output, DWORD* Input, UINT nLength )
{
 //entry invariants
 ASSERT( nLength % 4 == 0 );
 ASSERT( AfxIsValidAddress(Output, nLength, TRUE) );
 ASSERT( AfxIsValidAddress(Input, nLength/4, FALSE) );

 //transfer the data by shifting and copying
 UINT i = 0;
 UINT j = 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: Implementation of main MD5 checksum algorithm; ends the checksum calculation.
RETURNS:  CString : the final hexadecimal MD5 checksum result
ARGUMENTS:  None
NOTES:   Performs the final MD5 checksum calculation ('Update' does most of the work,
    this function just finishes the calculation.)
*****************************************************************************************/
CString CMD5Checksum::Final()
{
 //Save number of bits
 BYTE Bits[8];
 DWordToByte( Bits, m_nCount, 8 );

 //Pad out to 56 mod 64.
 UINT nIndex = (UINT)((m_nCount[0] >> 3) & 0x3f);
 UINT nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex);
 Update( PADDING, nPadLen );

 //Append length (before padding)
 Update( Bits, 8 );

 //Store final state in 'lpszMD5'
 const int nMD5Size = 16;
 unsigned char lpszMD5[ nMD5Size ];
 DWordToByte( lpszMD5, m_lMD5, nMD5Size );

 //Convert the hexadecimal checksum to a CString
 CString strMD5;
 for ( int i=0; i < nMD5Size; i++)
 {
  CString Str;
  if (lpszMD5[i] == 0) {
   Str = CString("00");
  }
  else if (lpszMD5[i] <= 15)  {
   Str.Format("0%x",lpszMD5[i]);
  }
  else {
   Str.Format("%x",lpszMD5[i]);
  }

  ASSERT( Str.GetLength() == 2 );
  strMD5 += Str;
 }
 ASSERT( strMD5.GetLength() == 32 );
 return strMD5;
}


/*****************************************************************************************
FUNCTION:  CMD5Checksum::Update
DETAILS:  protected
DESCRIPTION: Implementation of main MD5 checksum algorithm
RETURNS:  void
ARGUMENTS:  BYTE* Input    : input block
    UINT nInputLen : length of input block
NOTES:   Computes the partial MD5 checksum for 'nInputLen' bytes of data in 'Input'
*****************************************************************************************/
void CMD5Checksum::Update( BYTE* Input, ULONG nInputLen )
{
 //Compute number of bytes mod 64
 UINT nIndex = (UINT)((m_nCount[0] >> 3) & 0x3F);

 //Update number of bits
 if ( ( m_nCount[0] += nInputLen << 3 )  <  ( nInputLen << 3) )
 {
  m_nCount[1]++;
 }
 m_nCount[1] += (nInputLen >> 29);

 //Transform as many times as possible.
 UINT i=0;  
 UINT nPartLen = 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;
 }

 // Buffer remaining input
 memcpy( &m_lpszBuffer[nIndex], &Input[i], nInputLen-i);
}



文件完整性校验之MD5校验 MD5校验是一种有效的保护文件完整性的方式,它能够快速计算出文件的散列值,并与原始散列值进行比较,从而检查文件是否被篡改或损坏。使用Python编写的MD5校验器,可以让您轻松地验证文件的完整性,提高文件安全性。在主程序中,我们将一个文件路径和该文件的原始MD5散列值作为输入参数传递给calculate_md5函数,并使用if语句检查计算出的散列值是否与原始MD5散列值相同。如果相同,则该文件的完整性得到了验证。要使用MD5校验文件,您需要使用一个MD5校验器工具,该工具将读取您的文件并计算它的散列值。 阅读详情

相关推荐

蓝天p950ep6 ,神州精盾t96e 解锁版BIos ,蓝天p950ep6 黑苹果bios,神州精盾t96e 黑苹果bios。

蓝天p950ep6 ,神州精盾t96e 解锁版BIos ,蓝天p950ep6 黑苹果bios,神州精盾t96e 黑苹果bios。 已解锁功耗墙 电压 cfg等。

VC++ MD5检验

头文件申明(CMD5Checksum.h): #ifndef MD5_CHECK_SUM_HEAD #define MD5_CHECK_SUM_HEAD #pragma once //初始常量 #define MD5_INIT_STATE_0 0x67452301 #define MD5_INIT_STATE_1 0xefcdab89 #define MD5_INIT_STATE_2 0x9...

老狼的专栏 1002

TLV320AIC3204音频CODEC硬件设计与调试实战

本文深入解析了TLV320AIC3204音频CODEC的硬件设计与调试实战。文章从芯片功能定位入手,详细阐述了电源时钟设计、模拟输入电路等关键硬件设计要点,并提供了软件驱动配置与分层调试方法,帮助工程师有效规避常见陷阱,解决底噪、失真等典型音频调试问题。

zero1的博客 1122

在文件分割器中加入md5校验

     我最近终于用vc开发出了自己的第一个作品—文件分割器,核心代码完全是自己完成的,还请各位网友赐教,但是网上关于这样的文章不少,所以我就在我的作品中加入了大名鼎鼎的md5数据校验,在这篇文章中,我不想讲述文件是怎么分割的,而是想说说如何加入md5算法。    为什么我要在文件分割器中加入md5算法呢?目的就是为了要保证被分割后的文件再合并完成之后还是原原本本的原文件,也就是说,如果我们利用

bxcs_2008的专栏 1540

从STM32F411到华大HC32F460:一个真实项目移植的踩坑与填坑全记录

本文详细记录了从STM32F411移植到华大HC32F460芯片的全过程,包括开发环境搭建、时钟树配置、中断处理、外设驱动、看门狗陷阱、Flash操作和低功耗设计等关键坑点及解决方案。特别针对HC32F460的200MHz主频、双PLL架构和HSRUN模式等特性进行了深入分析,为工程师提供实用的移植指南,帮助节省大量调试时间。

weixin_33691817的博客 418

深入解析车载以太网DoIP诊断:Wireshark实战TCP/UDS报文分析

本文深入解析车载以太网DoIP诊断,重点介绍如何利用Wireshark进行TCP/UDS报文实战分析。文章详细讲解了从以太网帧、IP帧、TCP段到DoIP协议及UDS服务的逐层拆解方法,并提供了使用Wireshark定位通信故障(如乱序、丢包、重传)的实用技巧,帮助工程师高效排查车载诊断网络问题。

c2d3e4f的博客 674

使用md5校验和算法保护文件(转载)

     近日要用到文件校验算法,查看了一下相关资料,得到以下理论与实践经验。一、理论部分:1、预备知识1.1什么是数据校验通俗的说,就是为保证数据的完整性,用一种指定的算法对原始数据计算出的一个校验值。接收方用同样的算法计算一次校验值,如果和随数据提供的校验值一样,就说明数据是完整的。1.2最简单的检验实现方法:最简单的校验就是把原始数据和待比较数据直接进行比较,看是否完全一样这种方法是最安全最

916

unity游戏开发日志(一)将mmd模型导入unity,并解决材质丢失的问题

unity音乐游戏开发,导入角色模型并解决材质问题

yizhigou1的博客 1762

使用md5校验和算法保护文件(算法/原理/程序)

近日要用到文件校验算法,查看了一下相关资料,得到以下理论与实践经验。 一、理论部分: 1、预备知识 1.1什么是数据校验 通俗的说,就是为保证数据的完整性,用一种指定的算法对原始数据计算出的一个校验值。接收方用同样的算法计算一次校验值,如果和随数据提供的校验值一样,就说明数据是完整的。 1.2最简单的检验 实现方法:最简单的校验就是把原始数据和待比较数据直接进行

http://www.softwareace.cn 王牌软件 789

5、高级综合技术:从调度到优化的全面解析

本文深入解析了高级综合技术,涵盖从控制/数据流图构建、调度算法、分配绑定策略到编译器优化的全流程。通过案例分析和对比,探讨了不同优化策略对性能和资源利用的影响,并总结了关键要点及未来发展趋势,为高效利用FPGA实现数字设计提供了全面指导。

night的博客 117

【100%通过率】2024华为OD机试真题E卷 C++语言 实现【流浪地球】

流浪地球计划在赤道上均匀部署了N个转向发动机,按位置顺序编号为0~N-1。 1) 初始状态下所有的发动机都是未启动状态; 2) 发动机起动的方式分为“手动启动”和“关联启动”两种方式; 3) 如果在时刻1一个发动机被启动,下一个时刻2与之相邻的两个发动机就会被“关联启动”; 4) 如果准备启动某个发动机时,它已经被启动了,则什么都不用做; 5) 发动机0与发动机N-1是相邻; 地球联合政府准备挑选某些发动机在某些时刻进行“手动启动”,当然最终所有的发动机都会被启动。 哪些发动机最晚被启动呢?

MISAYAONE的博客 4210

简述MD5信息摘要算法

在之前的文章中,我们聊了不少的加密算法,今天我们聊一种被广泛使用的密码散列函数——MD5。

jiamisoft的博客 1584

UNet 改进(22):结合Transformer结构

保留了UNet的经典编码器-解码器结构在瓶颈层使用Transformer替代传统的卷积层采用跳跃连接保持空间细节信息使用双卷积块(DoubleConv)作为基础构建模块。

2401_82355416的博客 774

web-MD5加密

MD5概述 MD5是一种加密算法。可以用于数据加密、文件快传、文件校验 、数据压缩等方面。 MD5还被称之为数据摘要算法,或数据指纹算法。 a. 特点: i. 经过加密后的数据,是不可破译的,无法得到原有的明文内容。 ii. 经过加密的数据,都是128位2进制数据组成。通常会把它书写成32位16进制数据。 iii. 任何形式的数据,经过加密之后,都会变为二进制数据,长度为32位16进制数据。 ...

qq_31783363的博客 1475

Graphviz安装及使用:决策树可视化

Python大数据分析与机器学习学习笔记 Graphviz安装及使用:决策树可视化

算法工程师 1万+

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

java中的用户名和密码加密保存到txt文件中

刚开始接触java公司让做一个界面,其中用到用户名和密码的保存,在网上找到了MD5的加密方法。 所谓MD5,即"Message-Digest Algorithm 5(信息-摘要算法)",它由MD2、MD3、MD4发展而来的一种单向函数算法(也就是HASH算法),它是国际著名的公钥加密算法标准RSA的第一设计者R.Rivest于上个世纪90年代初开发出来的。MD5的最大作用在于,将不同格式的大

shenme18301582427的专栏 8050

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

linux之 md5sum 的用法

MD5算法常常被用来验证网络文件传输的完整性,防止文件被人篡改。MD5全称是报文摘要算法(Message-Digest Algorithm 5),此算法对任意长度的信息逐位进行计算,产生一个二进制长度为128位(十六进制长度就是32位)的“指纹”(或称“报文摘要”),不同的文件产生相 同的报文摘要的可能性是非常非常之小的。  在linux或Unix上,md5sum是用来计算和校验文件报文摘要的...

QLiuQ 853

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

消息摘要算法设计与实现

消息摘要算法设计与实现什么是消息摘要消息摘要和hash算法的区别消息摘要的应用为什么使用消息摘要算法设计与实现主要的应用的算法本文主要主要介绍-MD2、MD4、MD5 什么是消息摘要 消息摘要的定义:消息摘要(Message Digest)又称为数字摘要(Digital Digest)。它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生。如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了。因此消息摘要保证了消息的完整性

以梦为马!的博客 794
上一篇: Ms05039蠕虫的VC实现
下一篇: 用VC++6.0 Sockets API实现聊天室程序
goingup
博客等级 码龄22年 52粉丝 158原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值