Looly 4 年 前
コミット
71a82e0534

+ 1 - 0
CHANGELOG.md

@@ -9,6 +9,7 @@
 * 【poi    】     重要:不再兼容POI-3.x,增加兼容POI-5.x(issue#I35J6B@Gitee)
 * 【core   】     FileTypeUtil使用长匹配优先(pr#1457@Github)
 * 【core   】     IterUtil和CollUtil增加isEqualList方法(issue#I3A3PY@Gitee)
+* 【crypto 】     增加PBKDF2(issue#1416@Github)
 
 ### Bug修复
 * 【socket 】     修复Client创建失败资源未释放问题。

+ 13 - 0
hutool-crypto/src/main/java/cn/hutool/crypto/SecureUtil.java

@@ -19,6 +19,7 @@ import cn.hutool.crypto.digest.MD5;
 import cn.hutool.crypto.symmetric.AES;
 import cn.hutool.crypto.symmetric.DES;
 import cn.hutool.crypto.symmetric.DESede;
+import cn.hutool.crypto.symmetric.PBKDF2;
 import cn.hutool.crypto.symmetric.RC4;
 import cn.hutool.crypto.symmetric.SymmetricCrypto;
 
@@ -1048,4 +1049,16 @@ public final class SecureUtil {
 	public static void disableBouncyCastle() {
 		GlobalBouncyCastleProvider.setUseBouncyCastle(false);
 	}
+
+	/**
+	 * PBKDF2加密密码
+	 *
+	 * @param password 密码
+	 * @param salt 盐
+	 * @return 盐,一般为16位
+	 * @since 5.6.0
+	 */
+	public static String pbkdf2(char[] password, byte[] salt){
+		return new PBKDF2().encryptHex(password, salt);
+	}
 }

+ 66 - 0
hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/PBKDF2.java

@@ -0,0 +1,66 @@
+package cn.hutool.crypto.symmetric;
+
+import cn.hutool.core.util.HexUtil;
+import cn.hutool.crypto.KeyUtil;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.PBEKeySpec;
+
+/**
+ * PBKDF2应用一个伪随机函数以导出密钥,PBKDF2简单而言就是将salted hash进行多次重复计算。
+ * 参考:https://blog.csdn.net/huoji555/article/details/83659687
+ *
+ * @author looly
+ */
+public class PBKDF2 {
+
+	private String algorithm = "PBKDF2WithHmacSHA1";
+	//生成密文的长度
+	private int keyLength = 512;
+
+	//迭代次数
+	private int iterationCount = 1000;
+
+	/**
+	 * 构造,算法PBKDF2WithHmacSHA1,盐长度16,密文长度512,迭代次数1000
+	 */
+	public PBKDF2() {
+	}
+
+	/**
+	 * 构造
+	 *
+	 * @param algorithm      算法,一般为PBKDF2WithXXX
+	 * @param keyLength      生成密钥长度,默认512
+	 * @param iterationCount 迭代次数,默认1000
+	 */
+	public PBKDF2(String algorithm, int keyLength, int iterationCount) {
+		this.algorithm = algorithm;
+		this.keyLength = keyLength;
+		this.iterationCount = iterationCount;
+	}
+
+	/**
+	 * 加密
+	 *
+	 * @param password 密码
+	 * @param salt     盐
+	 * @return 加密后的密码
+	 */
+	public byte[] encrypt(char[] password, byte[] salt) {
+		final PBEKeySpec pbeKeySpec = new PBEKeySpec(password, salt, iterationCount, keyLength);
+		final SecretKey secretKey = KeyUtil.generateKey(algorithm, pbeKeySpec);
+		return secretKey.getEncoded();
+	}
+
+	/**
+	 * 加密
+	 *
+	 * @param password 密码
+	 * @param salt     盐
+	 * @return 加密后的密码
+	 */
+	public String encryptHex(char[] password, byte[] salt) {
+		return HexUtil.encodeHexStr(encrypt(password, salt));
+	}
+}

+ 15 - 0
hutool-crypto/src/test/java/cn/hutool/crypto/test/symmetric/PBKDF2Test.java

@@ -0,0 +1,15 @@
+package cn.hutool.crypto.test.symmetric;
+
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.crypto.SecureUtil;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PBKDF2Test {
+
+	@Test
+	public void encryptTest(){
+		final String s = SecureUtil.pbkdf2("123456".toCharArray(), RandomUtil.randomBytes(16));
+		Assert.assertEquals(128, s.length());
+	}
+}