使用 PBKDF2 導出密鑰

使用 PBKDF2 導出密鑰

java默認提供的方法爲:

    /**
     * 使用算法 PBKDF2 基於 SHA-256 導出密鑰
     * 使用 JCE 默認方法,使用默認的 Provider
     *
     * @param password       口令
     * @param salt           鹽值
     * @param iterationCount 迭代次數
     * @return 導出結果
     */
    public static byte[] derivedKeyUsingJCE(char[] password, byte[] salt, int iterationCount) throws GeneralSecurityException {
        SecretKeyFactory fact = SecretKeyFactory.getInstance("PBKDF2WITHHMACSHA256");
        return fact.generateSecret(new PBEKeySpec(password, salt, iterationCount, KEY_LENGTH)).getEncoded();
    }

參考代碼:

import org.bouncycastle.crypto.PBEParametersGenerator;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.GeneralSecurityException;
import java.security.Security;

/**
 * @author youngbear
 * @email [email protected]
 * @date 2020/6/30 22:40
 * @blog https://blog.csdn.net/next_second
 * @github https://github.com/YoungBear
 * @description 使用 PBKDF2 算法導出口令
 */
public class PBKDF2Practise {

    // key 長度 256 bit,32字節
    private static final int KEY_LENGTH = 256;
    // 測試鹽值(隨機生成)
    private static final byte[] TEST_SALT = {127, 28, 114, -2, -84, -125, -6, 27, 44, 109, 82, 127, 43, 124, 5, 99};
    // 測試口令
    private static final String TEST_PASSWORD = "@T2b45&l";
    // 測試迭代次數
    private static final int ITERATION_COUNT = 1000;

    public static void main(String[] args) throws GeneralSecurityException {
        char[] passwordChars = TEST_PASSWORD.toCharArray();
        byte[] bytesBC = derivedKeyUsingBC(passwordChars, TEST_SALT, ITERATION_COUNT);
        System.out.println(Hex.toHexString(bytesBC));
        byte[] bytesJCE = derivedKeyUsingJCE(passwordChars, TEST_SALT, ITERATION_COUNT);
        System.out.println(Hex.toHexString(bytesJCE));
        byte[] bytesJCEBC = derivedKeyUsingJCEBC(passwordChars, TEST_SALT, ITERATION_COUNT);
        System.out.println(Hex.toHexString(bytesJCEBC));

    }

    /**
     * 使用算法 PBKDF2 基於 SHA-256 導出密鑰
     * 使用 BouncyCastle 提供的 low-level API
     *
     * @param password       口令
     * @param salt           鹽值
     * @param iterationCount 迭代次數
     * @return 導出結果
     */
    public static byte[] derivedKeyUsingBC(char[] password, byte[] salt, int iterationCount) {
        PBEParametersGenerator generator = new PKCS5S2ParametersGenerator(new SHA256Digest());
        generator.init(PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(password), salt, iterationCount);
        return ((KeyParameter) generator.generateDerivedParameters(KEY_LENGTH)).getKey();
    }

    /**
     * 使用算法 PBKDF2 基於 SHA-256 導出密鑰
     * 使用 JCE 默認方法,使用默認的 Provider
     *
     * @param password       口令
     * @param salt           鹽值
     * @param iterationCount 迭代次數
     * @return 導出結果
     */
    public static byte[] derivedKeyUsingJCE(char[] password, byte[] salt, int iterationCount) throws GeneralSecurityException {
        SecretKeyFactory fact = SecretKeyFactory.getInstance("PBKDF2WITHHMACSHA256");
        return fact.generateSecret(new PBEKeySpec(password, salt, iterationCount, KEY_LENGTH)).getEncoded();
    }

    /**
     * 使用算法 PBKDF2 基於 SHA-256 導出密鑰
     * 使用 JCE 默認方法,使用 BouncyCastle 的 Provider
     *
     * @param password       口令
     * @param salt           鹽值
     * @param iterationCount 迭代次數
     * @return 導出結果
     */
    public static byte[] derivedKeyUsingJCEBC(char[] password, byte[] salt, int iterationCount) throws GeneralSecurityException {
        Security.addProvider(new BouncyCastleProvider());
        SecretKeyFactory fact = SecretKeyFactory.getInstance(
                "PBKDF2WITHHMACSHA256", "BC");
        return fact.generateSecret(new PBEKeySpec(password, salt, iterationCount, KEY_LENGTH)).getEncoded();
    }
}

其中,使用BouncyCastle的話,需要引入pom依賴:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.65</version>
</dependency>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章