📄 md5.h
字号:
// 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 + -