zoukankan      html  css  js  c++  java
  • 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));
        }
    

    结果:

  • 相关阅读:
    ajax专题
    luogu P1346 电车 最短路
    luogu P1462 通往奥格瑞玛的道路 最短路
    luogu P1328 生活大爆炸版石头剪刀布
    luogu P1315 联合权值 枚举
    luogu P1156 垃圾陷阱 背包问题
    luogu P1217 回文质数 枚举
    luogu P3650 滑雪课程设计 枚举
    luogu1209 修理牛棚 贪心
    luogu P1223 排队接水 贪心
  • 原文地址:https://www.cnblogs.com/peaceliu/p/7825706.html
Copyright © 2011-2022 走看看