Hmac算法
我们回顾一下哈希算法:
正是因为相同的输入会产生相同的输出,我们加盐的目的就在于,使得输入有所变化:
这个salt可以看作是一个额外的“认证码”,同样的输入,不同的认证码,会产生不同的输出。因此,要验证输出的哈希,必须同时提供“认证码”。
Hmac算法就是一种基于密钥的消息认证码算法,它的全称是Hash-based Message Authentication Code,是一种更安全的消息摘要算法。
因此,HmacMD5可以看作带有一个安全的key的MD5。使用HmacMD5而不是用MD5加salt,有如下好处:
- HmacMD5使用的key长度是64字节,更安全;
- Hmac输出和原有的哈希算法长度一致。
可见,Hmac本质上就是把key混入摘要的算法。验证此哈希时,除了原始的输入数据,还要提供key。
为了保证安全,我们不会自己指定key,而是通过Java标准库的KeyGenerator生成一个安全的随机的key。下面是使用HmacMD5的代码:
- 通过名称获取
KeyGenerator
实例; - 通过
KeyGenerator
创建一个SecretKey
实例; - 用初始化
Mac
实例; - 对
Mac
实例反复调用update(byte[])
输入数据; - 调用
Mac
实例的doFinal()
获取最终的哈希值。我们可以用Hmac算法取代原有的自定义的加盐算法,因此,存储用户名和口令的数据库结构如下:
有了Hmac计算的哈希和,我们想要验证怎么办?这时,SecretKey
不能从KeyGenerator
生成,而是从一个byte[]
数组恢复:
恢复SecretKey
的语句就是new SecretKeySpec(hkey, "HmacMD5")
。
Hmac算法是一种标准的基于密钥的哈希算法,可以配合MD5、SHA-1等哈希算法,计算的摘要长度和原摘要算法长度相同。