shiro中MessageDigest根据盐值计算md5
Posted 张侦毅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shiro中MessageDigest根据盐值计算md5相关的知识,希望对你有一定的参考价值。
MessageDigest简介
java.security.MessageDigest
类用于为应用程序提供信息摘要算法的功能,如 MD5
或 SHA
算法。简单点说就是用于生成散列码。信息摘要是安全的单向哈希函数,它接收任意大小的数据,输出固定长度的哈希值。
源码示例
在下面的示例中,抽取的是shiro
中的SimpleHash
类源码使用的是shiro
中的MessageDigest
,通过对名为admin
的username
进行盐值计算,然后依据此盐值对密码123456
进行md5
计算。
源码如下:
@Slf4j
public class MessageDigestTest
/**
* 盐值计算
* @param username 用户名
* @return byte[] 盐值byte数组
*/
public byte[] getSalt(String username)
// 计算盐值
ByteSource byteSource = ByteSource.Util.bytes(username);
return byteSource.getBytes();
/**
* 将字符串转换成byte数组
* @param str 输入字符串
* @return byte[]
*/
private byte[] getByte(String str)
return str.getBytes();
/**
* 测试md5盐值加密算法
* 用户admin,密码123456
* 加密后的结果:e0b141de1c8091be350d3fc80de66528
*/
@Test
public void testMD5()
// 计算次数
Integer hashIterations = 4;
try
// 装载md5加密方法
MessageDigest digest = MessageDigest.getInstance("md5");
// 计算用户盐值
byte[] salt = getSalt("admin");
// 将密码转换成byte数组
byte[] bytes = getByte("123456");
// 如果盐值不为空,则MessageDigest加载盐值
if (salt != null)
digest.reset();
digest.update(salt);
// 执行md5运算
byte[] hashed = digest.digest(bytes);
int iterations = hashIterations - 1; //already hashed once above
//iterate remaining number:
for (int i = 0; i < iterations; i++)
digest.reset();
hashed = digest.digest(hashed);
// 将byte数组转换成字符串
String result = byteToString(hashed);
// 在控制台中打印加密后的md5字符串
log.info("md5加密结果:",result);
catch (NoSuchAlgorithmException e)
e.printStackTrace();
/**
* 将byte数组转换成字符串
* @param hashed 加密字符串
* @return String
*/
private String byteToString(byte[] hashed)
// 创建字符串StringBuffer
StringBuffer sb = new StringBuffer();
// 创建缓存
String temp = null;
// 循环遍历拼接字符串
for(int i = 0,hashedLenth = hashed.length; i < hashedLenth; i ++)
temp = Integer.toHexString(0xFF & hashed[i]);
sb.append(temp);
return sb.toString();
上面中,源码的计算结果为:e0b141de1c8091be350d3fc80de66528
分析
MessageDigest的实例化
从上面的示例中,我们可以看出,MessageDigest
的实例化方法为:
MessageDigest digest = MessageDigest.getInstance("md5");
在实例化的同时,我们需要为其指定加密方式,如上面,我们指定的加密方式为md5
。
MessageDigest接收被加密数据
MessageDigest
接收被加密数据方式如下:
digest.update(salt);
为了避免之前接收的被加密数据对现在所造成的影响,因而这里加入了清空之前接收的被加密数据方法。
digest.reset();
而MessageDigest
执行的加密方法为:
byte[] hashed = digest.digest(bytes);
虽然说在源码中,在此之前也加入了digest.reset();
操作,不过经过实测,删掉此处的代码其也并不影响结果的正确性,换言之,对于digest.digest(bytes)
的前序操作digest.reset();
可加可不加,在此处并不会影响程序的执行结果。
这里需要注意的是,MessageDigest
所接收的数据,无论是盐值,还是密码,均是byte[]
格式。
而被接收的数据如果长度比较长,可以通过重复执行多次digest.update(salt);
,依次将其添加进来;同样的,MessageDigest
对于被加密对象,也可以执行多次加密操作,即可以执行多次digest.digest(bytes)
操作,这样进而增加了加密密码的强度。
而在上面的例子中hashIterations
表示的是加密的迭代次数,在shiro的源码中,默认执行4次加密操作。
以上是关于shiro中MessageDigest根据盐值计算md5的主要内容,如果未能解决你的问题,请参考以下文章