|
@@ -1,177 +0,0 @@
|
|
|
-package cn.superdesk.libs.common.util;
|
|
|
-
|
|
|
-import org.slf4j.Logger;
|
|
|
-import org.slf4j.LoggerFactory;
|
|
|
-
|
|
|
-import javax.crypto.SecretKeyFactory;
|
|
|
-import javax.crypto.spec.PBEKeySpec;
|
|
|
-
|
|
|
-import java.security.NoSuchAlgorithmException;
|
|
|
-import java.security.SecureRandom;
|
|
|
-import java.security.spec.InvalidKeySpecException;
|
|
|
-
|
|
|
-import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
|
|
|
-
|
|
|
-import java.util.Arrays;
|
|
|
-import java.util.Random;
|
|
|
-
|
|
|
-
|
|
|
-/**
|
|
|
- * @author linjinyu
|
|
|
- * @description
|
|
|
- * @date 2018年7月25日
|
|
|
- */
|
|
|
-public class PasswordUtils {
|
|
|
-
|
|
|
- private static final Random RANDOM = new SecureRandom();
|
|
|
- private static final int ITERATIONS = 10000;
|
|
|
- private static final int KEY_LENGTH = 256;
|
|
|
-
|
|
|
- private static final Logger logger = LoggerFactory.getLogger(PasswordUtils.class);
|
|
|
-
|
|
|
-// private static final String salts = DigestUtils.md5("th9sS6618c6zmm5886Mu5zCo5Votte9U");
|
|
|
-
|
|
|
- private static final String salts = DigestUtils.md5("cn.superdesk.app.system.dao.entity.UserEntity");
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- *
|
|
|
- * @param password
|
|
|
- * @param salt
|
|
|
- * @return
|
|
|
- */
|
|
|
- public static String encodePassword(String password, Object salt) {
|
|
|
-
|
|
|
- ShaPasswordEncoder passwordEncoder = new ShaPasswordEncoder();
|
|
|
-
|
|
|
- return passwordEncoder.encodePassword(password, salt);
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 原来用的简单加密方式
|
|
|
- *
|
|
|
- * @param password
|
|
|
- * @return
|
|
|
- */
|
|
|
- public static String encryptPassword(String password) {
|
|
|
-
|
|
|
-
|
|
|
- StringBuilder sb = new StringBuilder();
|
|
|
- for (int i = 0; i < password.length(); i++) {
|
|
|
- sb.append(password.charAt(i)).append(salts.substring(i * 2, (i + 1) * 2));
|
|
|
- }
|
|
|
-
|
|
|
- logger.info("密码{} # encryptPassword:{}", password, DigestUtils.md5(sb.toString()));
|
|
|
-
|
|
|
- return DigestUtils.md5(sb.toString());
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 简单加密方式 升级版 salt 存放到 AppUser表中
|
|
|
- *
|
|
|
- * @param password
|
|
|
- * @param salt
|
|
|
- * @return
|
|
|
- */
|
|
|
- public static String encryptPassword(String password, String salt) {
|
|
|
-
|
|
|
-
|
|
|
- StringBuilder sb = new StringBuilder();
|
|
|
- for (int i = 0; i < password.length(); i++) {
|
|
|
- sb.append(password.charAt(i)).append(salt.substring(i * 2, (i + 1) * 2));
|
|
|
- }
|
|
|
-
|
|
|
- logger.info("密码{} # encryptPassword:{}", password, DigestUtils.md5(sb.toString()));
|
|
|
-
|
|
|
- return DigestUtils.md5(sb.toString());
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 使用说明 mark1
|
|
|
- *
|
|
|
- * 1. 你用getNextSalt创建一个盐
|
|
|
- * 2. 您向用户询问他的密码,并使用哈希方法生成一个盐渍和散列的密码。该方法返回一个字节[],您可以使用盐保存在数据库中
|
|
|
- * 3. 对用户进行身份验证,请求他的密码,从数据库中检索盐和散列密码,并使用isExpectedPassword方法检查详细信息是否匹配
|
|
|
- *
|
|
|
- */
|
|
|
-
|
|
|
-
|
|
|
- /****************************************** mark1 start ******************************************/
|
|
|
- /**
|
|
|
- * Returns a random salt to be used to hash a password.
|
|
|
- *
|
|
|
- * @return a 16 bytes random salt
|
|
|
- */
|
|
|
- public static byte[] getNextSalt() {
|
|
|
- byte[] salt = new byte[16];
|
|
|
- RANDOM.nextBytes(salt);
|
|
|
- return salt;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Returns a salted and hashed password using the provided hash.<br>
|
|
|
- * Note - side effect: the password is destroyed (the char[] is filled with zeros)
|
|
|
- *
|
|
|
- * @param password the password to be hashed
|
|
|
- * @param salt a 16 bytes salt, ideally obtained with the getNextSalt method
|
|
|
- * @return the hashed password with a pinch of salt
|
|
|
- */
|
|
|
- public static byte[] hash(char[] password, byte[] salt) {
|
|
|
- PBEKeySpec spec = new PBEKeySpec(password, salt, ITERATIONS, KEY_LENGTH);
|
|
|
- Arrays.fill(password, Character.MIN_VALUE);
|
|
|
- try {
|
|
|
- SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
|
|
- return skf.generateSecret(spec).getEncoded();
|
|
|
- } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
|
|
|
- throw new AssertionError("Error while hashing a password: " + e.getMessage(), e);
|
|
|
- } finally {
|
|
|
- spec.clearPassword();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Returns true if the given password and salt match the hashed value, false otherwise.<br>
|
|
|
- * Note - side effect: the password is destroyed (the char[] is filled with zeros)
|
|
|
- *
|
|
|
- * @param password the password to check
|
|
|
- * @param salt the salt used to hash the password
|
|
|
- * @param expectedHash the expected hashed value of the password
|
|
|
- * @return true if the given password and salt match the hashed value, false otherwise
|
|
|
- */
|
|
|
- public static boolean isExpectedPassword(char[] password, byte[] salt, byte[] expectedHash) {
|
|
|
- byte[] pwdHash = hash(password, salt);
|
|
|
- Arrays.fill(password, Character.MIN_VALUE);
|
|
|
- if (pwdHash.length != expectedHash.length) return false;
|
|
|
- for (int i = 0; i < pwdHash.length; i++) {
|
|
|
- if (pwdHash[i] != expectedHash[i]) return false;
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Generates a random password of a given length, using letters and digits.
|
|
|
- *
|
|
|
- * @param length the length of the password
|
|
|
- * @return a random password
|
|
|
- */
|
|
|
- public static String generateRandomPassword(int length) {
|
|
|
- StringBuilder sb = new StringBuilder(length);
|
|
|
- for (int i = 0; i < length; i++) {
|
|
|
- int c = RANDOM.nextInt(62);
|
|
|
- if (c <= 9) {
|
|
|
- sb.append(String.valueOf(c));
|
|
|
- } else if (c < 36) {
|
|
|
- sb.append((char) ('a' + c - 10));
|
|
|
- } else {
|
|
|
- sb.append((char) ('A' + c - 36));
|
|
|
- }
|
|
|
- }
|
|
|
- return sb.toString();
|
|
|
- }
|
|
|
-
|
|
|
- /****************************************** mark1 end ******************************************/
|
|
|
-}
|