首页 > 编程知识 正文

什么是Md5,md5的缺点

时间:2023-05-03 16:55:06 阅读:210258 作者:3034

比较官方的解释大家可以百度,这里我说一下自己的理解。

一.作用:一般用于互联网一种数据的唯一性标识。

二.实体:本身是一个128位的0/1比特。一般被表示为16进制的字符串。4个比特位组成一个16进制字符,因此常常能见到的是(128/4=)32个16进制字符组成的字符串   4951 dd1c bff8 cbbe 4cd4 475c a939 fc8b,当然它实质是一种消息摘要算法

三.特点:

1.完全相同的一段数据,不论时间地点(加密算法相同的条件)加密出的32位的字符串完全相同。

2.加密过程本身就是一个有损的加密过程。因此几乎不能还原出原始数据。安全

补充:一般还原出原始数据都是使用碰撞的方式来还原。意思大概和穷举的意思一样,有足够多的原始数据量,世界上的所有数据用 1~n来表示,把1~n都用MD5计算一遍得1x~nx(x表示计算后得的数)。把1~n当成键值对,把1x~nx放入键值对当得到一个MD5字符串,通过值去找键,就知道是什么数据了。因为你本来就拥有数据,因此才能找到数据。但俊秀的棉花糖没有原始数据时,想通过128比特的玩意去恢复大于128比特的数据本身就是玩笑,数据量都不一样,至于原理有兴趣的朋友可以研究研究信息论。不想研究的可以回想回想之前学的香农公式。再从这一点去研究。又有大的世界。

3.散列能力巨强。安全

MD5工具类代码:

import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.security.MessageDigest;public class MD5Utils {public static String getStringMD5(String str) {try {MessageDigest digest = MessageDigest.getInstance("MD5");return new String(encode(digest.digest(str.getBytes())));} catch (Exception e) {throw new RuntimeException("md5 digest fail:", e);}}public static String getFileMD5(File file) {FileInputStream in = null;try {MessageDigest digest = MessageDigest.getInstance("MD5");if (!file.isFile()) {throw new RuntimeException("md5 digest fail: file not exists!");}byte buffer[] = new byte[1024];int len;in = new FileInputStream(file);while ((len = in.read(buffer, 0, 1024)) != -1) {digest.update(buffer, 0, len);}return new String(encode(digest.digest()));} catch (Exception e) {throw new RuntimeException("md5 digest fail:", e);} finally {if (in != null) {try {in.close();} catch (IOException e) {}}}}private static final char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };public static char[] encode(byte[] bytes) {final int nBytes = bytes.length;char[] result = new char[2 * nBytes];int j = 0;for (int i = 0; i < nBytes; i++) {// Char for top 4 bitsresult[j++] = HEX[(0xF0 & bytes[i]) >>> 4];// Bottom 4result[j++] = HEX[(0x0F & bytes[i])];}return result;}}

当以上代码加密文件时。即使文件名不同,只要文件内容相同,加密出的MD5完全一致:

测试:

加密一个图片:

 

import java.io.File;import utils.MD5Utils;public class MD5Test {public static void main(String[] args) {//MD5第一次运算 4951dd1cbff8cbbe4cd4475ca939fc8bSystem.out.println(MD5Utils.getFileMD5(new File("C:\Users\anxiaopei\Desktop\index.jpg")));//MD5第二次运算System.out.println(MD5Utils.getFileMD5(new File("C:\Users\anxiaopei\Desktop\index.jpg")));//MD5第三次运算System.out.println(MD5Utils.getFileMD5(new File("C:\Users\anxiaopei\Desktop\index文件名真的不同!.jpg")));//MD5第四次运算System.out.println(MD5Utils.getFileMD5(new File("C:\Users\anxiaopei\Desktop\index文件名真的不同!.jpg")));//1的MD5数为System.out.println(MD5Utils.getStringMD5("1"));}}

结果:

对字符串1的加密,大家使用我的代码在你的机器上做了MD5运算后一定也能得到 c4ca4238a0b923820dcc509a6f75849b

第一次与第二次加密证明了,对相同的文件 不同的时间加密的出相同的MD5

第三四次加密与前两次相同证明在,文件的副本,哪怕文件名不一样,只要文件内容相同,加密的MD5也是相同的。

现在我们来做一个有趣的事。

把图片以记事本打开 更改其中一个字符。再次加密图片(改了一个字符,图片也会打不开,不要使用重要图片做测试),这次我们更改文件的副本里的一个字符。删掉添加更改都可以,随意。这次我就只改一个字符,把最后一个字符“ ? ”删掉。

删掉“?”后我的副本都不能预览了。

 用MD5运算后,可以看到第二行与第三行结果完全不一样,证明了它散列的能力。巨强!可以说百分之零点几的的差别也会导致MD5完全不一样。因此再不考虑碰撞的可能性下,只要两个数据的MD5相同,那我们可以认为这两个数据完全相同。

补充:什么是碰撞?:https://blog.csdn.net/qq_29519041/article/details/84404223

 

说了这么多知道了它唯一标识的能力很强。

既然他的唯一标识能力这么强。

那有个使用场景就是,用来作为文件的唯一标识。比如文件上传时,哪怕你的文件名不一样,经过MD5一下,服务器对比一下存在服务器的文件的MD5码表。就知道你上传的这个文件是否服务器已经存在,qq的秒传也是使用这个方法(我猜的)发现服务器有这个文件后,直接把服务器那个文件传给你要传的人。如果你是上传文件给服务器,那你也得到一个访问服务器那个文件的权限。因为服务器知道你上传的文件就是服务器存着的那个文件,这就是秒传的精髓。当然具体实现消息摘要算法的方式也许会不一样。也许是md其他什么的。

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。