C++实现MD5
发表于:2025-01-20 作者:千家信息网编辑
千家信息网最后更新 2025年01月20日,以下代码是自己用C++语言对MD5算法的实现,编程工具是VC2013。虽然代码的封装性、安全性和效率远远比不上RFC文档中的标准实现或者OpenSSL的源码(这些代码研究了很久依旧没看懂,它们的效率虽
千家信息网最后更新 2025年01月20日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安全错误
数据库的锁怎样保障安全
新加坡服务器有没有云顶手游
服务器内存 b360
申请信用卡服务器繁忙
信息化网络安全保障体系建设
数据库的tns
敏捷软件开发概念图
个性化网络技术服务
百度文库怎么绑定学校数据库
it软件开发有用吗
网络安全法方案
网络安全的六大职能
四川佳缘网络安全有限公司的电话
韩天明的服务器叫什么名字
学生系统数据库设计
爬大众点评数据库
微软浏览器显示代理服务器有问题
软件开发评审线上化
360皮肤软件开发
软件开发岗位工作描述
软件开发最速成的
江苏数据库日志审计代理商
xmanager服务器响应慢
局机关网络安全责任书
学软件开发好还是学财经好
网吧没有服务器怎么清理
软件开发策划下载
无线网络技术教程第三版期末
软件开发用啥做笔记
逆战迷城守护者是服务器么
mysql数据库异地缓存