MD5 加密算法详解

  • 一、概念
  • 二、算法原理
    • 2.1、MD5(32)、MD5(16)
    • 2.2、算法 4步流程
  • 三、 其他
    • 3.1、作用
    • 3.2、MD5可以作为数据库主键,唯一吗?
    • 3.3、测试源码

一、概念

MD5算法是单向散列算法的一种。单向散列算法也称为HASH算法,是一种将任意长度的信息压缩至某一固定长度(称之为消息摘要)的函数(该压缩过程不可逆)。在MD5算法中,这个摘要是指将任意数据映射成一个128位长的摘要信息。并且其是不可逆的,即从摘要信息无法反向推演中原文,在演算过程中,原文的内容也是有丢失的。

并非说md5不能破解。MD5破解可以参考王晓云教授的《MD5破解》论文

因为MD5算法最终生成的是一个128位长的数据,从原理上说,有2^128种可能,这是一个非常巨大的数据,约等于3.4乘10的38次方,虽然这个是个天文数字,但是世界上可以进行加密的数据原则上说是无限的,因此是可能存在不同的内容经过MD5加密后得到同样的摘要信息,但这个碰中的概率非常小。可用于数字签名、信息完整性检查等用途;

1、对于需要高度安全性的数据,一般改用其他算法,如SHA-2。MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是高要求的数字签名等用途。
2、常见的散列算法还有SHA、RIPE-MD、HAVAL、N-Hash等

二、算法原理

2.1、MD5(32)、MD5(16)

MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
将这128 位用十六进制表示便是常见的32 字符的MD5 码,而所谓的16 字符的MD5 码,其实是这32 字符中间的16 个字符。

MD5(123456,32) = e10adc3949ba59abbe56e057f20f883e
MD5(123456,16) = 49ba59abbe56e057

2.2、算法 4步流程

MD5 算法将输入的信息进行分组,每组512 位(64个 字节),顺序处理完所有分组后输出128 位结果。
在每一组消息的处理中,都要进行4 轮、每轮16 步、总计64 步的处理。其中每步计算中含一次左循环移位,每一步结束时将计算结果进行一次右循环移位。详见下方流程。

第1步:进行数据填充整理

这一步是对要加密的数据进行填充和整理,将要加密的二进制数据对512取模,得到的结果如果不够448位,则进行补足,补足的方式是第1位填充1,后面全部填充0。

为啥是448位呢? 在数据读取时,会有一个结束标识位。如同c中的字符串,有一个\0的结束标识;
将需加密的信件信息(如一份文件)分次读取到缓冲区中,一次最好读取64*n 个字节,这样就是n 组,方便处理。那么此时,对信息进行填充,使其字节数除以64 时余数为56,其一个结束标识符就是8字节;如,一个消息为64n 倍数字节,则最后一次读取0 字节(结束标识),据本规则将填充56 字节(448bit)。

第2步:记录数据长度

经过第一步整理完成后的数据的位数可以表示为N*512+448,再向其后追加64位用来存储数据的长度,比如数据的长度为16字节,则用10000来填充后64位。这一步做完后,数据的位数将变成(N+1)*512。

第3步:以标准的幻数作为输入

MD5的实现需要每512个字节进行一次处理,后一次处理的输入为前一次处理的输出,因此,在循环处理开始之前,需要拿4个标准数作为输入,它们分别是:

unsigned int A=0x67452301,B=0xefcdab89,C=0x98badcfe,D=0x10325476;

第4步:进行N轮循环处理,将最后的结果输出

这一步重要的是每一轮的处理算法,每一轮处理也要循环64次,这64次循环被分为4各组,每16次循环为一组,每组循环使用不同的逻辑处理函数,处理完成后,将输出作为输入进入下一轮循环。

通过上面的标准128bit 输入,参与每组512bit 计算,得到一个新的128值,接着参与下一轮循环运算,最终得到一个128位的值;
具体运算:
这里用到4 个逻辑函数F,G,H,I,分别对应4 轮运算,它们将参与运算。(4轮16步)
第一轮逻辑函数:F(b,c,d)=(b&c)|((~b)&d) 参与第一轮的16 步运算 (b,c,d均为32位数)
第二轮逻辑函数:G(b,c,d)=(b&d)|(c&(~d)) 参与第二轮的16 步运算
第三轮逻辑函数:H(b,c,d)= bcd 参与第三轮的16 步运算
第四轮逻辑函数:I(b,c,d)= c^(b|(~d)) 参与第四轮的16 步运算
再引入一个移位函数MOVE(X,n),它将整型变量X 左循环移n 位,如变量X 为32 位,则MOVE(X,n)= (X
<< n) | (X >> (32 - n))。

三、 其他

3.1、作用

  • 一致性检验,如大文件上传时,需要对文件一致性校验;
  • 数字签名,还是最上面那个例子。只是把md5看出了一个指纹,按了个手印说明独一无二了;
  • 安全访问认证等;

如:在用户注册时,会将密码进行md5加密,存到数据库中。这样可以防止那些可以看到数据库数据的人,恶意操作了。

3.2、MD5可以作为数据库主键,唯一吗?

前面也讲了md5无法避免碰撞,那么md5值就不唯一。
也就是一个原始数据,只对应一个md5值;但是一个md5值,可能对应多个原始数据。

3.3、测试源码

package com.xuecheng.test.md5test;import org.springframework.util.DigestUtils;public class MD5 {/**四个链接变量*/private final int A=0x67452301;private final int B=0xefcdab89;private final int C=0x98badcfe;private final int D=0x10325476;/**ABCD的临时变量*/private int Atemp,Btemp,Ctemp,Dtemp;/**常量ti*公式:floor(abs(sin(i+1))×(2pow32)*/private final int K[]={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};/**向左位移数,计算方法未知*/private final int s[]={7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21};/**初始化函数*/private void init(){Atemp=A;Btemp=B;Ctemp=C;Dtemp=D;}/**移动一定位数*/private int  shift(int a,int s){return(a<<s)|(a>>>(32-s));//右移的时候,高位一定要补零,而不是补充符号位}/**主循环*/private void MainLoop(int M[]){int F,g;int a=Atemp;int b=Btemp;int c=Ctemp;int d=Dtemp;for(int i = 0; i < 64; i ++){if(i<16){F=(b&c)|((~b)&d);g=i;}else if(i<32){F=(d&b)|((~d)&c);g=(5*i+1)%16;}else if(i<48){F=b^c^d;g=(3*i+5)%16;}else{F=c^(b|(~d));g=(7*i)%16;}int tmp=d;d=c;c=b;b=b+shift(a+F+K[i]+M[g],s[i]);a=tmp;}Atemp=a+Atemp;Btemp=b+Btemp;Ctemp=c+Ctemp;Dtemp=d+Dtemp;}/**填充函数*处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64)*填充方式为先加一个0,其它位补零*最后加上64位的原来长度*/private int[] add(String str){int num=((str.length()+8)/64)+1;//以512位,64个字节为一组int strByte[]=new int[num*16];//64/4=16,所以有16个整数for(int i=0;i<num*16;i++){//全部初始化0strByte[i]=0;}int    i;for(i=0;i<str.length();i++){strByte[i>>2]|=str.charAt(i)<<((i%4)*8);//一个整数存储四个字节,小端序}strByte[i>>2]|=0x80<<((i%4)*8);//尾部添加1/**添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位*/strByte[num*16-2]=str.length()*8;return strByte;}/**调用函数*/public String getMD5(String source){init();int strByte[]=add(source);for(int i=0;i<strByte.length/16;i++){int num[]=new int[16];for(int j=0;j<16;j++){num[j]=strByte[i*16+j];}MainLoop(num);}return changeHex(Atemp)+changeHex(Btemp)+changeHex(Ctemp)+changeHex(Dtemp);}/**整数变成16进制字符串*/private String changeHex(int a){String str="";for(int i=0;i<4;i++){str+=String.format("%2s", Integer.toHexString(((a>>i*8)%(1<<8))&0xff)).replace(' ', '0');}return str;}/**单例*/private static MD5 instance;public static MD5 getInstance(){if(instance==null){instance=new MD5();}return instance;}private MD5(){};public static void main(String[] args){String str=MD5.getInstance().getMD5("123");System.out.println(str);String s1 = DigestUtils.md5DigestAsHex("123".getBytes());System.out.println(s1);}}

参考资料

https://cloud.tencent.com/developer/article/1402024
https://my.oschina.net/u/3352105/blog/875927
https://www.cnblogs.com/orangebook/p/3558334.html

MD5 加密算法详解相关推荐

  1. 密码学:RSA加密算法详解

    概述 本文旨在说明RSA加密算法的原理及实现,而其相关的数学部分的证明则不是本文内容. 版权说明 著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者:Q-WHai 发表日期: ...

  2. MD5算法详解及实现(C语言)

    其他现代密码学算法详解及实现见专栏合集~ MD5算法 算法过程 (i)消息填充 首先填充消息,使它的长度比512的整数倍少64位(这64位用来记录原数据长度).填充的内容由一个1和后续的0组成.必须进 ...

  3. openssl_sign() 语法+RSA公私钥加密解密,非对称加密算法详解

    其实有时候觉得写博客好烦,就个函数就开篇博客.很小的意见事情而已,知道的人看来多取一举,或者说没什么必要,浪费时间,不知道的人就会很郁闷.技术就是这样的,懂的人觉得真的很简单啊,不知道的人真的好难.. ...

  4. java的rsa加密_java实现的RSA加密算法详解

    本文实例讲述了java实现的RSA加密算法.分享给大家供大家参考,具体如下: 一.什么是非对称加密 1.加密的密钥与加密的密钥不相同,这样的加密算法称之为非对称加密 2.密钥分为:公钥,私钥 公钥:可 ...

  5. RSA加密算法详解及例题

    这是我自己在学习RSA加密算法的时候自己整理的笔记,如需转载请注明出处 RSA加密算法 我这里就不对RSA的发明背景做介绍了,你只要知道RSA加密算法是非常非常重要的加密算法,放在现在的时代亦是如此. ...

  6. rsa加密算法java实例,java实现的RSA加密算法详解

    本文实例讲述了java实现的RSA加密算法.分享给大家供大家参考,具体如下: 一.什么是非对称加密 1.加密的密钥与加密的密钥不相同,这样的加密算法称之为非对称加密 2.密钥分为:公钥,私钥 公钥:可 ...

  7. RSA加密算法详解以及RSA在laravel中的应用

    最近做APP,由于刚开始开发,所以关于数据传输之间的加密部分还没做.在BOSS的要求下,准备给APP的接口加上RSA加密.先测试一个小demo. 一.使用场景 APP接口数据部分的加密.特别是设计到账 ...

  8. c# php加解密,PHP和C#可共用的可逆加密算法详解

    在一些项目中要求在php中生成加密,然后在asp.net中接受过来的密码再解密,下面和大家分享一个PHP与asp.net C#可共用的可逆加密算法,感兴趣的可以参考参考. php加密算法: class ...

  9. oracle解析md5,Oracle中的MD5加密详解

    一.技术点 1. DBMS_OBFUSCATION_TOOLKIT.MD5 DBMS_OBFUSCATION_TOOLKIT.MD5是MD5编码的数据包函数,但偶在使用select DBMS_OBFU ...

  10. php的md5(),php MD5加密详解

    PHP crypt()函数可以完成基本的加密功能: string crypt (string input_string [, string salt]) 这一函数完成被称作单向加密的功能,也就是说,它 ...

最新文章

  1. Task03:青少年软件编程(Scratch)等级考试模拟卷(二级)
  2. python简单计算器异常处理_Python实现的简单计算器
  3. 小程序 数据缓存
  4. BETA、RC、ALPHA、Release、GA 等版本号的意义
  5. Java技术:SpringBoot实现邮件发送功能
  6. 在编码中熟练使用JDK文档
  7. matlab创建nc文件怎么打开,MATLAB打开nc文件并读取nc文件数据
  8. CNN提取文本特征,融合PMF模型实现推荐系统
  9. 苹果Safari中保存的密码如何导入Chrome浏览器?
  10. 神经网络的直观解释相关文档
  11. 线性代数学习之坐标转换和线性变换
  12. 30分钟一部动画短片!从MMD入门3D世界,边玩边学的3D教程!(一)“MMD快速入门教程CSDN”
  13. 电路交换、报文交换、分组交换各自的特点
  14. 公司计算机程序员英语怎么说,计算机程序员英文求职信范文模板
  15. 记录一下学习EFCore中的基础知识
  16. 假如明天失业了,我该去哪里
  17. 《东周列国志》第八十五回 乐羊子怒啜中山羹 西门豹乔送河伯妇
  18. 支付宝网商贷是雪中送炭么?
  19. 腾讯会议发布录屏工具“会记”,让云端视频协作随用随录、随享随看
  20. 解决openwrt opkg内核版本不匹配问题

热门文章

  1. SQL Server 2008安装图解教程
  2. python可以破解网站吗_python变相破解校园网 - 『编程语言区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn...
  3. 人工神经网络的算法原理,人工神经网络算法步骤
  4. 怎么将几张pdf合并成一张_如何将多个PDF合并成一个PDF?PDF文档合并成单个的方法...
  5. 深度学习与计算机视觉教程(8) | 常见深度学习框架介绍(CV通关指南·完结)
  6. ug二次开发python_UG/NX二次开发入门指导
  7. 3DMAX卸载/完美解决安装失败/如何彻底卸载清除干净3DMAX各种残留注册表和文件的方法
  8. yum安装wget命令
  9. C语言全局变量和数组的应用
  10. 详解Java 堆排序