在这里我只贴下简单实现,有兴趣了解shiro salt的,大家可以去看看源码哈,或者可以自己实现一些简单的md5,sha1,base64等的简易salt实现,以下示例基本都有注释,如有不对,欢迎指正
package com.zy.md; import java.security.MessageDigest; import java.util.Random; /** * Created by root on 16-10-2. */ public class Test { //main测试类 public static void main(String[] args) { String result = getMD5("zhoudazhuang"); System.err.println(result); } /** * 生成md5 * @param message * @return */ public static String getMD5(String message) { String md5str = ""; try { String token = System.currentTimeMillis()+new Random().nextInt()+""; System.out.println(token); //1 创建一个提供信息摘要算法的对象,初始化为md5算法对象 MessageDigest md = MessageDigest.getInstance("MD5");//这里可换为SHA1 //2 将消息变成byte数组 byte[] input = message.getBytes(); //3 计算后获得字节数组,这就是那128位了 byte表示为-128 127 MD5最终需32位的16进制字符表示 byte[] buff = md.digest(input); System.out.printf(buff.toString()); //4 把数组每一字节(一个字节占八位)换成16进制连成md5字符串 md5str = bytesToHex(buff); } catch (Exception e) { e.printStackTrace(); } return md5str; } /** * Integer.toHexString取得了十六进制字符串,可以看出 * b[i] & 0xFF运算后得出的仍然是个int,那么为何要和 0xFF进行与运算呢?直接 Integer.toHexString(b[i]);将byte强转为int不行吗?答案是不行的. * 其原因在于: * 1.byte的大小为8bits而int的大小为32bits * 2.java的二进制采用的是补码形式 * 二进制转十六进制 * @param bytes * @return */ public static String bytesToHex(byte[] bytes) { StringBuffer md5str = new StringBuffer(); //把数组每一字节换成16进制连成md5字符串 int digital; for (int i = 0; i < bytes.length; i++) { digital = bytes[i]; //Java中的一个byte,其范围是-128~127的,而Integer.toHexString的参数本来是int,如果不进行&0xff,那么当一个byte会转换成int时,对于负数,会做位扩展,举例来说,一个byte的-1(即0xff),会被转换成int的-1(即0xffffffff),那么转化出的结果就不是我们想要的了。 //而0xff默认是整形,所以,一个byte跟0xff相与会先将那个byte转化成整形运算,这样,结果中的高的24个比特就总会被清0,于是结果总是我们想要的 //而0xff为255 所以这里需使用 digital += 256 if(digital < 0) { digital += 256; } //当digital比16小时,高位补0,否则位数不够 if(digital < 16){ md5str.append("0"); } md5str.append(Integer.toHexString(digital)); } return md5str.toString().toUpperCase(); } public static String byteArrayToHex(byte[] byteArray) { // 首先初始化一个字符数组,用来存放每个16进制字符 char[] hexDigits = {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F' }; // new一个字符数组,这个就是用来组成结果字符串的(解释一下:一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方)) char[] resultCharArray =new char[byteArray.length * 2]; // 遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去 int index = 0; for (byte b : byteArray) { //hexDigits[b>>> 4 & 0xf] 由b获得16进制中的高8位 无符号右移4位与0xf 无符号右移4位则是计算高位 resultCharArray[index++] = hexDigits[b>>> 4 & 0xf]; //hexDigits[b>>> 4 & 0xf] 由b获得16进制中的低8位 b与0xf resultCharArray[index++] = hexDigits[b& 0xf]; } // 字符数组组合成字符串返回 return new String(resultCharArray); } }