前言
散列函数,也称作哈希函数、消息摘要函数。经常用到的MD5就属于这个范畴。本篇介绍什么是消息摘要、作用及几种实现方式
一、什么是消息摘要算法
消息摘要函数的主要作用不是完成数据的加密与解密工作的,它是用来验证数据完整性的重要技术。通过摘要函数,可以为数据创建“数字指纹”(散列值)。其认证流程图如下
特点:
- 单向性,运算过程不可逆
- 任意两个不同消息的散列值一定不同
- 散列值不同,则原始消息一定不同
各大软件厂商提供软件下载的时候会附带上数字指纹,如mysql
为了方便人们识别和阅读,数字指纹常以十六进制字符的串的形式出现
二、消息摘要算法家谱
1.MD算法
MD5算法是典型的消息摘要算法,它由MD4、MD3、MD2算法改进而来。无论是哪种MD算法,它们都需要获得一个随机长度的信息并产生一个128位的二进制信息摘要,转换成16进制就是32位的字符串。我们见到的大部分MD5算法的数字指纹都是32位十六进制的字符串。
随着计算机发展水平的提高,MD5算法已不再适合安全要求较高的场合
2.SHA算法
SHA算法基于MD4算法基础之上,其与MD算法不同之处在于摘要长度,SHA算法的摘要长度更长,安全性更高
发展历史:
- SHA-0算法,1983年第一个版本,因降低密码安全性撤回
- SHA-1算法,1995年发布,通常我们也把SHA-1算法简称为SHA算法。其在安全协定中使用广泛。包括TLS/SSL,SSH等。SHA-0和SHA-1算法可对最大长度为264的字节信息做摘要处理,得到160位的摘要信息,40为16进制的字符串
- SHA-2算法,是SHA-224,SHA-256,SHA-384,SHA-512四种算法的总称。
3.MAC算法
MAC算法结合了MD5和SHA算法的优势,并加入了密钥的支持,是一种更为安全的消息摘要算法。我们也通常把MAC算法称为HMAC算法(keyed-Hash Message Authentication Code)
经MAC算法得到的摘要值长度与参与实现的算法摘要值长度相同。如,HmacSHA1得到的摘要长度就是160位二进制,换算成十六进制编码就是40位。
三、代码实现
1.引入jar包
这里引入辅助jar包
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.14</version>
</dependency>
2.MD5算法
实现细节
算法 | 摘要长度 | 备注 |
---|---|---|
MD2 | 128 | jdk实现 |
MD5 | 128 | jdk实现 |
MD4 | 128 | Bouncy Castle实现 |
代码
public class MDUtil {
public static void main(String[] args) {
md5("helloWorld");
}
public static void md5(String src) {
String md5Hex = DigestUtils.md5Hex(src.getBytes(StandardCharsets.UTF_8));
System.out.println(md5Hex);
}
}
3.SHA256算法
实现细节
算法 | 摘要长度 | 备注 |
---|---|---|
SHA-1 | 160 | jdk实现 |
SHA-256 | 256 | jdk实现 |
SHA-384 | 384 | jdk实现 |
SHA-512 | 512 | jdk实现 |
SHA-224 | 224 | Bouncy Castle |
代码
public class SHAUtil {
public static void main(String[] args) {
sha256("helloWorld");
}
private static void sha1(String src) {
byte[] results = DigestUtils.sha1(src);
System.out.println(Hex.encodeHexString(results));
}
private static void sha256(String src) {
byte[] results = DigestUtils.sha256(src);
System.out.println(Hex.encodeHexString(results));
}
}
3.HmacSHA256算法
实现细节
算法 | 摘要长度 | 备注 |
HmacMD5 | 128 | jdk实现 |
HmacSHA1 | 160 | |
HmacSHA256 | 256 | |
HmacSHA384 | 384 | |
HmacSHA512 | 512 | |
HmacMD2 | 128 | Bouncy Castle实现 |
HmacMD4 | 128 | |
HmacSHA224 | 224 |
分为两步
- 构建密钥
- 执行消息摘要
public class HmacUtil {
public static void main(String[] args) throws Exception {
byte[] result = hmacSHA256(initHmacSHA256Key(), "helloWorld");
System.out.println(Hex.toHexString(result));
}
/**
* 初始化密钥
*
* @return 密钥
* @throws NoSuchAlgorithmException NoSuchAlgorithmException
*/
public static byte[] initHmacSHA256Key() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacSHA256");
SecretKey secretKey = keyGenerator.generateKey();
return secretKey.getEncoded();
}
public static byte[] hmacSHA256(byte[] key, String valueToDigest) throws Exception {
// 还原密钥
SecretKeySpec sk = new SecretKeySpec(key, "HmacSHA256");
Mac mac = Mac.getInstance(sk.getAlgorithm());
mac.init(sk);
return mac.doFinal(valueToDigest.getBytes(StandardCharsets.UTF_8));
}
public static byte[] initHmacMD5Key() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
SecretKey secretKey = keyGenerator.generateKey();
return secretKey.getEncoded();
}
private static byte[] hmacMd5(byte[] key, String valueToDigest) throws NoSuchAlgorithmException, InvalidKeyException {
// 还原密钥
SecretKeySpec sk = new SecretKeySpec(key, "HmacMD5");
Mac mac = Mac.getInstance(sk.getAlgorithm());
mac.init(sk);
return mac.doFinal(valueToDigest.getBytes(StandardCharsets.UTF_8));
}
}
总结
消息摘要算法其主要作用是认证消息的完整性。MD5是较为常用的消息摘要算法,不过其已不安全,在安全要求较高的场景不再使用,如网络传输敏感数据。笔者在项目中用的最多的是带有密钥的HmacSHA256算法。