C++实现MD5
发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,以下代码是自己用C++语言对MD5算法的实现,编程工具是VC2013。虽然代码的封装性、安全性和效率远远比不上RFC文档中的标准实现或者OpenSSL的源码(这些代码研究了很久依旧没看懂,它们的效率虽
千家信息网最后更新 2026年10月31日C++实现MD5
以下代码是自己用C++语言对MD5算法的实现,编程工具是VC2013。虽然代码的封装性、安全性和效率远远比不上RFC文档中的标准实现或者OpenSSL的源码(这些代码研究了很久依旧没看懂,它们的效率虽高,但可读性不高,不适合于我这种基础比较薄弱的童鞋阅读),但算法思路比较直观,清晰易懂,方便让基础比较薄弱的童鞋阅读。本人属于C++初学者,编写的代码可能不够简洁,不够美观,很多地方也没有考虑周到,希望大家见谅,也希望能有高手能指正批评。
注意:每处理64个字符就进行一次MD5操作,MD5算法本身不算太难,主要是输入消息的预处理过程比较麻烦。
#pragma warning(disable : 4996)//VC2013增加了安全机制,如果不加这句会出现编译错误#include#include #include #include #include using namespace std;typedef unsigned int UNINT;//为unsigned int重命名,方便编程#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 21UNINT hash_state[4];UNINT word_32[16];char block[64];//初始化向量(A,B,C,D)void Init(){ hash_state[0] = 0x67452301; hash_state[1] = 0xefcdab89; hash_state[2] = 0x98badcfe; hash_state[3] = 0x10325476;}//将长度为64的字符数组转换成长度为16的整型数组,即将四个字符数组单元转换为一个整型数组int char64_to_word32(int n){ int i; for (i = 0; i < n; i++){ word_32[i] = (block[4 * i + 0] << 24) ^ (block[4 * i + 1] << 16) ^ (block[4 * i + 2] << 8) ^ block[4 * i + 3]; } return i;}//新建一个分组存放消息长度void newblock_length(UNINT l){ for (int i = 0; i < 15; i++){ word_32[i] = 0; } //将消息长度存放在最后4个字节 word_32[15] = l;}UNINT rotate_left(UNINT x, UNINT n){ return ((x << n) | (x >> (32 - n)));}UNINT F(UNINT x, UNINT y, UNINT z){ return ((x & y) | (~x & z));}UNINT G(UNINT x, UNINT y, UNINT z){ return ((x & z) | (y & ~z));}UNINT H(UNINT x, UNINT y, UNINT z){ return (x ^ y ^ z);}UNINT I(UNINT x, UNINT y, UNINT z){ return (y ^ (x | ~z));}void FF(UNINT* a, UNINT b, UNINT c, UNINT d, UNINT x, UNINT s, UNINT ac){ *a += F(b, c, d) + x + ac; *a = rotate_left(*a, s); *a += b;}void GG(UNINT* a, UNINT b, UNINT c, UNINT d, UNINT x, UNINT s, UNINT ac){ *a += G(b, c, d) + x + ac; *a = rotate_left(*a, s); *a += b;}void HH(UNINT* a, UNINT b, UNINT c, UNINT d, UNINT x, UNINT s, UNINT ac){ *a += H(b, c, d) + x + ac; *a = rotate_left(*a, s); *a += b;}void II(UNINT* a, UNINT b, UNINT c, UNINT d, UNINT x, UNINT s, UNINT ac){ *a += I(b, c, d) + x + ac; *a = rotate_left(*a, s); *a += b;}void MD5_Transform(UNINT* x){ UNINT a, b, c, d; a = hash_state[0]; b = hash_state[1]; c = hash_state[2]; d = hash_state[3]; // Round 1 FF(&a, b, c, d, x[0], S11, 0xd76aa478); FF(&d, a, b, c, x[1], S12, 0xe8c7b756); FF(&c, d, a, b, x[2], S13, 0x242070db); FF(&b, c, d, a, x[3], S14, 0xc1bdceee); FF(&a, b, c, d, x[4], S11, 0xf57c0faf); FF(&d, a, b, c, x[5], S12, 0x4787c62a); FF(&c, d, a, b, x[6], S13, 0xa8304613); FF(&b, c, d, a, x[7], S14, 0xfd469501); FF(&a, b, c, d, x[8], S11, 0x698098d8); FF(&d, a, b, c, x[9], S12, 0x8b44f7af); FF(&c, d, a, b, x[10], S13, 0xffff5bb1); FF(&b, c, d, a, x[11], S14, 0x895cd7be); FF(&a, b, c, d, x[12], S11, 0x6b901122); FF(&d, a, b, c, x[13], S12, 0xfd987193); FF(&c, d, a, b, x[14], S13, 0xa679438e); FF(&b, c, d, a, x[15], S14, 0x49b40821); // Round 2 GG(&a, b, c, d, x[1], S21, 0xf61e2562); GG(&d, a, b, c, x[6], S22, 0xc040b340); GG(&c, d, a, b, x[11], S23, 0x265e5a51); GG(&b, c, d, a, x[0], S24, 0xe9b6c7aa); GG(&a, b, c, d, x[5], S21, 0xd62f105d); GG(&d, a, b, c, x[10], S22, 0x2441453); GG(&c, d, a, b, x[15], S23, 0xd8a1e681); GG(&b, c, d, a, x[4], S24, 0xe7d3fbc8); GG(&a, b, c, d, x[9], S21, 0x21e1cde6); GG(&d, a, b, c, x[14], S22, 0xc33707d6); GG(&c, d, a, b, x[3], S23, 0xf4d50d87); GG(&b, c, d, a, x[8], S24, 0x455a14ed); GG(&a, b, c, d, x[13], S21, 0xa9e3e905); GG(&d, a, b, c, x[2], S22, 0xfcefa3f8); GG(&c, d, a, b, x[7], S23, 0x676f02d9); GG(&b, c, d, a, x[12], S24, 0x8d2a4c8a); // Round 3 HH(&a, b, c, d, x[5], S31, 0xfffa3942); HH(&d, a, b, c, x[8], S32, 0x8771f681); HH(&c, d, a, b, x[11], S33, 0x6d9d6122); HH(&b, c, d, a, x[14], S34, 0xfde5380c); HH(&a, b, c, d, x[1], S31, 0xa4beea44); HH(&d, a, b, c, x[4], S32, 0x4bdecfa9); HH(&c, d, a, b, x[7], S33, 0xf6bb4b60); HH(&b, c, d, a, x[10], S34, 0xbebfbc70); HH(&a, b, c, d, x[13], S31, 0x289b7ec6); HH(&d, a, b, c, x[0], S32, 0xeaa127fa); HH(&c, d, a, b, x[3], S33, 0xd4ef3085); HH(&b, c, d, a, x[6], S34, 0x4881d05); HH(&a, b, c, d, x[9], S31, 0xd9d4d039); HH(&d, a, b, c, x[12], S32, 0xe6db99e5); HH(&c, d, a, b, x[15], S33, 0x1fa27cf8); HH(&b, c, d, a, x[2], S34, 0xc4ac5665); // Round 4 II(&a, b, c, d, x[0], S41, 0xf4292244); II(&d, a, b, c, x[7], S42, 0x432aff97); II(&c, d, a, b, x[14], S43, 0xab9423a7); II(&b, c, d, a, x[5], S44, 0xfc93a039); II(&a, b, c, d, x[12], S41, 0x655b59c3); II(&d, a, b, c, x[3], S42, 0x8f0ccc92); II(&c, d, a, b, x[10], S43, 0xffeff47d); II(&b, c, d, a, x[1], S44, 0x85845dd1); II(&a, b, c, d, x[8], S41, 0x6fa87e4f); II(&d, a, b, c, x[15], S42, 0xfe2ce6e0); II(&c, d, a, b, x[6], S43, 0xa3014314); II(&b, c, d, a, x[13], S44, 0x4e0811a1); II(&a, b, c, d, x[4], S41, 0xf7537e82); II(&d, a, b, c, x[11], S42, 0xbd3af235); II(&c, d, a, b, x[2], S43, 0x2ad7d2bb); II(&b, c, d, a, x[9], S44, 0xeb86d391); hash_state[0] += a; hash_state[1] += b; hash_state[2] += c; hash_state[3] += d;}int main(){ UNINT word_pos, block_pos, counter, counter_update; string str ; Init();//初始化向量(A,B,C,D) cin >> str; counter = str.length();//计算输入消息的长度 counter_update = counter; block_pos = 0; //对输入消息进行分组,每组64bytes while (counter_update / 64>0){ str.copy(block, 64, 64 * block_pos);//将起始位置为64*j的后续64个字符拷贝到block数组 char64_to_word32(16);//将64个字符转换成16个字 //MD5 MD5_Transform(word_32); block_pos++; counter_update -= 64; } if (counter_update % 64 == 0){ newblock_length(counter); //MD5 MD5_Transform(word_32); } else{ //对剩余不足64bytes的分组进行处理 str.copy(block, counter_update, 64 * block_pos); //如果最后一个分组剩余不足4bytes空间来存放原始消息长度,则用0将该分组填充满,然后再新建一个分组存放消息长度 if (counter_update > 60){ //将block数组前面4k个字符转换成k个整型数 word_pos = char64_to_word32(counter_update / 4); //更新block最后剩余的字符数 counter_update -= 4 * word_pos; //根据剩余字符数模4的不同结果进行不同的处理 switch (counter_update){ case 0:{ break; } //如果最后剩余一个字符,则将其左移到最高8位,后面24位补0 case 1:{ word_32[word_pos] = (block[4 * word_pos] << 24) ^ 0x000000; word_pos++; break; } //如果最后剩余两个字符,则将其左移到最高16位,后面16位补0 case 2:{ word_32[word_pos] = (block[4 * word_pos] << 24) ^ (block[4 * word_pos + 1] << 16) ^ 0x0000; word_pos++; break; } //如果最后剩余三个字符,则将其左移到最高24位,后面8位补0 case 3:{ word_32[word_pos] = (block[4 * word_pos] << 24) ^ (block[4 * word_pos + 1] << 16) ^ (block[4 * word_pos + 2] << 8) ^ 0x00; word_pos++; break; } } //对word_36数组的剩余单元填充 while (word_pos < 16){ word_32[word_pos] = 0; word_pos++; } //MD5 MD5_Transform(word_32); //新建一个数组存放消息长度 newblock_length(counter); //MD5 MD5_Transform(word_32); } //如果最后一个分组剩余超过4bytes的空间,则用最后4bytes存放消息长度,其他位置用0填充 else{ word_pos = char64_to_word32(counter_update / 4); counter_update -= 4 * word_pos; switch (counter_update){ case 0:{ break; } case 1:{ word_32[word_pos] = (block[4 * word_pos] << 24) ^ 0x000000; word_pos++; break; } case 2:{ word_32[word_pos] = (block[4 * word_pos] << 24) ^ (block[4 * word_pos + 1] << 16) ^ 0x0000; word_pos++; break; } case 3:{ word_32[word_pos] = (block[4 * word_pos] << 24) ^ (block[4 * word_pos + 1] << 16) ^ (block[4 * word_pos + 2] << 8) ^ 0x00; word_pos++; break; } } while (word_pos < 15){ word_32[word_pos] = 0; word_pos++; } word_32[15] = counter; //MD5 MD5_Transform(word_32); } } cout << hex << hash_state[0] << endl; cout << hex << hash_state[1] << endl; cout << hex << hash_state[2] << endl; cout << hex << hash_state[3] << endl; system("pause"); return 0;}
字符
消息
长度
剩余
数组
分组
代码
最高
算法
处理
输入
C++
不同
薄弱
安全
不够
位置
单元
向量
基础
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
手冲咖啡和咖啡机区别
互联网科技
互联网佳科技有限公司
互联网金融监管科技数据
北京互联网科技
有木互联网科技
万达互联网科技
恒生科技互联网指数分析
济南和联互联网科技有限公司
哈尔滨新华互联网科技学院
阿里巴巴算科技企业还是互联网
互联网公司科技股
崇明区互联网教育科技诚信经营
中国航天科技大学国际工业互联网
每天都有哪些好的互联网科技
富国互联网科技002692
互联网科技年终奖
湖北辰鑫科技互联网
科技互联网公司两年变化
上海旺乐尼互联网科技有限公司
北京互联网络科技有限公司
上海致骋互联网科技
互联网科技大会案例
互联网与医疗科技
中国互联网十大科技股排名
高科技互联网发展前景如何
山东星卡互联网科技有限公司官网
广东工业互联网大赛深圳学泰科技
互联网安防科技感
互联网时代高科技布局