前言
本章讲解典型的加密算法MD5
方法
1、概念
MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。这套算法的程序在 RFC 1321 标准中被加以规范。1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。
MD5属于典型的单向加密算法(单向加密又称为不可逆加密算法,在加密过程中不使用密钥,明文由系统加密处理成密文,密文无法解密。一般适合于验证,在验证过程中,重新输入明文,并经过同样的加密算法处理,得到相同的密文并被系统重新认证。广泛使用于口令加密)
2、MD5加密原理
我们仍然以单词 China 为例,如何将其进行MD5加密呢?
第一步:首先将China单词转化为ASCII码的十六进制表示方式
China的十六进制为:43 68 69 6E 61
第二步:对得到的数据 4368696E61 进行填充和附加,使其能够被512整除。
填充指的是对原始信息进行填充,填充的首位是1,其余位全部为0,填充后的数据需要满足(n*512 - 64)位,我们本次试验的数据很明显是小于该位数的,即满足 512-64 = 448位即可。
附加指的是附加原始信息的长度,也就是还需要在后面补充64位,如果长度大于64位,则只取低64位。
通过填充和附加,使得数据变为512位。
以China为例,数据为:4368696E61,该数据长度为40位,因为 40 < 448,所以需要进行填充,共需填充 448 - 40 = 408位,使用十六进制表示为80000.....0000(408位)。然后进行附加,由于我们的数据长度为40位,十六进制为28,但是需要凑成64位,所以附加 2800000000000000。
最终经过填充和附加得到的数据为:4368696E61 80000.....0000(408位)2800000000000000。
第三步:将得到数据进行拆分,按照512位分块,每个512位分成4个128位数据块,最后将4个128位的数据块依次送到不同的散列函数进行4轮运算,每一轮又按照32位的小数据块进行复杂运算,最后将得到一个128位的哈希值,也就是最终的结果。
3、注意事项
MD5算法很有用,因为与存储可变长度的大文本相比,比较和存储这些较小的哈希值更容易。MD5算法是一种广泛使用的用于单向哈希的算法,该哈希用于验证而不必给出原始值。Unix系统使用 MD5算法以128位加密格式存储用户密码。MD5算法被广泛用于检查文件的完整性。而且,使用该算法很容易生成原始消息的信息摘要。MD5算法可以执行任意位数的消息的信息摘要,不限于MD的和,MD5sum仅限八位字节。但是多年来,MD5容易出现哈希冲突弱点,即可以为两个不同的输入创建相同的哈希函数。MD5对这些冲突攻击没有提供任何安全性。SHA(Secure Hash Algorithm,可产生160位信息摘要,并由NSA设计为数字签名算法的一部分)现已取代MD5,因为它不易产生SHA,现在已在密码学领域被接受以用于生成哈希函数-我发生碰撞,直到现在还没有发生碰撞。而且,MD5算法比优化的SHA算法要慢得多。SHA比MD5算法安全得多,而且,与MD5不同,它可以用超出速率的现有技术来实现。如今,考虑到更高的数据安全性(例如SHA256(可生成文本的256位签名)),新的哈希算法正在市场上出现。
此外,如果必须要使用MD5算法的话,可以在原有MD5的基础上 “加盐”,以确保使用MD5算法加密的数据安全性得到一定提升。
4、Java实现MD5加密
package cn.edu.ccut;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Test {
public static void main(String[] args) throws Exception {
String str = "China";
md5(str);
}
/**
* md5
*
*/
public static void md5(String str) {
byte[] secretBytes = null;
try {
secretBytes = MessageDigest.getInstance("md5").digest(
str.getBytes());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("没有这个md5算法!");
}
String md5code = new BigInteger(1, secretBytes).toString(16);
for (int i = 0; i < 32 - md5code.length(); i++) {
md5code = "0" + md5code;
}
System.out.println("MD5加密后:"+md5code);
}
}
执行结果如下: