MD5是一种广泛使用的散列函数,它将输入数据不可逆地映射成固定长度的哈希值,通常是128位的二进制数。在计算机科学中,哈希函数(也叫散列函数)是将任意数量的数据映射到固定数量的数据的函数,而MD5就是其中一种。本文主要从以下几个方面进行详细阐述。
一、MD5加密算法原理
MD5加密算法是由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)在1991年提出,它基于消息摘要算法,能够快速将任意长度的字节序列映射为一个128位的哈希值。MD5加密算法的基本原理如下:
1、填充数据:首先在数据末位填充一位1,然后在末尾填充足够的0,使得填充前的长度之与512同余448,这里的512是MD5加密算法的一个固定参数。
public class MD5 {
private static final String SPLIT_STR = "'5A827999' + F(a,b,c,d) + X[k] + T[i]";
private static final Integer[] R = {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};
// T是用正弦函数生成的一个表,其中k表示第k个元素的值
private static final Integer[] T = new Integer[64];
static {
for (int i = 0; i < 64; i++) {
double d = Math.abs(Math.sin(i + 1));
T[i] = (int) (d * (1L << 32));
}
}
// ...
}
2、划分数据:将填充后的数据划分为多个512位的块,然后对每个块进行加密操作。
3、初始化变量:对每个块进行加密操作之前,需要先对MD5加密算法用到的四个变量进行初始化,这四个变量的初始值为固定值。
4、加密:将每个块进行加密操作,每个块的加密都是基于上一个块的加密结果。最终的加密结果即为MD5值。
二、MD5加密算法应用场景
MD5加密算法在计算机领域中有着广泛的应用场景,下面介绍三个典型的应用场景。
1、密码存储
MD5加密算法可以用于密码的存储,通过将用户输入的明文密码进行MD5加密,将加密后的结果存储到数据库中。当用户下一次登录时,再将输入的密码进行MD5加密,并与数据库中的密文密码进行比对,从而达到验证用户身份的目的。
public class PasswordUtils {
/**
* 对字符串进行MD5加密
*
* @param src 待加密的字符串
* @return 加密后的字符串
*/
public static String encrypt(String src) {
MessageDigest md5;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
byte[] byteArray = src.getBytes(StandardCharsets.UTF_8);
byte[] md5Bytes = md5.digest(byteArray);
StringBuilder hexValue = new StringBuilder();
for (byte md5Byte : md5Bytes) {
int val = ((int) md5Byte) & 0xff;
if (val < 16) {
hexValue.append("0");
}
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
// ...
}
2、数字签名
MD5加密算法可以用于数字签名,数字签名是指用某个私钥对信息进行签名,再将签名与信息一起发送给收件人,收件人使用对应的公钥来验证签名的合法性。
public class DigitalSignatureUtils {
/**
* 对数据进行数字签名
*
* @param data 待签名的数据
* @param privateKey 签名私钥
* @return 数字签名
* @throws Exception
*/
public static byte[] sign(byte[] data, PrivateKey privateKey) throws Exception {
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
/**
* 验证数字签名
*
* @param data 原始数据
* @param signature 签名
* @param publicKey 验证公钥
* @return 验证结果
* @throws Exception
*/
public static boolean verify(byte[] data, byte[] signature, PublicKey publicKey) throws Exception {
Signature sig = Signature.getInstance("MD5withRSA");
sig.initVerify(publicKey);
sig.update(data);
return sig.verify(signature);
}
}
3、文件校验
MD5加密算法可以用于文件校验,因为文件的MD5值是唯一的,这意味着当用户想要下载一个文件时,可以先对文件的MD5值进行校验,如果MD5值一致,则表明该文件是原来的文件,否则文件就被篡改了。
public class FileCheckUtils {
/**
* 计算文件MD5值
*
* @param file 待计算MD5值的文件
* @return MD5值
* @throws Exception
*/
public static String getFileMD5(File file) throws Exception {
FileInputStream fileInputStream = new FileInputStream(file);
byte[] buffer = new byte[1024];
MessageDigest md5 = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fileInputStream.read(buffer);
if (numRead > 0) {
md5.update(buffer, 0, numRead);
}
} while (numRead != -1);
fileInputStream.close();
byte[] md5Bytes = md5.digest();
StringBuilder hexValue = new StringBuilder();
for (byte md5Byte : md5Bytes) {
int val = ((int) md5Byte) & 0xff;
if (val < 16) {
hexValue.append("0");
}
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
}
三、MD5加密算法存在的问题
虽然MD5加密算法在很多应用场景中都得到了广泛的应用,但由于一些历史原因和技术问题,MD5加密算法在某些场景下可能存在一些问题,下面介绍两个MD5加密算法存在的问题。
1、碰撞攻击
在密码存储、数字签名等场景中,MD5加密算法被用于验证数据的完整性、安全性,但实际上,MD5加密算法可以被破解,因为它并不是完全无法反推。碰撞攻击是指在输入的任意两个不同的数据中找到相同的MD5值的过程。目前针对MD5的碰撞攻击已经非常成熟,因此在密码存储、数字签名等场景中建议使用更为安全的加密算法。
2、MD5彩虹表攻击
彩虹表攻击是指对密文进行预先计算,存储在数据库中的彩虹表中,然后进行账号破解的攻击方式。虹表都是提前计算好算法,存放在一个表格里,由于在运算速度上,计算要比破解慢得多,因此,指定长度的几乎所有明文可能,都可以构造一张包含其MD5值的彩虹表。因此,为了增强密码的安全性,导入“盐值”(即随机数)后再进行MD5加密。
public class SaltMd5 {
/**
* 加盐MD5加密
*
* @param src 待加密的字符串
* @param salt 盐值
* @return 盐值加密后的字符串
*/
public static String encrypt(String src, String salt) {
return DigestUtils.md5Hex(salt + DigestUtils.md5Hex(src));
}
}
总之,MD5加密算法在现实生活中有着广泛的应用场景,在使用时候,我们需要根据具体的业务场景来选择加密方式,建议在密码存储、数字签名等安全性要求比较高的场景下,不要使用MD5加密算法。
原创文章,作者:VZOFB,如若转载,请注明出处:https://www.506064.com/n/333159.html
微信扫一扫
支付宝扫一扫