zoukankan      html  css  js  c++  java
  • zbb20180921 java,md5,MD5加密+加盐

    MD5加密+加盐

    了解:

    • MD5加密,是属于不可逆的。我们知道正常使用MD5加密技术,同一字符,加密后的16进制数是不变的,自从出现彩虹表,对于公司内部员工来说,可以反查数据,获取不可能的权限,所以出现了salt算法。
      代码如下:
    package com.md5.demo;
    import java.math.BigInteger;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    /**
     * 普通的MD加密
     * @author peaceliu
     *
     */
    public class MD5Utils {
        /**
         * 使用md5的算法进行加密
         */
        public static String md5(String plainText) {
            byte[] secretBytes = null;
            try {
                secretBytes = MessageDigest.getInstance("md5").digest(plainText.getBytes());
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException("没有md5这个算法!");
            }
            String md5code = new BigInteger(1, secretBytes).toString(16);// 16进制数字
            // 如果生成数字未满32位,需要前面补0
            for (int i = 0; i < 32 - md5code.length(); i++) {
                md5code += "0";
            }
            return md5code;
        }
        public static void main(String[] args) {
            System.out.println(md5("lhp"));
        }
    }

    • 一般使用的加盐:
      md5(Password+UserName),即将用户名和密码字符串相加再MD5,这样的MD5摘要基本上不可反查。
      但有时候用户名可能会发生变化,发生变化后密码即不可用了(验证密码实际上就是再次计算摘要的过程)。
      ----------
    • 因此我们做了一个非常简单的加盐算法,每次保存密码到数据库时,都生成一个随机16位数字,将这16位数字和密码相加再求MD5摘要,然后在摘要中再将这16位数字按规则掺入形成一个48位的字符串。
    • 在验证密码时再从48位字符串中按规则提取16位数字,和用户输入的密码相加再MD5。按照这种方法形成的结果肯定是不可直接反查的,且同一个密码每次保存时形成的摘要也都是不同的。
      代码如下:
    package com.md5.demo;
    import java.security.MessageDigest;
    import java.util.Random;
    import org.apache.commons.codec.binary.Hex;
    /**
     * MD5加盐加密
     */    
    public class PasswordUtil {
        /**
         * 生成含有随机盐的密码
         */
        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);
        }
        /**
         * 校验密码是否正确
         */
        public static boolean verify(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摘要
         */
        public 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;
            }
        }
    }

    测试:

        public static void main(String[] args) {
            // 加密+加盐
            String password1 = generate("admin");
            System.out.println("结果:" + password1 + "   长度:"+ password1.length());
            // 解码
            System.out.println(verify("admin", password1));
            // 加密+加盐
            String password2= generate("admin");
            System.out.println("结果:" + password2 + "   长度:"+ password2.length());
            // 解码
            System.out.println(verify("admin", password2));
        }

    结果:

  • 相关阅读:
    75. 颜色分类
    排序链表
    两个数组的交集
    242. 有效的字母异位词
    排序优化
    622.设计循环队列
    比较含退格的字符串
    682.棒球比赛
    496.下一个更大的元素I
    线性排序算法
  • 原文地址:https://www.cnblogs.com/super-admin/p/9686926.html
Copyright © 2011-2022 走看看