From 9a48a4cfc42b1a08881eb80d965df398f7b9224c Mon Sep 17 00:00:00 2001 From: FatttSnake Date: Mon, 6 Jun 2022 23:56:07 +0800 Subject: [PATCH] Add PBKDF2Util --- .../library/database/util/PBKDF2Util.java | 98 +++++++++++++++++++ .../library/database/PBKDF2UtilTest.java | 29 ++++++ 2 files changed, 127 insertions(+) create mode 100644 Library/src/main/java/com/cfive/classroom/library/database/util/PBKDF2Util.java create mode 100644 Library/src/test/java/com/cfive/classroom/library/database/PBKDF2UtilTest.java diff --git a/Library/src/main/java/com/cfive/classroom/library/database/util/PBKDF2Util.java b/Library/src/main/java/com/cfive/classroom/library/database/util/PBKDF2Util.java new file mode 100644 index 0000000..a052954 --- /dev/null +++ b/Library/src/main/java/com/cfive/classroom/library/database/util/PBKDF2Util.java @@ -0,0 +1,98 @@ +package com.cfive.classroom.library.database.util; + +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import java.math.BigInteger; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; + +public class PBKDF2Util { + public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1"; + + public static final int SALT_BYTE_SIZE = 32 / 2; //盐的长度 + public static final int HASH_BIT_SIZE = 128 * 4; //生成密文的长度 + public static final int PBKDF2_ITERATIONS = 1000; //迭代次数 + + /** + * @auther: Ragty + * @describe: 对输入的密码进行验证 + * @param: [attemptedPassword(待验证密码), encryptedPassword(密文), salt(盐值)] + * @return: boolean + * @date: 2018/11/2 + */ + public boolean authenticate(String attemptedPassword, String encryptedPassword, String salt) + throws NoSuchAlgorithmException, InvalidKeySpecException { + // 用相同的盐值对用户输入的密码进行加密 + String encryptedAttemptedPassword = getEncryptedPassword(attemptedPassword, salt); + // 把加密后的密文和原密文进行比较,相同则验证成功,否则失败 + return encryptedAttemptedPassword.equals(encryptedPassword); + } + + + /** + * @auther: Ragty + * @describe: 生成密文 + * @param: [password(明文密码), salt(盐值)] + * @return: java.lang.String + * @date: 2018/11/2 + */ + public String getEncryptedPassword(String password, String salt) throws NoSuchAlgorithmException, + InvalidKeySpecException { + + KeySpec spec = new PBEKeySpec(password.toCharArray(), fromHex(salt), PBKDF2_ITERATIONS, HASH_BIT_SIZE); + SecretKeyFactory f = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM); + return toHex(f.generateSecret(spec).getEncoded()); + } + + + /** + * @auther: Ragty + * @describe: 通过加密的强随机数生成盐(最后转换为16进制) + * @param: [] + * @return: java.lang.String + * @date: 2018/11/2 + */ + public String generateSalt() throws NoSuchAlgorithmException { + SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); + byte[] salt = new byte[SALT_BYTE_SIZE]; + random.nextBytes(salt); + + return toHex(salt); + } + + + /** + * @auther: Ragty + * @describe: 十六进制字符串转二进制字符串 + * @param: [hex] + * @return: byte[] + * @date: 2018/11/2 + */ + private static byte[] fromHex(String hex) { + byte[] binary = new byte[hex.length() / 2]; + for (int i = 0; i < binary.length; i++) { + binary[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16); + } + return binary; + } + + + /** + * @auther: Ragty + * @describe: 二进制字符串转十六进制字符串 + * @param: [array] + * @return: java.lang.String + * @date: 2018/11/2 + */ + private static String toHex(byte[] array) { + BigInteger bi = new BigInteger(1, array); + String hex = bi.toString(16); + int paddingLength = (array.length * 2) - hex.length(); + if (paddingLength > 0) + return String.format("%0" + paddingLength + "d", 0) + hex; + else + return hex; + } +} \ No newline at end of file diff --git a/Library/src/test/java/com/cfive/classroom/library/database/PBKDF2UtilTest.java b/Library/src/test/java/com/cfive/classroom/library/database/PBKDF2UtilTest.java new file mode 100644 index 0000000..918ecae --- /dev/null +++ b/Library/src/test/java/com/cfive/classroom/library/database/PBKDF2UtilTest.java @@ -0,0 +1,29 @@ +package com.cfive.classroom.library.database; + +import com.cfive.classroom.library.database.util.PBKDF2Util; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Test; + +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; + +class PBKDF2UtilTest { + private static final Logger LOGGER = LogManager.getLogger(); + private final PBKDF2Util pbkdf2Util = new PBKDF2Util(); + + @Test + void testPassword() throws NoSuchAlgorithmException, InvalidKeySpecException { + String password = "123456"; + + String salt = pbkdf2Util.generateSalt(); + String pbkdf2 = pbkdf2Util.getEncryptedPassword(password, salt); +// String md5 = md5Util.digest(password); + + LOGGER.debug("原始密码:" + password); +// System.out.println("MD5加密后的密码:"+md5); + LOGGER.debug("盐值:" + salt); + LOGGER.debug("PBKDF2加盐后的密码:" + pbkdf2); + LOGGER.debug("Test success"); + } +} \ No newline at end of file