code_app/modules/base/HGMd5.cpp

314 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "HGMd5.h"
#include "HGInc.h"
/* Constants for MD5Transform routine. */
/* md5转换用到的常量算法本身规定的 */
#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
/*
接下来的这几个宏定义是md5算法规定的就是对信息进行md5加密都要做的运算。
据说有经验的高手跟踪程序时根据这几个特殊的操作就可以断定是不是用的md5
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) + (HGUInt)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
#define GG(a, b, c, d, x, s, ac) { (a) += G ((b), (c), (d)) + (x) + (HGUInt)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
#define HH(a, b, c, d, x, s, ac) { (a) += H ((b), (c), (d)) + (x) + (HGUInt)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
#define II(a, b, c, d, x, s, ac) { (a) += I ((b), (c), (d)) + (x) + (HGUInt)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
/* MD5 context. */
struct MD5_CTX
{
/* state (ABCD) */
/*四个32bits数用于存放最终计算得到的消息摘要。当消息长度〉512bits时也用于存放每个512bits的中间结果*/
HGUInt state[4];
/* number of bits, modulo 2^64 (lsb first) */
/*存储原始信息的bits数长度,不包括填充的bits最长为 2^64 bits因为2^64是一个64位数的最大值*/
HGUInt count[2];
/* input buffer */
/*存放输入的信息的缓冲区512bits*/
HGByte buffer[64];
};
/* MD5 initialization. Begins an MD5 operation, writing a new context. */
/*初始化md5的结构*/
static void MD5Init(MD5_CTX* ctx)
{
/*将当前的有效信息的长度设成0,这个很简单,还没有有效信息,长度当然是0了*/
ctx->count[0] = 0;
ctx->count[1] = 0;
/* Load magic initialization constants.*/
/*初始化链接变量,算法要求这样,这个没法解释了*/
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xefcdab89;
ctx->state[2] = 0x98badcfe;
ctx->state[3] = 0x10325476;
}
/*
将4字节的整数copy到字符形式的缓冲区中
output用于输出的字符缓冲区
input欲转换的四字节的整数形式的数组
lenoutput缓冲区的长度要求是4的整数倍
*/
static void MD5Encode(HGByte* output, const HGUInt* input, HGUInt len)
{
for (HGUInt i = 0, j = 0; j < len; i++, j += 4)
{
output[j] = (HGByte)(input[i] & 0xFF);
output[j + 1] = (HGByte)((input[i] >> 8) & 0xFF);
output[j + 2] = (HGByte)((input[i] >> 16) & 0xFF);
output[j + 3] = (HGByte)((input[i] >> 24) & 0xFF);
}
}
/*
与上面的函数正好相反这一个把字符形式的缓冲区中的数据copy到4字节的整数中即以整数形式保存
output保存转换出的整数
input欲转换的字符缓冲区
len输入的字符缓冲区的长度要求是4的整数倍
*/
static void MD5Decode(HGUInt* output, const HGByte* input, HGUInt len)
{
for (HGUInt i = 0, j = 0; j < len; i++, j += 4)
{
output[i] = ((HGUInt)input[j]) | (((HGUInt)input[j + 1]) << 8) | (((HGUInt)input[j + 2]) << 16) | (((HGUInt)input[j + 3]) << 24);
}
}
/*
对512bits信息(即block缓冲区)进行一次处理,每次处理包括四轮
state[4]md5结构中的state[4]用于保存对512bits信息加密的中间结果或者最终结果
block[64]欲加密的512bits信息
*/
static void MD5Transform(HGUInt* state, const HGByte* block)
{
HGUInt a = state[0], b = state[1], c = state[2], d = state[3], x[16];
MD5Decode(x, block, 64);
/* Round 1 */
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information. */
memset(x, 0, sizeof(x));
}
/*
MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
将与加密的信息传递给md5结构可以多次调用
context初始化过了的md5结构
input欲加密的信息可以任意长
inputLen指定input的长度
*/
static void MD5Update(MD5_CTX* ctx, const HGByte* data, HGUInt size)
{
HGUInt i, index, partLen;
/*
计算已有信息的bits长度的字节数的模64, 64bytes=512bits。
用于判断已有信息加上当前传过来的信息的总长度能不能达到512bits
如果能够达到则对凑够的512bits进行一次处理
*/
index = (HGUInt)((ctx->count[0] >> 3) & 0x3F);
/* Update number of bits *//*更新已有信息的bits长度 */
if ((ctx->count[0] += ((HGUInt)size << 3)) < ((HGUInt)size << 3))
ctx->count[1]++;
ctx->count[1] += ((HGUInt)size >> 29);
/* 计算已有的字节数长度还差多少字节可以 凑成64的整倍数 */
partLen = 64 - index;
/* 如果当前输入的字节数 大于 已有字节数长度补足64字节整倍数所差的字节数 */
if (size >= partLen)
{
/* 用当前输入的内容把ctx->buffer的内容补足512bits */
memcpy(&ctx->buffer[index], data, partLen);
/* 用基本函数对填充满的512bits已经保存到ctx->buffer中 做一次转换转换结果保存到ctx->state中 */
MD5Transform(ctx->state, ctx->buffer);
/*
对当前输入的剩余字节做转换(如果剩余的字节<在输入的data缓冲区中>大于512bits的话
转换结果保存到ctx->state中
*/
for (i = partLen; i + 63 < size; i += 64) /* 把i+63<size改为i+64<=size更容易理解 */
MD5Transform(ctx->state, &data[i]);
index = 0;
}
else
{
i = 0;
}
/* 将输入缓冲区中的不足填充满512bits的剩余内容填充到ctx->buffer中留待以后再作处理 */
memcpy(&ctx->buffer[index], &data[i], size - i);
}
/*
MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
获取加密 的最终结果
digest保存最终的加密串
context你前面初始化并填入了信息的md5结构
*/
static void MD5Final(MD5_CTX* ctx, HGByte* md5)
{
/*
用于bits填充的缓冲区为什么要64个字节呢因为当欲加密的信息的bits数被512除其余数为448时
需要填充的bits的最大值为512=64*8 。
*/
static const HGByte MD5_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
};
HGByte bits[8];
HGUInt index, padLen;
/* 将要被转换的信息(所有的)的bits长度拷贝到bits中 */
MD5Encode(bits, ctx->count, 8);
/* 计算所有的bits长度的字节数的模64, 64bytes=512bits */
index = (HGUInt)((ctx->count[0] >> 3) & 0x3F);
/* 计算需要填充的字节数padLen的取值范围在1-64之间 */
padLen = (index < 56) ? (56 - index) : (120 - index);
/* 这一次函数调用绝对不会再导致MD5Transform的被调用因为这一次不会填满512bits */
MD5Update(ctx, MD5_PADDING, padLen);
/* 补上原始信息的bits长度bits长度固定的用64bits表示这一次能够恰巧凑够512bits不会多也不会少 */
MD5Update(ctx, bits, 8);
/* Store state in digest */
MD5Encode(md5, ctx->state, 16);
memset(ctx, 0, sizeof(MD5_CTX));
}
HGResult HGAPI HGBase_MakeMd5(const HGByte* data, HGUInt size, HGByte* md5)
{
if (NULL == data || 0 == size || NULL == md5)
{
return HGBASE_ERR_INVALIDARG;
}
MD5_CTX ctx;
MD5Init(&ctx);
MD5Update(&ctx, data, size);
MD5Final(&ctx, md5);
return HGBASE_ERR_OK;
}