开发语言:C/C++
实现功能:
下载地址:
HMAC-MD5.zip
更新历史:
V1.1 2010年05月08日
- 增加输出BASE64编码字符串接口。
V1.0 2010年04月15日
完成正式版本。
接口函数:
MD5_Hash
HMAC_MD5_Hash
MD5_BASE64
HMAC_MD5_BASE64
源文件:
HMAC_MD5_API.h
/* ---------------------------------------------------------- 文件名称:HMAC_MD5_API.h 作者:秦建辉 MSN:[email protected] 当前版本:V1.1 历史版本: V1.1 2010年05月08日 增加输出BASE64编码字符串接口。 V1.0 2010年04月15日 完成正式版本。 功能描述: MD5和HMAC-MD5加密 接口函数: MD5_Hash HMAC_MD5_Hash MD5_BASE64 HMAC_MD5_BASE64 ------------------------------------------------------------ */ #pragma once #include <windows.h> //-------------------导出函数------------- #ifdef __cplusplus extern "C"{ #endif /* 功能:计算输入数据的MD5哈希值 入口参数: inputBuffer:输入数据 inputCount:输入数据长度(字节数) outputBuffer:输入数据的哈希值 返回值: 哈希值的有效长度(字节数) */ INT MD5_Hash( const BYTE* inputBuffer, UINT inputCount, BYTE* outputBuffer ); /* 功能:计算输入数据的HMAC-MD5哈希值 入口参数: inputBuffer:输入数据 inputCount:输入数据长度(字节数) userKey:用户密钥 UserKeyLen:用户密钥长度 outputBuffer:输入数据的哈希值 返回值: 哈希值的有效长度(字节数) */ INT HMAC_MD5_Hash( const BYTE* inputBuffer, UINT inputCount, const BYTE* userKey, UINT UserKeyLen, BYTE* outputBuffer ); /* 功能:计算输入数据的MD5哈希值,并转换为BASE64编码字符串输出。 入口参数: inputBuffer:输入数据 inputCount:输入数据长度(字节数) outputBuffer:MD5哈希值的BASE64编码字符串 返回值: BASE64编码字符串长度(字符数),不包括字符串结束符 */ INT MD5_BASE64( const BYTE* inputBuffer, UINT inputCount, TCHAR* outputBuffer ); /* 功能:计算输入数据的HMAC-MD5哈希值,并转换为BASE64编码字符串输出。 入口参数: inputBuffer:输入数据 inputCount:输入数据长度(字节数) userKey:用户密钥 UserKeyLen:用户密钥长度 outputBuffer:HMAC-MD5哈希值的BASE64编码字符串 返回值: BASE64编码字符串长度(字符数),不包括字符串结束符 */ INT HMAC_MD5_BASE64( const BYTE* inputBuffer, UINT inputCount, const BYTE* userKey, UINT UserKeyLen, TCHAR* outputBuffer ); #ifdef __cplusplus } #endif
HMAC_MD5_DATA.h:
#pragma once typedef struct { DWORD p[4]; DWORD q[4][16]; } TYPE_MD5DATA; /* ------------------------------------------------ MD5关键参数,修改即可形成不同的变体 ------------------------------------------------ */ const TYPE_MD5DATA MD5_ARGUMENTS = { // 初始状态 {0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476}, // 变换操作偏移量表 {0xD76AA478,0xE8C7B756,0x242070DB,0xC1BDCEEE, 0xF57C0FAF,0x4787C62A,0xA8304613,0xFD469501, 0x698098D8,0x8B44F7AF,0xFFFF5BB1,0x895CD7BE, 0x6B901122,0xFD987193,0xA679438E,0x49B40821, 0xF61E2562,0xC040B340,0x265E5A51,0xE9B6C7AA, 0xD62F105D,0x02441453,0xD8A1E681,0xE7D3FBC8, 0x21E1CDE6,0xC33707D6,0xF4D50D87,0x455A14ED, 0xA9E3E905,0xFCEFA3F8,0x676F02D9,0x8D2A4C8A, 0xFFFA3942,0x8771F681,0x6D9D6122,0xFDE5380C, 0xA4BEEA44,0x4BDECFA9,0xF6BB4B60,0xBEBFBC70, 0x289B7EC6,0xEAA127FA,0xD4EF3085,0x04881D05, 0xD9D4D039,0xE6DB99E5,0x1FA27CF8,0xC4AC5665, 0xF4292244,0x432AFF97,0xAB9423A7,0xFC93A039, 0x655B59C3,0x8F0CCC92,0xFFEFF47D,0x85845DD1, 0x6FA87E4F,0xFE2CE6E0,0xA3014314,0x4E0811A1, 0xF7537E82,0xBD3AF235,0x2AD7D2BB,0xEB86D391} }; // 变换操作移位表 const BYTE MDShiftTable[][4] = {{7,12,17,22},{5,9,14,20},{4,11,16,23},{6,10,15,21}}; // 填充数据 const BYTE MDPadding[] = { 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 }; // MD5基本位操作函数 #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))) // 位循环左移位操作 #define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) // ---------变换操作---------- // 第一轮变换基本操作 #define FF(a, b, c, d, x, s, t) { / (a) += F((b), (c), (d)) + (x) + (t); / (a) = ROL((a), (s)); / (a) += (b); / } // 第二轮变换基本操作 #define GG(a, b, c, d, x, s, t) { / (a) += G((b), (c), (d)) + (x) + (t); / (a) = ROL((a), (s)); / (a) += (b); / } // 第三轮变换基本操作 #define HH(a, b, c, d, x, s, t) { / (a) += H((b), (c), (d)) + (x) + (t); / (a) = ROL((a), (s)); / (a) += (b); / } // 第四轮变换基本操作 #define II(a, b, c, d, x, s, t) { / (a) += I((b), (c), (d)) + (x) + (t); / (a) = ROL((a), (s)); / (a) += (b); / }
HMAC_MD5_API.cpp:
#include "HMAC_MD5_API.h" #include "HMAC_MD5_DATA.h" #include "..//BASE64//BASE64_API.h" // 定义数据结构 typedef struct _MD5CTX { DWORD aState[4]; // 记录数据的变化状态 DWORD aCount[2]; // 记录数据的原始长度(以bit为单位) BYTE aBuffer[64]; // 原始数据 } MD5CTX; // 初始化 void MD5_Init( MD5CTX* pstruContext ) { const DWORD *MDOriginState; MDOriginState = MD5_ARGUMENTS.p; pstruContext->aState[0] = MDOriginState[0]; pstruContext->aState[1] = MDOriginState[1]; pstruContext->aState[2] = MDOriginState[2]; pstruContext->aState[3] = MDOriginState[3]; pstruContext->aCount[0] = pstruContext->aCount[1] = 0; } // MD5基本变换操作 void MD5_Transform( DWORD* pState, DWORD* px ) { const DWORD (*MDOffTable)[16]; DWORD a,b,c,d; MDOffTable = MD5_ARGUMENTS.q; a = pState[0], b = pState[1], c = pState[2], d = pState[3]; // 第一轮变换 FF(a, b, c, d, px[ 0], MDShiftTable[0][0], MDOffTable[0][ 0]); FF(d, a, b, c, px[ 1], MDShiftTable[0][1], MDOffTable[0][ 1]); FF(c, d, a, b, px[ 2], MDShiftTable[0][2], MDOffTable[0][ 2]); FF(b, c, d, a, px[ 3], MDShiftTable[0][3], MDOffTable[0][ 3]); FF(a, b, c, d, px[ 4], MDShiftTable[0][0], MDOffTable[0][ 4]); FF(d, a, b, c, px[ 5], MDShiftTable[0][1], MDOffTable[0][ 5]); FF(c, d, a, b, px[ 6], MDShiftTable[0][2], MDOffTable[0][ 6]); FF(b, c, d, a, px[ 7], MDShiftTable[0][3], MDOffTable[0][ 7]); FF(a, b, c, d, px[ 8], MDShiftTable[0][0], MDOffTable[0][ 8]); FF(d, a, b, c, px[ 9], MDShiftTable[0][1], MDOffTable[0][ 9]); FF(c, d, a, b, px[10], MDShiftTable[0][2], MDOffTable[0][10]); FF(b, c, d, a, px[11], MDShiftTable[0][3], MDOffTable[0][11]); FF(a, b, c, d, px[12], MDShiftTable[0][0], MDOffTable[0][12]); FF(d, a, b, c, px[13], MDShiftTable[0][1], MDOffTable[0][13]); FF(c, d, a, b, px[14], MDShiftTable[0][2], MDOffTable[0][14]); FF(b, c, d, a, px[15], MDShiftTable[0][3], MDOffTable[0][15]); // 第二轮变换 GG(a, b, c, d, px[ 1], MDShiftTable[1][0], MDOffTable[1][ 0]); GG(d, a, b, c, px[ 6], MDShiftTable[1][1], MDOffTable[1][ 1]); GG(c, d, a, b, px[11], MDShiftTable[1][2], MDOffTable[1][ 2]); GG(b, c, d, a, px[ 0], MDShiftTable[1][3], MDOffTable[1][ 3]); GG(a, b, c, d, px[ 5], MDShiftTable[1][0], MDOffTable[1][ 4]); GG(d, a, b, c, px[10], MDShiftTable[1][1], MDOffTable[1][ 5]); GG(c, d, a, b, px[15], MDShiftTable[1][2], MDOffTable[1][ 6]); GG(b, c, d, a, px[ 4], MDShiftTable[1][3], MDOffTable[1][ 7]); GG(a, b, c, d, px[ 9], MDShiftTable[1][0], MDOffTable[1][ 8]); GG(d, a, b, c, px[14], MDShiftTable[1][1], MDOffTable[1][ 9]); GG(c, d, a, b, px[ 3], MDShiftTable[1][2], MDOffTable[1][10]); GG(b, c, d, a, px[ 8], MDShiftTable[1][3], MDOffTable[1][11]); GG(a, b, c, d, px[13], MDShiftTable[1][0], MDOffTable[1][12]); GG(d, a, b, c, px[ 2], MDShiftTable[1][1], MDOffTable[1][13]); GG(c, d, a, b, px[ 7], MDShiftTable[1][2], MDOffTable[1][14]); GG(b, c, d, a, px[12], MDShiftTable[1][3], MDOffTable[1][15]); // 第三轮变换 HH(a, b, c, d, px[ 5], MDShiftTable[2][0], MDOffTable[2][ 0]); HH(d, a, b, c, px[ 8], MDShiftTable[2][1], MDOffTable[2][ 1]); HH(c, d, a, b, px[11], MDShiftTable[2][2], MDOffTable[2][ 2]); HH(b, c, d, a, px[14], MDShiftTable[2][3], MDOffTable[2][ 3]); HH(a, b, c, d, px[ 1], MDShiftTable[2][0], MDOffTable[2][ 4]); HH(d, a, b, c, px[ 4], MDShiftTable[2][1], MDOffTable[2][ 5]); HH(c, d, a, b, px[ 7], MDShiftTable[2][2], MDOffTable[2][ 6]); HH(b, c, d, a, px[10], MDShiftTable[2][3], MDOffTable[2][ 7]); HH(a, b, c, d, px[13], MDShiftTable[2][0], MDOffTable[2][ 8]); HH(d, a, b, c, px[ 0], MDShiftTable[2][1], MDOffTable[2][ 9]); HH(c, d, a, b, px[ 3], MDShiftTable[2][2], MDOffTable[2][10]); HH(b, c, d, a, px[ 6], MDShiftTable[2][3], MDOffTable[2][11]); HH(a, b, c, d, px[ 9], MDShiftTable[2][0], MDOffTable[2][12]); HH(d, a, b, c, px[12], MDShiftTable[2][1], MDOffTable[2][13]); HH(c, d, a, b, px[15], MDShiftTable[2][2], MDOffTable[2][14]); HH(b, c, d, a, px[ 2], MDShiftTable[2][3], MDOffTable[2][15]); // 第四轮变换 II(a, b, c, d, px[ 0], MDShiftTable[3][0], MDOffTable[3][ 0]); II(d, a, b, c, px[ 7], MDShiftTable[3][1], MDOffTable[3][ 1]); II(c, d, a, b, px[14], MDShiftTable[3][2], MDOffTable[3][ 2]); II(b, c, d, a, px[ 5], MDShiftTable[3][3], MDOffTable[3][ 3]); II(a, b, c, d, px[12], MDShiftTable[3][0], MDOffTable[3][ 4]); II(d, a, b, c, px[ 3], MDShiftTable[3][1], MDOffTable[3][ 5]); II(c, d, a, b, px[10], MDShiftTable[3][2], MDOffTable[3][ 6]); II(b, c, d, a, px[ 1], MDShiftTable[3][3], MDOffTable[3][ 7]); II(a, b, c, d, px[ 8], MDShiftTable[3][0], MDOffTable[3][ 8]); II(d, a, b, c, px[15], MDShiftTable[3][1], MDOffTable[3][ 9]); II(c, d, a, b, px[ 6], MDShiftTable[3][2], MDOffTable[3][10]); II(b, c, d, a, px[13], MDShiftTable[3][3], MDOffTable[3][11]); II(a, b, c, d, px[ 4], MDShiftTable[3][0], MDOffTable[3][12]); II(d, a, b, c, px[11], MDShiftTable[3][1], MDOffTable[3][13]); II(c, d, a, b, px[ 2], MDShiftTable[3][2], MDOffTable[3][14]); II(b, c, d, a, px[ 9], MDShiftTable[3][3], MDOffTable[3][15]); pState[0] += a; pState[1] += b; pState[2] += c; pState[3] += d; } // MD5块更新操作 void MD5_Update( MD5CTX* pstruContext, const BYTE* pInput, DWORD dwInputLen ) { DWORD i, dwIndex, dwPartLen, dwBitsNum; // 计算 mod 64 的字节数 dwIndex = (pstruContext->aCount[0] >> 3) & 0x3F; // 更新数据位数 dwBitsNum = dwInputLen << 3; pstruContext->aCount[0] += dwBitsNum; if(pstruContext->aCount[0] < dwBitsNum) { pstruContext->aCount[1]++; } pstruContext->aCount[1] += dwInputLen >> 29; dwPartLen = 64 - dwIndex; if(dwInputLen >= dwPartLen) { memcpy( pstruContext->aBuffer+dwIndex, pInput, dwPartLen ); MD5_Transform( pstruContext->aState, (DWORD*)pstruContext->aBuffer ); for(i = dwPartLen; i + 63 < dwInputLen; i += 64 ) { MD5_Transform( pstruContext->aState, (DWORD*)(pInput + i) ); } dwIndex = 0; } else { i = 0; } memcpy( pstruContext->aBuffer + dwIndex, pInput + i, dwInputLen - i ); } // 处理最后的数据块 void MD5_Final( MD5CTX* pstruContext ) { DWORD dwIndex, dwPadLen; BYTE pBits[8]; memcpy( pBits, pstruContext->aCount, 8 ); // 计算 mod 64 的字节数 dwIndex = (pstruContext->aCount[0] >> 3) & 0x3F; // 使长度满足K*64+56个字节 dwPadLen = (dwIndex < 56) ? (56-dwIndex) : (120-dwIndex); MD5_Update( pstruContext, MDPadding, dwPadLen ); MD5_Update( pstruContext, pBits, 8 ); } INT MD5_Hash( const BYTE* inputBuffer, UINT inputCount, BYTE* outputBuffer ) { MD5CTX struContext; if( inputBuffer == NULL ) { inputCount = 0; } // 进行MD5变换 MD5_Init( &struContext ); // 初始化 MD5_Update( &struContext, inputBuffer, inputCount ); // MD5数据块更新操作 MD5_Final( &struContext ); // 获得最终结果 // 获取哈希值 if( outputBuffer != NULL ) { memcpy( outputBuffer, struContext.aState, 16 ); } return 16; } INT HMAC_MD5_Hash( const BYTE* inputBuffer, UINT inputCount, const BYTE* userKey, UINT UserKeyLen, BYTE* outputBuffer ) { BYTE hmacKey[64] = {0}; BYTE k_ipad[64]; BYTE k_opad[64]; MD5CTX struContext; if( inputBuffer == NULL ) { inputCount = 0; } if( userKey == NULL ) { UserKeyLen = 0; } // 保证密钥长度不超过64字节 if( UserKeyLen > 64 ) { MD5_Hash( userKey, UserKeyLen, hmacKey ); } else { memcpy( hmacKey, userKey, UserKeyLen ); } for( UINT i = 0; i < 64; i++ ) { k_ipad[i] = hmacKey[i] ^ 0x36; k_opad[i] = hmacKey[i] ^ 0x5C; } // 内圈MD5运算 MD5_Init( &struContext ); // 初始化 MD5_Update( &struContext, k_ipad, 64 ); // MD5数据块更新操作 MD5_Update( &struContext, inputBuffer, inputCount ); // MD5数据块更新操作 MD5_Final( &struContext ); // 获得最终结果 memcpy( hmacKey, struContext.aState, 16 ); // 外圈MD5运算 MD5_Init( &struContext ); // 初始化 MD5_Update( &struContext, k_opad, 64 ); // MD5数据块更新操作 MD5_Update( &struContext, hmacKey, 16 ); // MD5数据块更新操作 MD5_Final( &struContext ); // 获得最终结果 // 获取哈希值 if( outputBuffer != NULL ) { memcpy( outputBuffer, struContext.aState, 16 ); } return 16; } INT MD5_BASE64( const BYTE* inputBuffer, UINT inputCount, TCHAR* outputBuffer ) { BYTE hash[16]; INT iByteNum; // 计算输入串MD5的哈希值 iByteNum = MD5_Hash( inputBuffer, inputCount, hash ); // 将哈希值转换成BASE64编码 return BASE64_Encode( hash, iByteNum, outputBuffer ); } INT HMAC_MD5_BASE64( const BYTE* inputBuffer, UINT inputCount, const BYTE* userKey, UINT UserKeyLen, TCHAR* outputBuffer ) { BYTE hash[16]; INT iByteNum; // 计算输入串HMAC-MD5的哈希值 iByteNum = HMAC_MD5_Hash( inputBuffer, inputCount, userKey, UserKeyLen, hash ); // 将哈希值转换成BASE64编码 return BASE64_Encode( hash, iByteNum, outputBuffer ); }