MD5加密工具类

MD5加密工具类:

 

 

/**
 * @Author
 * @ClassName MD5Utils
 * @Description MD5加密工具
 * @Date 2021/3/15 17:52
 * @Version 1.0
 */
public class MD5Utils {

    private static final Logger logger = LoggerFactory.getLogger(MD5Utils.class);


    /**
     * Md5加密
     * @param message 加密信息
     * @return 返回 32 位的 字母 + 数字
     */
    public static String MD5(String message) {
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            return "check jdk";
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        byte[] byteArray = new byte[0];
        try {
            byteArray = message.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            logger.error(e.getMessage());
        }
        byte[] md5Bytes = md5.digest(byteArray);
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }


    /**
     * MD5 加密支持传入加密后的位数、字母是否大小写
     * @param pwd  需要加密的字符串
     * @param isUpper 字母大小写(false为默认小写,true为大写)
     * @param bit 加密的位数(16, 32, 64)
     * @return
     */
    public static String MD5(String pwd, boolean isUpper, Integer bit) {
        String md5 = new String();
        try {
            // 创建加密对象
            MessageDigest md = MessageDigest.getInstance("md5");
            if (bit == 64) {
                String bsB64 = Base64.encodeBase64String(md.digest(pwd.getBytes("utf-8")));
                md5 = bsB64;
            } else {
                // 计算MD5函数
                md.update(pwd.getBytes());
                byte b[] = md.digest();
                int i;
                StringBuffer sb = new StringBuffer("");
                for (int offset = 0; offset < b.length; offset++) {
                    i = b[offset];
                    if (i < 0)
                        i += 256;
                    if (i < 16)
                        sb.append("0");
                    sb.append(Integer.toHexString(i));
                }
                md5 = sb.toString();
                if(bit == 16) {
                    //截取32位md5为16位
                    String md16 = md5.substring(8, 24);
                    md5 = md16;
                    if (isUpper)
                        md5 = md5.toUpperCase();
                    return md5;
                }
            }
            //转换成大写
            if (isUpper)
                md5 = md5.toUpperCase();
        } catch (Exception e) {
          logger.error("md5加密抛出异常");
        }
        return md5;
    }


    /**
     *   加盐MD5
     * MD5加密,是属于不可逆的。我们知道正常使用MD5加密技术,
     * 同一字符,加密后的16进制数是不变的,自从出现彩虹表,对于公司内部员工来说,
     * 可以反查数据,获取不可能的权限,所以出现了salt算法。
     * 因此我们做了一个非常简单的加盐算法,每次保存密码到数据库时,都生成一个随机16位数字,将这16位数字和密码相加再求MD5摘要,
     * 然后在摘要中再将这16位数字按规则掺入形成一个48位的字符串。
     * 在验证密码时再从48位字符串中按规则提取16位数字,和用户输入的密码相加再MD5。
     * 按照这种方法形成的结果肯定是不可直接反查的,且同一个密码每次保存时形成的摘要也都是不同的。
     */
    public static String generate(String password) {
        Random r = new Random();
        StringBuilder sb = new StringBuilder(16);
        sb.append(r.nextInt(99999999)).append(r.nextInt(99999999));
        int len = sb.length();
        if (len < 16) {
            for (int i = 0; i < 16 - len; i++) {
                sb.append("0");
            }
        }
        String salt = sb.toString();
        password = md5Hex(password + salt);
        char[] cs = new char[48];
        for (int i = 0; i < 48; i += 3) {
            cs[i] = password.charAt(i / 3 * 2);
            char c = salt.charAt(i / 3);
            cs[i + 1] = c;
            cs[i + 2] = password.charAt(i / 3 * 2 + 1);
        }
        return new String(cs);
    }

    /**
     *  校验加盐后 是否和原文一致
     * @author
     * @param password 明文密码
     * @param md5 加密后的密文
     * @return
     */
    public static boolean verifyPasswordHasSalt(String password, String md5) {
        char[] cs1 = new char[32];
        char[] cs2 = new char[16];
        for (int i = 0; i < 48; i += 3) {
            cs1[i / 3 * 2] = md5.charAt(i);
            cs1[i / 3 * 2 + 1] = md5.charAt(i + 2);
            cs2[i / 3] = md5.charAt(i + 1);
        }
        String salt = new String(cs2);
        return md5Hex(password + salt).equals(new String(cs1));
    }
    

    /**
     * 获取十六进制字符串形式的MD5摘要
     */
    private static String md5Hex(String src) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] bs = md5.digest(src.getBytes());
            return new String(new Hex().encode(bs));
        } catch (Exception e) {
            return null;
        }
    }
    
}

 

posted @ 2018-07-20 16:36  邓维-java  阅读(239)  评论(0编辑  收藏  举报