⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 md5.h

📁 MD5算法的C++版本
💻 H
📖 第 1 页 / 共 3 页
字号:
// MD5.h: interface for the MD5 class.

/*
 *	Copyright (c) 2006 - 2007 All Rights Reserved
 *
 *	程序作者:
 *		张鲁夺(zhangluduo) : 为所有爱我的人和我爱的人努力!
 *
 *	联系方式:
 *		zhangluduo@msn.com
 *		QQ群:34064264
 *
 *	更新时间:
 *		2007-10-24
 *
 *	功能描述:
 *		MD5算法实现, 根据rfc1321.txt中的源码封装成C++类, 详细算法流程请参
 *		见rfc1321.txt
 *
 *	授权声明:
 *		许可任何单位,个人随意使用,拷贝,修改,散布及出售这份代码,及其相关的
 *		开发文档,但是必须保留此版权信息,以慰藉作者辛勤的劳动,及表明此代码
 *		的来源,如若此份代码有任何BUG或者您有更好的修改建议, 请通知作者,以
 *		便弥补作者由于水平所限而导致的一些错误和不足,谢谢!
 */

#ifndef _MD5_H
#define _MD5_H

#pragma warning(disable : 4786)
#include <string>
using namespace std;

#include <WINDOWS.h>		// for GetFileSize API
#include <STDIO.h>			// for sprintf
#include "FunctionAddr.h"

#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21

// F, G, H and I are basic MD5 functions.
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))

// ROTATE_LEFT rotates x left n bits.
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))

/** FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
	Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac)							\
{															\
	(a) += F ((b), (c), (d)) + (x) + (unsigned long)(ac);	\
	(a) = ROTATE_LEFT ((a), (s));							\
	(a) += (b); 											\
}
#define GG(a, b, c, d, x, s, ac)							\
{															\
	(a) += G ((b), (c), (d)) + (x) + (unsigned long)(ac);	\
	(a) = ROTATE_LEFT ((a), (s));							\
	(a) += (b);												\
}
#define HH(a, b, c, d, x, s, ac)							\
{															\
	(a) += H ((b), (c), (d)) + (x) + (unsigned long)(ac);	\
	(a) = ROTATE_LEFT ((a), (s));							\
	(a) += (b);												\
}
#define II(a, b, c, d, x, s, ac)							\
{															\
	(a) += I ((b), (c), (d)) + (x) + (unsigned long)(ac);	\
	(a) = ROTATE_LEFT ((a), (s));							\
	(a) += (b);												\
}

class MD5
{
public:

	MD5();
	virtual ~MD5();

private:

	// MD5 context.
	struct MD5_CTX
	{
		unsigned long state[4];		// state (ABCD)
		unsigned long count[2];		// number of bits, modulo 2^64 (lsb first)
		unsigned char buffer[64];	// input buffer
	};

	// this value must initialize first
	unsigned char PADDING[64];

private:

	/** Encodes input (UINT4) into output (unsigned char). Assumes len is
		a multiple of 4.
	*/
	void Encode (unsigned char *output, unsigned long *input, unsigned int len);

	/** Encodes input (UINT4) into output (unsigned char). Assumes len is
		a multiple of 4.
	*/
	void Decode (unsigned long* output, unsigned char *input, unsigned int len);

	/** Decodes input (unsigned char) into output (UINT4). Assumes len is
		a multiple of 4.
	*/
	void MD5_memset (unsigned char* output, int value, unsigned int len);

	// Note: Replace "for loop" with standard memcpy if possible.
	void MD5_memcpy (unsigned char* output, unsigned char* input, unsigned int len);

private:


	/** step 1
		MD5 initialization. Begins an MD5 operation, writing a new context.
	*/
	void MD5Init (struct MD5_CTX *context);

	/** step 2
		MD5 block update operation. Continues an MD5 message-digest
		operation, processing another message block, and updating the
		context.
	*/
	void MD5Update (struct MD5_CTX *context, /* context */ unsigned char *input, /* input block */ unsigned int inputLen /* length of input block */);

	/** step 3
		MD5 basic transformation. Transforms state based on block.
	*/
	void MD5Transform (unsigned long state[4], unsigned char block[64]);

	/** step 4
		MD5 finalization. Ends an MD5 message-digest operation, writing the
		the message digest and zeroizing the context.
	*/
	void MD5Final (unsigned char digest[16], /* message digest */ MD5_CTX *context /* context */);

private:

	string	m_strErr;	// 错误描述
	bool	m_bStop;	// 终止文件计算标志

	// 将寄存器A, B, C, D的值转换为十六进制, 并以字符串方式返回
	string	ResultToHex(unsigned char digest[16], bool bUppercase = true);

	// 调用用户指定的回调函数
	void	OnFileProcessing(int nProgress, FunctionAddr addr);

public:


	/** 获取文件的MD5值
		参数
			FileName	- 文件名
			bUppercase	- 结果是否转换为大写
			addr		- 回调函数地址, 通过回调函数把计算进度回传给用户, 
						  函数原型:void OnFileProcessing(int nProgress);
		注意
			因为在对一个较大的文件计算MD5值的时间较长, 为避免界面发生假死
			现象, 尽量将这个函数放在一个单独的线程中调用
	*/
	string	MD5File   (const char *FileName, bool bUppercase = true, FunctionAddr addr = 0);

	/** 获取字符串的MD5值
		pData		- 待计算MD5值的数据
		DataLen		- 数据长度(单位, 字节)
		Uppercase	- 结果是否转换为大写
	*/
	string	MD5String (unsigned char *pData, unsigned long DataLen, bool bUppercase = true);

	/** 计算文件MD5值时, 半途终止计算, 需要注意的是, 
		这个函数与MD5File尽量不要放在一个线程中
	*/
	void	FileTerminate();

	// 获取错误描述
	string GetError();

};

#endif





//	rfc1321.txt
//
//	Network Working Group                                          R. Rivest
//	Request for Comments: 1321           MIT Laboratory for Computer Science
//												 and RSA Data Security, Inc.
//																  April 1992
//
//
//						 The MD5 Message-Digest Algorithm
//
//	Status of this Memo
//
//	   This memo provides information for the Internet community.  It does
//	   not specify an Internet standard.  Distribution of this memo is
//	   unlimited.
//
//	Acknowlegements
//
//	   We would like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle,
//	   David Chaum, and Noam Nisan for numerous helpful comments and
//	   suggestions.
//
//	Table of Contents
//
//	   1. Executive Summary                                                1
//	   2. Terminology and Notation                                         2
//	   3. MD5 Algorithm Description                                        3
//	   4. Summary                                                          6
//	   5. Differences Between MD4 and MD5                                  6
//	   References                                                          7
//	   APPENDIX A - Reference Implementation                               7
//	   Security Considerations                                            21
//	   Author's Address                                                   21
//
//	1. Executive Summary
//
//	   This document describes the MD5 message-digest algorithm. The
//	   algorithm takes as input a message of arbitrary length and produces
//	   as output a 128-bit "fingerprint" or "message digest" of the input.
//	   It is conjectured that it is computationally infeasible to produce
//	   two messages having the same message digest, or to produce any
//	   message having a given prespecified target message digest. The MD5
//	   algorithm is intended for digital signature applications, where a
//	   large file must be "compressed" in a secure manner before being
//	   encrypted with a private (secret) key under a public-key cryptosystem
//	   such as RSA.
//
//	Rivest                                                          [Page 1]
//	
//	RFC 1321              MD5 Message-Digest Algorithm            April 1992
//
//
//	   The MD5 algorithm is designed to be quite fast on 32-bit machines. In
//	   addition, the MD5 algorithm does not require any large substitution
//	   tables; the algorithm can be coded quite compactly.
//
//	   The MD5 algorithm is an extension of the MD4 message-digest algorithm
//	   1,2]. MD5 is slightly slower than MD4, but is more "conservative" in
//	   design. MD5 was designed because it was felt that MD4 was perhaps
//	   being adopted for use more quickly than justified by the existing
//	   critical review; because MD4 was designed to be exceptionally fast,
//	   it is "at the edge" in terms of risking successful cryptanalytic
//	   attack. MD5 backs off a bit, giving up a little in speed for a much
//	   greater likelihood of ultimate security. It incorporates some
//	   suggestions made by various reviewers, and contains additional
//	   optimizations. The MD5 algorithm is being placed in the public domain
//	   for review and possible adoption as a standard.
//
//	   For OSI-based applications, MD5's object identifier is
//
//	   md5 OBJECT IDENTIFIER ::=
//		 iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
//
//	   In the X.509 type AlgorithmIdentifier [3], the parameters for MD5
//	   should have type NULL.
//
//	2. Terminology and Notation
//
//	   In this document a "word" is a 32-bit quantity and a "byte" is an
//	   eight-bit quantity. A sequence of bits can be interpreted in a
//	   natural manner as a sequence of bytes, where each consecutive group
//	   of eight bits is interpreted as a byte with the high-order (most
//	   significant) bit of each byte listed first. Similarly, a sequence of
//	   bytes can be interpreted as a sequence of 32-bit words, where each
//	   consecutive group of four bytes is interpreted as a word with the
//	   low-order (least significant) byte given first.
//
//	   Let x_i denote "x sub i". If the subscript is an expression, we
//	   surround it in braces, as in x_{i+1}. Similarly, we use ^ for
//	   superscripts (exponentiation), so that x^i denotes x to the i-th
//	   power.
//
//	   Let the symbol "+" denote addition of words (i.e., modulo-2^32
//	   addition). Let X <<< s denote the 32-bit value obtained by circularly
//	   shifting (rotating) X left by s bit positions. Let not(X) denote the
//	   bit-wise complement of X, and let X v Y denote the bit-wise OR of X
//	   and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY
//	   denote the bit-wise AND of X and Y.
//
//	Rivest                                                          [Page 2]
//	
//	RFC 1321              MD5 Message-Digest Algorithm            April 1992
//
//
//	3. MD5 Algorithm Description
//
//	   We begin by supposing that we have a b-bit message as input, and that
//	   we wish to find its message digest. Here b is an arbitrary
//	   nonnegative integer; b may be zero, it need not be a multiple of
//	   eight, and it may be arbitrarily large. We imagine the bits of the
//	   message written down as follows:
//
//			  m_0 m_1 ... m_{b-1}
//
//	   The following five steps are performed to compute the message digest
//	   of the message.
//
//	3.1 Step 1. Append Padding Bits
//
//	   The message is "padded" (extended) so that its length (in bits) is
//	   congruent to 448, modulo 512. That is, the message is extended so
//	   that it is just 64 bits shy of being a multiple of 512 bits long.
//	   Padding is always performed, even if the length of the message is
//	   already congruent to 448, modulo 512.
//
//	   Padding is performed as follows: a single "1" bit is appended to the
//	   message, and then "0" bits are appended so that the length in bits of
//	   the padded message becomes congruent to 448, modulo 512. In all, at
//	   least one bit and at most 512 bits are appended.
//
//	3.2 Step 2. Append Length
//
//	   A 64-bit representation of b (the length of the message before the
//	   padding bits were added) is appended to the result of the previous
//	   step. In the unlikely event that b is greater than 2^64, then only
//	   the low-order 64 bits of b are used. (These bits are appended as two
//	   32-bit words and appended low-order word first in accordance with the
//	   previous conventions.)
//
//	   At this point the resulting message (after padding with bits and with
//	   b) has a length that is an exact multiple of 512 bits. Equivalently,
//	   this message has a length that is an exact multiple of 16 (32-bit)
//	   words. Let M[0 ... N-1] denote the words of the resulting message,
//	   where N is a multiple of 16.
//
//	3.3 Step 3. Initialize MD Buffer
//
//	   A four-word buffer (A,B,C,D) is used to compute the message digest.
//	   Here each of A, B, C, D is a 32-bit register. These registers are
//	   initialized to the following values in hexadecimal, low-order bytes
//	   first):
//
//	Rivest                                                          [Page 3]
//	
//	RFC 1321              MD5 Message-Digest Algorithm            April 1992
//
//
//			  word A: 01 23 45 67
//			  word B: 89 ab cd ef
//			  word C: fe dc ba 98
//			  word D: 76 54 32 10
//
//	3.4 Step 4. Process Message in 16-Word Blocks
//
//	   We first define four auxiliary functions that each take as input
//	   three 32-bit words and produce as output one 32-bit word.
//
//			  F(X,Y,Z) = XY v not(X) Z
//			  G(X,Y,Z) = XZ v Y not(Z)
//			  H(X,Y,Z) = X xor Y xor Z
//			  I(X,Y,Z) = Y xor (X v not(Z))
//
//	   In each bit position F acts as a conditional: if X then Y else Z.
//	   The function F could have been defined using + instead of v since XY
//	   and not(X)Z will never have 1's in the same bit position.) It is
//	   interesting to note that if the bits of X, Y, and Z are independent
//	   and unbiased, the each bit of F(X,Y,Z) will be independent and
//	   unbiased.
//
//	   The functions G, H, and I are similar to the function F, in that they
//	   act in "bitwise parallel" to produce their output from the bits of X,
//	   Y, and Z, in such a manner that if the corresponding bits of X, Y,
//	   and Z are independent and unbiased, then each bit of G(X,Y,Z),
//	   H(X,Y,Z), and I(X,Y,Z) will be independent and unbiased. Note that
//	   the function H is the bit-wise "xor" or "parity" function of its
//	   inputs.
//
//	   This step uses a 64-element table T[1 ... 64] constructed from the
//	   sine function. Let T[i] denote the i-th element of the table, which
//	   is equal to the integer part of 4294967296 times abs(sin(i)), where i
//	   is in radians. The elements of the table are given in the appendix.
//
//	   Do the following:
//
//	   /* Process each 16-word block. */
//	   For i = 0 to N/16-1 do
//
//		 /* Copy block i into X. */
//		 For j = 0 to 15 do
//		   Set X[j] to M[i*16+j].
//		 end /* of loop on j */
//
//		 /* Save A as AA, B as BB, C as CC, and D as DD. */
//		 AA = A
//		 BB = B
//
//	Rivest                                                          [Page 4]
//	
//	RFC 1321              MD5 Message-Digest Algorithm            April 1992
//
//
//		 CC = C
//		 DD = D
//
//		 /* Round 1. */
//		 /* Let [abcd k s i] denote the operation
//			  a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
//		 /* Do the following 16 operations. */
//		 [ABCD  0  7  1]  [DABC  1 12  2]  [CDAB  2 17  3]  [BCDA  3 22  4]
//		 [ABCD  4  7  5]  [DABC  5 12  6]  [CDAB  6 17  7]  [BCDA  7 22  8]
//		 [ABCD  8  7  9]  [DABC  9 12 10]  [CDAB 10 17 11]  [BCDA 11 22 12]
//		 [ABCD 12  7 13]  [DABC 13 12 14]  [CDAB 14 17 15]  [BCDA 15 22 16]
//
//		 /* Round 2. */
//		 /* Let [abcd k s i] denote the operation
//			  a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
//		 /* Do the following 16 operations. */
//		 [ABCD  1  5 17]  [DABC  6  9 18]  [CDAB 11 14 19]  [BCDA  0 20 20]
//		 [ABCD  5  5 21]  [DABC 10  9 22]  [CDAB 15 14 23]  [BCDA  4 20 24]
//		 [ABCD  9  5 25]  [DABC 14  9 26]  [CDAB  3 14 27]  [BCDA  8 20 28]
//		 [ABCD 13  5 29]  [DABC  2  9 30]  [CDAB  7 14 31]  [BCDA 12 20 32]
//
//		 /* Round 3. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -