聊一聊MD5

MD5是什么

message-digest algorithm 5(信息-摘要算法)。经常说的“MD5加密”,就是它→信息-摘要算法。

在下载一下东西时,经常在一些压缩包属性里,看到md5值。而且这个下载页面,很可能会在某一个地方,写了一句,此文件的MD5值为XXXXXXXXX。这有什么作用呢?

白话白话:md5,其实就是一中算法。可以将一个字符串,或文件,或压缩包,执行md5后,就可以生成一个固定长度为128bit的串。这个串,基本上是唯一的。

所以,有人修过压缩包后,就会生成新的串,这时就可以拿网站提供的串和新生成的串对比,如果不同,那就是被人修过过了。

 

加密和摘要,是不一样的

加密后的消息是完整的;具有解密算法,得到原始数据;

摘要得到的消息是不完整的;通过摘要的数据,不能得到原始数据;

所以,当看到很多人说,md5,加密,解密的时候,呵呵一笑就好了。

QQ截图20150311162809

 

MD5长度

有人说md5,128位,32位,16位,到底md5多长?

md5的长度,默认为128bit,也就是128个0和1的二进制串。

这样表达是很不友好的。

所以将二进制转成了16进制,每4个bit表示一个16进制,

所以128/4 = 32 换成16进制表示后,为32位了。

QQ截图20150305111855

 

为什么网上还有md5是16位的呢?

网上有很多帖子,md5 32位 16位 加密 区别。

仔细观察admin生成的32位和16位的md5值……

查询结果:

md5(admin,32) = 21232f297a57a5a743894a0e4a801fc3

md5(admin,16) = 7a57a5a743894a0e

看出来了吧!

其实16位的长度,是从32位md5值来的。是将32位md5去掉前八位,去掉后八位得到的。

 

MD5的作用

①一致性检验,最上面那个例子

②数字签名,还是最上面那个例子。只是把md5看出了一个指纹,按了个手印说明独一无二了。

③安全访问认证,这个就是平时系统设计的问题了。

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

 

md5不能破解吗?

md5是不可逆的,也就是没有对应的算法,从生产的md5值逆向得到原始数据。

但是如果使用暴力破解,那就另说了。

 

md5是唯一的吗?

md5作为数据库中的主键可行吗?这就涉及到一个问题,md5值是唯一的吗?答案是,不唯一。

也就是一个原始数据,只对应一个md5值;

但是一个md5值,可能对应多个原始数据。

 

java中生成MD5的值

public class MD5Test {

	//main测试类
	public static void main(String[] args) {
		String result = getMD5("aaa");
		System.err.println(result);
	}

	/**
	 * 生成md5
	 * @param message
	 * @return
	 */
	public static String getMD5(String message) {
		String md5str = "";
		try {
			//1 创建一个提供信息摘要算法的对象,初始化为md5算法对象
			MessageDigest md = MessageDigest.getInstance("MD5");

			//2 将消息变成byte数组
			byte[] input = message.getBytes();

			//3 计算后获得字节数组,这就是那128位了
			byte[] buff = md.digest(input);

			//4 把数组每一字节(一个字节占八位)换成16进制连成md5字符串
			md5str = bytesToHex(buff);

		} catch (Exception e) {
			e.printStackTrace();
		}
		return md5str;
	}

	/**
	 * 二进制转十六进制
	 * @param bytes
	 * @return
	 */
	public static String bytesToHex(byte[] bytes) {
		StringBuffer md5str = new StringBuffer();
		//把数组每一字节换成16进制连成md5字符串
		int digital;
		for (int i = 0; i < bytes.length; i++) {
			 digital = bytes[i];

			if(digital < 0) {
				digital += 256;
			}
			if(digital < 16){
				md5str.append("0");
			}
			md5str.append(Integer.toHexString(digital));
		}
		return md5str.toString().toUpperCase();
	}
}

 

 

MD5的详细算法……自己搜吧。

17 comments

  • byte2hex的关键在于int digital = byte[i]; 这一句,我猜的是这里就是作者说的把128个字节按4个字节分组的根据,后面的容易理解,+=256无非是变为正数,<16则表示为正数但不够4位的情况(这种情况可以理解为按4个字节分组最后的部分,或者总字节不够128,则直接加0补齐)。个人理解,现在刚好要用MD5,看到大牛的文章,但是刚看的时候确实不好理解,应该基础不好吧。写点自己的理解,希望像我这样的菜鸟可以这样理解,当然这仅是个人愚见。

  • 等待答案

    有人吗?为什么MessageDigest的对象md不调用.update方法????????

  • 看了一些你的文章,觉得你是个挺有意思的人,哈哈,可惜没留个联系方式。

  • linglingjiu

    那里digital += 256;是什么意思呢?我是小白

  • 一杯清水因滴入一滴污水而变污浊,一杯污水却不会因一滴清水的存在而变清澈。

  • 不错,otn的byte2hex似乎更好理解:
    /*
    * Converts a byte to hex digit and writes to the supplied buffer
    */
    private void byte2hex(byte b, StringBuffer buf) {
    char[] hexChars = { ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’,
    ‘9’, ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’ };
    int high = ((b & 0xf0) >> 4);
    int low = (b & 0x0f);
    buf.append(hexChars[high]);
    buf.append(hexChars[low]);
    }

    /*
    * Converts a byte array to hex string
    */
    private String toHexString(byte[] block) {
    StringBuffer buf = new StringBuffer();

    int len = block.length;

    for (int i = 0; i < len; i++) {
    byte2hex(block[i], buf);
    if (i < len-1) {
    buf.append(":");
    }
    }
    return buf.toString();
    }

  • 我想明白了,楼主的方法真的不错

  • 谢谢

    • 冒昧请教下你那个二进制转十六进制函数的工作原理,我很难理解.
      先谢过了.

      • 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234
        例如上面是128位的 0、1代码串(上面的1234 只是标记第几位)
        每4位 当成一个组合 1234 ,比如这四位内容为 1001 那么变成16进制就是9了;如果是1101 那就是13了,也就是d了

      • 有个笨办法,就是先把26进制数转换为10进制数,再把得到的10进制数转化为16进制

  • Pingback: 聊一聊MD5 | 程序员之家

  • Pingback: MD5 | 勿忘初心

发表评论

电子邮件地址不会被公开。 必填项已用*标注