MD5(Message-Digest Algorithm 5)是一种被广泛使用的密码散列函数,是一种不可逆的加密算法,该算法可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5 由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1991年公布,用以取代 MD4 算法。这套算法的程序在 RFC 1321 标准中被加以规范。1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如 SHA-2。2004年,证实MD5 算法无法防止碰撞(collision),因此不适用于安全性认证,如 SSL 公开密钥认证或是数字签名等用途。
MD5 算法的应用非常广泛,包括但不限于:
文件完整性校验:下载文件时,可以提供文件的 MD5 值,用户下载完文件后,用 MD5 工具可以计算出下载文件的 MD5 值,通过对比就可以校验文件的完整性。
密码存储:在存储用户密码时,通常不会存储明文密码,而是存储密码的 MD5 值。当然,为了安全,现在更推荐使用 SHA-256 等更安全的算法。
数字签名:虽然 MD5 算法不能防止碰撞,但仍可用于数字签名,因为签名通常还会结合其他机制(如私钥加密)来保证安全性。
然而,由于 MD5 算法的安全漏洞,现在已经不再推荐用于安全性要求较高的场合。对于需要高度安全性的应用,建议使用 SHA-256 或更高级的加密算法。
1、使用 MD5 消息摘要
消息摘要是密码学中的一个重要概念,它能够将任意长度的数据转换为固定长度的摘要值,这个摘要值通常是一个较短的字符串。消息摘要算法,也被称作散列算法,是一种单向加密算法,具有不可逆性,即无法从摘要值恢复出原始数据。
消息摘要的特点:
- 固定长度:无论输入的消息有多长,计算出来的消息摘要的长度总是固定的,如MD5的固定长度为128位(16字节)。
- 唯一性:只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出。
- 不可逆性:消息摘要是单向的,无法从摘要值恢复出原始数据。
- 快速计算:消息摘要算法通常能够快速地计算出摘要值,适用于大数据量的处理。
【实例】使用 MD5 算法,生成消息摘要。
(1)创建 MD5Util 类(MD5消息摘要工具类)。
package com.pjb.util;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
/**
* MD5消息摘要工具类
* @author pan_junbiao
**/
public class MD5Util
{
//字符编码
private final static String charsetName = StandardCharsets.UTF_8.name();
//算法
private final static String algorithm = "MD5";
/**
* MD5消息摘要
*/
public static String encodeMD5(String data) throws Exception
{
//创建消息摘要对象
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
//执行消息摘要算法
byte[] digestBytes = messageDigest.digest(data.getBytes(charsetName));
//将指定byte数组转换成16进制字符串,否则输出的结果是一串乱码
String result = byteToHexString(digestBytes);
return result;
}
/**
* 将指定byte数组转换成16进制字符串
*/
private static String byteToHexString(byte[] b) {
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < b.length; i++) {
//把密文转换成16进制
String hex = Integer.toHexString(b[i] & 0xFF);
//如果密文的长度只有1位,则需要再高位进行补0
if (hex.length() == 1) {
hex = '0' + hex;
}
//拼接字符与转大写字母
hexString.append(hex.toUpperCase());
}
return hexString.toString();
}
}
(2)使用 MD5 算法,生成消息摘要。
/**
* MD5消息摘要
*/
@Test
public void testMD5() throws Exception
{
String data = "您好,欢迎访问 pan_junbiao的博客";
String encodeMD5 = MD5Util.encodeMD5(data);
//打印结果
System.out.println("原始数据:" + data);
System.out.println("MD5消息摘要:" + encodeMD5);
}
执行结果:
2、密码的加密与校验
实际开发应用中,存储用户密码时,通常不会存储明文密码,而是存储密码的 MD5 值。在身份验证过程中,用户通常不会直接发送密码,而是发送密码的摘要值。服务器通过相同的摘要算法计算出的摘要值与数据库中存储的摘要值进行比对,从而验证用户身份。这种方法即使在数据被截获的情况下,也能够保护密码的安全。
【实例】使用 MD5 算法,实现密码的加密与校验。
/**
* 密码的加密与校验
*/
@Test
public void createPasswordMD5() throws Exception
{
String password = "123456"; //原始密码
String salt = "ABCDEFG"; //盐
//使用MD5算法,加密密码(密码格式:原始密码 + 盐)
String passwordMD5 = MD5Util.encodeMD5(password + salt);
//打印结果
System.out.println("原始密码:" + password);
System.out.println("MD5密码加密:" + passwordMD5);
}
执行结果: