上一篇介绍了MD及SHA,接下来我们来说说MAC算法。MAC只要就是加入了密钥。
上一篇:Java加密与解密之消息摘要算法
MAC:Message Authentication Code,消息认证码算法。
MAC算法结合了MD5和SHA算法的优势,加入了密钥的支持,是一种更加安全的消息摘要算法。
MAC兼容了MD和SHA算法的特性,并在此基础上加入了密钥, 因为MAC算法融合了密钥散列函数通常我们也把MAC称为HMAC(keyd-Hash Message Authentication Code)。
MD系列:HmacMD2,HmacMD4,HmacMD5三种算法;
SHA系列:HmacSHA1,HmacSHA224,HmacSHA256,HmacSHA384,HmacSHA512五种算法。
HMAC生成的摘要信息长度与使用的MD或是SHA是对应的。如:HmacSHA256使用这个算法那生成的摘要信息长度就是256个字节。
JDK8支持的算法:
HmacMD5,HmacSHA1,HmacSHA256,HmacSHA384,HmacSHA512
HmacMD2,HmacMD4,HmacSHA224这三种不支持,只用使用第三方库BC(Bouncy Castle)
代码示例:
package com.pack.security.mac;
import java.nio.charset.Charset;
import java.util.Base64;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class HmacSHA1 {
// 算法
private static final String ALGORITHM = "HmacSHA1" ;
/**
* <p>
* 初始化HmacSHA1密钥
* </p>
* 2020年10月8日 下午2:55:38
* @author xg
* @return byte[] 生成的密钥信息
* @throws Exception
*/
public static byte[] initHmacSHA1Key() throws Exception{
// 初始化KeyGenerator密钥生成器
KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM) ;
// 产生密钥
SecretKey secretKey = keyGenerator.generateKey() ;
// 获取密钥
return secretKey.getEncoded() ;
}
/**
* <p>
* HmacSHA1 消息摘要
* </p>
* @author xg
* @param data 要加密的数据
* @param key 密钥信息
* @return byte[] 摘要信息
* @throws Exception
*/
public static byte[] encodeHmacSHA1(byte[] data, byte[] key) throws Exception {
// 还原密钥
SecretKey secretKey = new SecretKeySpec(key, ALGORITHM) ;
// 实例化MAC
Mac mac = Mac.getInstance(secretKey.getAlgorithm()) ;
// 初始化mac
mac.init(secretKey) ;
// 返回消息摘要
return mac.doFinal(data) ;
}
public static String hex(byte[] digest) {
StringBuilder sb = new StringBuilder() ;
for (byte b : digest) {
String str = Integer.toHexString(b & 0xff) ;
if (str.length() < 2) {
sb.append("0" + str) ;
} else {
sb.append(str) ;
}
}
return sb.toString() ;
}
public static void main(String[] args) throws Exception {
String message = "我是HmacSHA1算法" ;
byte[] key1 = initHmacSHA1Key() ;
String strKey1 = Base64.getEncoder().encodeToString(key1) ;
byte[] messageDigest1 = encodeHmacSHA1(message.getBytes(Charset.forName("UTF-8")), key1) ;
String strDigest1 = hex(messageDigest1) ;
System.out.println(strDigest1) ;
byte[] key2 = Base64.getDecoder().decode(strKey1.getBytes()) ;
byte[] messageDigest2 = encodeHmacSHA1(message.getBytes(Charset.forName("UTF-8")), key2) ;
String strDigest2 = hex(messageDigest2) ;
System.out.println(strDigest2) ;
System.out.println(strDigest1.equals(strDigest2)) ;
}
}
笔者曾经在一个项目中使用过该算法。当时是有很多的厂商要和我们系统对接,为了安全我们给每一个厂商提供一个密钥,然后厂商按照我们的约定对所有的入参进行签名,我们系统进行安全验证。
其它的算法这里就不演示了,针对自己使用的JDK版本看是否支持你所需要的算法即可,基本上BC支持了我们熟知的所有加解密算法。
到此我们对消息摘要算法进行了简单的介绍和使用。后续还会对对称加密和非对称加密及数字签名算法进行介绍。