/** * 随机字符串集 */ private static final String CHARACTORS = "efghxxxx"; /** * 随机长度范围 6表示0~6 */ private static final int RANDOM_LENGTH = 6;
/** * 深度加密 * * <br> * * * @param plain 明文,待加密串 * @param salt 盐 * @return String 加密字符串 * @version V1.0 * @throws Exception */ public static String encrypt(String plain, String salt) { if (StringUtils.isEmpty(salt)) { log.error("salt是空值"); throw new IllegalArgumentException("salt是空值"); } // 明文通过HMacSHA1 由动态key hash得到simple串 String simple = HMacSHA1.getSignature(plain, plain); // hash + 加盐 simple = simple.concat(salt); // 加盐simple串 通过HMacSHA1 由 固定KEY 再 hash得到complex串 String complex = HMacSHA1.getSignature(simple, KEY); // complex串 由 HMacSHA1 经过动态key 再 hash得到 复杂的multiplex 串 String multiplex = HMacSHA1.getSignature(complex, complex); // 对盐salt进行DES3加密 String des_salt = StaticKeyHelper.encryptKey(salt); // multiplex 尾部拼接加密的盐 得到最终的结果串 String result = multiplex.concat(des_salt); // 机密salt链接在加密密码之后 return result; }
深度随机盐
public static String salt() { Random random = new Random(); // 随机字符串长度 int length = random.nextInt(RANDOM_LENGTH) + 5; // 由给定chars串 生成随机长度为length的字符串 String salt = RandomStringUtils.random(length, CHARACTORS); return salt; }
对称解密得到盐
public static Map<String, String> resolvePassword(String encrypt) { Map<String, String> params = new HashMap<String, String>(); // 从字符串字段中解析出加密密码和盐,并对盐进行解密 String persistent = encrypt.substring(0, 40); String salt = encrypt.substring(40); salt = StaticKeyHelper.descryptKey(salt); params.put("password", persistent); params.put("salt", salt); return params; }
对称加解密方法,key跟上面的key不一样
private static final String KEY = "abcdxxxx"; public static String encryptKey(String key) { String s = ""; try { s = DES3.encrypt(key, KEY); } catch (Exception e) { throw new RuntimeException("加密错误", e); } return s; } public static String descryptKey(String data) { String s = ""; try { s = DES3.decrypt(data, KEY); } catch (Exception e) { throw new RuntimeException("解密错误", e); } return s; }
有了上述的加密方法,可以安全的对用户数据如密码进行加密了,并且数据库中存到加密数据不可逆,我们也不知道用户到底存的是什么密码,这才是安全的数据。
虽然我们不知道,但我们可以对用户的输入进行匹配校验,这个过程是一个对称的加密过程,即 一部分不可逆+一部分可逆= 加密串
//对用户的输入密码进行校验 String dbpwd = "数据库中的加密密码"; String salt = resolvePassword(dbpwd ).get("salt"); String encryptedPassword = PasswordHelper.encrypt(reqpwd, salt); if (!dbpwd.equals(encryptedPassword)) { throw new ServiceException(UserErrorCode.USER_NOT_FOUND, "用户帐号或密码错误"); }