热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MD5的自己的理解

这周我boss让我做个MD5的验证算法,这对我一个刚进来的菜鸟来说是要下点功夫,经过不断的百度,谷歌对MD5有个初步的了解什么是MD5算法呢?我理解的是,MD5算法将任意长度的数据(最终

这周我boss让我做个MD5的验证算法,这对我一个刚进来的菜鸟来说是要下点功夫,经过不断的百度,谷歌对MD5有个初步的了解


什么是MD5算法呢?我理解的是,MD5算法将任意长度的数据(最终都会转化为字符串),转换成一个固定大小(32位或者是16位)的加密数据。


而且这些加密后的数据是不可逆的,也就是说,你拿到加密后的数据后,想通过逆运算来获取原来的数据是不可能的。


那怎么办呢,只有通过拿到和原来一样的数据将他也转化为MD5码,并与之比较才知道原数据是什么。


这有什么用呢?我猜是这样的,假设背景是两军交战,指挥部要和前方进行通信,但是又怕发送内容被敌方截获,所以双方约定一个密码本,然后将要发送的内容经过多个MD5值加密,然后另一方通过密码本和MD5码进行核对,来确定发送的内容。(如果不懂请看电影《风声》)


好了废话了这么多我来说下MD5算法的实现吧。我的MD5算法如下

#include
#include
#include


#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 RL(x, y) (((x) <<(y)) | ((x) >> (32 - (y))))  //x向左循环移y位#define PP(x) (x<<24)|((x<<8)&0xff0000)|((x>>8)&0xff00)|(x>>24)  //将x高低位互换,例如PP(aabbccdd)=ddccbbaa#define FF(a, b, c, d, x, s, ac) a = b + (RL((a + F(b,c,d) + x + ac),s))#define GG(a, b, c, d, x, s, ac) a = b + (RL((a + G(b,c,d) + x + ac),s))#define HH(a, b, c, d, x, s, ac) a = b + (RL((a + H(b,c,d) + x + ac),s))#define II(a, b, c, d, x, s, ac) a = b + (RL((a + I(b,c,d) + x + ac),s))unsigned A,B,C,D,a,b,c,d,i,len,flen[2],x[16];   //i临时变量,len文件长,flen[2]为64位二进制表示的文件初始长度char filename[200];   //文件名FILE *fp;
 
 
void md5(){                 //MD5核心算法,供64轮  a=A,b=B,c=C,d=D;  /**//* Round 1 */  FF (a, b, c, d, x[ 0],  7, 0xd76aa478); /**//* 1 */  FF (d, a, b, c, x[ 1], 12, 0xe8c7b756); /**//* 2 */  FF (c, d, a, b, x[ 2], 17, 0x242070db); /**//* 3 */  FF (b, c, d, a, x[ 3], 22, 0xc1bdceee); /**//* 4 */  FF (a, b, c, d, x[ 4],  7, 0xf57c0faf); /**//* 5 */  FF (d, a, b, c, x[ 5], 12, 0x4787c62a); /**//* 6 */  FF (c, d, a, b, x[ 6], 17, 0xa8304613); /**//* 7 */  FF (b, c, d, a, x[ 7], 22, 0xfd469501); /**//* 8 */  FF (a, b, c, d, x[ 8],  7, 0x698098d8); /**//* 9 */  FF (d, a, b, c, x[ 9], 12, 0x8b44f7af); /**//* 10 */  FF (c, d, a, b, x[10], 17, 0xffff5bb1); /**//* 11 */  FF (b, c, d, a, x[11], 22, 0x895cd7be); /**//* 12 */  FF (a, b, c, d, x[12],  7, 0x6b901122); /**//* 13 */  FF (d, a, b, c, x[13], 12, 0xfd987193); /**//* 14 */  FF (c, d, a, b, x[14], 17, 0xa679438e); /**//* 15 */  FF (b, c, d, a, x[15], 22, 0x49b40821); /**//* 16 */ /**//* Round 2 */  GG (a, b, c, d, x[ 1],  5, 0xf61e2562); /**//* 17 */  GG (d, a, b, c, x[ 6],  9, 0xc040b340); /**//* 18 */  GG (c, d, a, b, x[11], 14, 0x265e5a51); /**//* 19 */  GG (b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /**//* 20 */  GG (a, b, c, d, x[ 5],  5, 0xd62f105d); /**//* 21 */  GG (d, a, b, c, x[10],  9, 0x02441453); /**//* 22 */  GG (c, d, a, b, x[15], 14, 0xd8a1e681); /**//* 23 */  GG (b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /**//* 24 */  GG (a, b, c, d, x[ 9],  5, 0x21e1cde6); /**//* 25 */  GG (d, a, b, c, x[14],  9, 0xc33707d6); /**//* 26 */  GG (c, d, a, b, x[ 3], 14, 0xf4d50d87); /**//* 27 */  GG (b, c, d, a, x[ 8], 20, 0x455a14ed); /**//* 28 */  GG (a, b, c, d, x[13],  5, 0xa9e3e905); /**//* 29 */  GG (d, a, b, c, x[ 2],  9, 0xfcefa3f8); /**//* 30 */  GG (c, d, a, b, x[ 7], 14, 0x676f02d9); /**//* 31 */  GG (b, c, d, a, x[12], 20, 0x8d2a4c8a); /**//* 32 */  /**//* Round 3 */  HH (a, b, c, d, x[ 5],  4, 0xfffa3942); /**//* 33 */  HH (d, a, b, c, x[ 8], 11, 0x8771f681); /**//* 34 */  HH (c, d, a, b, x[11], 16, 0x6d9d6122); /**//* 35 */  HH (b, c, d, a, x[14], 23, 0xfde5380c); /**//* 36 */  HH (a, b, c, d, x[ 1],  4, 0xa4beea44); /**//* 37 */  HH (d, a, b, c, x[ 4], 11, 0x4bdecfa9); /**//* 38 */  HH (c, d, a, b, x[ 7], 16, 0xf6bb4b60); /**//* 39 */  HH (b, c, d, a, x[10], 23, 0xbebfbc70); /**//* 40 */  HH (a, b, c, d, x[13],  4, 0x289b7ec6); /**//* 41 */  HH (d, a, b, c, x[ 0], 11, 0xeaa127fa); /**//* 42 */  HH (c, d, a, b, x[ 3], 16, 0xd4ef3085); /**//* 43 */  HH (b, c, d, a, x[ 6], 23, 0x04881d05); /**//* 44 */  HH (a, b, c, d, x[ 9],  4, 0xd9d4d039); /**//* 45 */  HH (d, a, b, c, x[12], 11, 0xe6db99e5); /**//* 46 */  HH (c, d, a, b, x[15], 16, 0x1fa27cf8); /**//* 47 */  HH (b, c, d, a, x[ 2], 23, 0xc4ac5665); /**//* 48 */	/**//* Round 4 */  II (a, b, c, d, x[ 0],  6, 0xf4292244); /**//* 49 */  II (d, a, b, c, x[ 7], 10, 0x432aff97); /**//* 50 */  II (c, d, a, b, x[14], 15, 0xab9423a7); /**//* 51 */  II (b, c, d, a, x[ 5], 21, 0xfc93a039); /**//* 52 */  II (a, b, c, d, x[12],  6, 0x655b59c3); /**//* 53 */  II (d, a, b, c, x[ 3], 10, 0x8f0ccc92); /**//* 54 */  II (c, d, a, b, x[10], 15, 0xffeff47d); /**//* 55 */  II (b, c, d, a, x[ 1], 21, 0x85845dd1); /**//* 56 */  II (a, b, c, d, x[ 8],  6, 0x6fa87e4f); /**//* 57 */  II (d, a, b, c, x[15], 10, 0xfe2ce6e0); /**//* 58 */  II (c, d, a, b, x[ 6], 15, 0xa3014314); /**//* 59 */  II (b, c, d, a, x[13], 21, 0x4e0811a1); /**//* 60 */  II (a, b, c, d, x[ 4],  6, 0xf7537e82); /**//* 61 */  II (d, a, b, c, x[11], 10, 0xbd3af235); /**//* 62 */  II (c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /**//* 63 */  II (b, c, d, a, x[ 9], 21, 0xeb86d391); /**//* 64 */  A += a;  B += b;  C += c;  D += d;}void getmd5(char *name, char* out){    FILE *fp;    if (name[0]==34) name[strlen(name)-1]=0,strcpy(name,name+1);  //处理文件的双引号,消除双引号    if (!(fp=fopen(name,"rb"))) {		printf("Can not open this file!\n");		}  //以二进制打开文件    fseek(fp, 0, SEEK_END);  //文件指针转到文件末尾    if((len=ftell(fp))==-1) {printf("Sorry! Can not calculate files which larger than 2 GB!\n");fclose(fp);}  //ftell函数返回long,最大为2GB,超出返回-1    rewind(fp);  //文件指针复位到文件头    A=0x67452301,B=0xefcdab89,C=0x98badcfe,D=0x10325476; //初始化链接变量    flen[1]=len/0x20000000;     //flen单位是bit    flen[0]=(len%0x20000000)*8;    memset(x,0,64);   //初始化x数组为0    fread(&x,4,16,fp);  //以4字节为一组,读取16组数据    for(i=0;i55) md5(),memset(x,0,64);    memcpy(x+14,flen,8);    //文件末尾加入原文件的bit长度    md5();    fclose(fp);    sprintf(out,"%08x%08x%08x%08x",PP(A),PP(B),PP(C),PP(D)); //高低位逆反输出到字符串out中} 
以上代码相当于提供了一个基于文件的MD5算法的API,只要输入文件名就可以获取到相应的MD5码了。


输出的MD5码,在第二个参数out中。


MD5码的值只与文件中的数据有关(保存的字符串)而与文件的名字,文件的日期无关,一开始不懂的时候,我还很丢脸的问了知乎。结果当然是惨不忍睹

,详情请看 
 http://www.zhihu.com/question/30168251/noti-answers?group_id=579646196239368192 
 


好了,我先写到这里,我还去研究下另外一种实现方法,我感觉他比这个强大,http://blog.csdn.net/flydream0/article/details/7049322这位同学写的我就先mark了。好了睡了。。。


推荐阅读
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文介绍了在使用Python中的aiohttp模块模拟服务器时出现的连接失败问题,并提供了相应的解决方法。文章中详细说明了出错的代码以及相关的软件版本和环境信息,同时也提到了相关的警告信息和函数的替代方案。通过阅读本文,读者可以了解到如何解决Python连接服务器失败的问题,并对aiohttp模块有更深入的了解。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
author-avatar
Me小盆友_128
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有