0


PBKDF2算法Java实现

PBKDF2

PBKDF2 (Password-Based Key Derivation Function 2),基于口令的密钥派生函数,可以防止字典攻击和彩虹表攻击。使用用户持有的、不需要保存的秘密,比如口令,来推导对称密钥(消息的发送方和接收方持有相同的秘密,使用同样的算法来推导对称密钥)。

key = generateKey(String algorithm, char[] password, byte[] salt, int iterationCount, int keyLength)

输入参数

algorithm: 算法名,比如: PBKDF2WithHmacSHA256* *

password: 口令,字节数组/字符串

salt:盐,安全生成的随机字节,推荐长度为128位

iterationCount:迭代次数

keyLength:派生密钥长度


注意:生成密钥所使用的类为javax.crypto.SecretKeyFactory(私密密钥工厂类)。可以通过指定以下的算法来请求SecretKeyFactory实例.


输出参数

根据请求长度派生的密钥,如32字节(256位)的密钥。

Java实现

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

public class PBKDF2Test {

    //字节数组转换成十六进制字符串
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    public static byte[] generateKey(String algorithm, char[] password, byte[] salt, int iterationCount, int keyLength)
            throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeySpec keySpec = new PBEKeySpec(password, salt, iterationCount, keyLength);
        SecretKeyFactory factory = SecretKeyFactory.getInstance(algorithm);
        byte[] key = factory.generateSecret(keySpec).getEncoded();
        return key;
    }

    public static void main(String[] args) {
        String algorithm = "PBKDF2WithHmacSHA256";
        SecureRandom sRandom = new SecureRandom();
        byte[] salt = new byte[16];
        sRandom.nextBytes(salt);
        String pwdText = "password1";
        int iterationCount = 50000;
        int keyLength = 256;
        try {
            byte[] hash = PBKDF2Test.generateKey(algorithm,password.toCharArray(), salt, iterationCount, keyLength);
            System.out.println("hash字节数组长度: " +hash.length);
            System.out.println("Hex字符串输出: "+ bytesToHex(hash));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
    }
}

其中,algorithm使用的是PBKDF2WithHmacSHA256

String algorithm = "PBKDF2WithHmacSHA256";

salt是使用强随机数生成器生成的长度为16的字节数组

SecureRandom sRandom = new SecureRandom();
byte[] salt = new byte[16];
sRandom.nextBytes(salt);

如果想基于指定的16进制字符串来生成salt,需要使用 hexToByte(String hex) 函数来做转换:

    public static byte[] hexToByte(String hex){
        int m = 0, n = 0;
        int byteLen = hex.length() / 2;
        byte[] ret = new byte[byteLen];
        for (int i = 0; i < byteLen; i++) {
            m = i * 2 + 1;
            n = m + 1;
            int intVal = Integer.decode("0x" + hex.substring(i * 2, m) + hex.substring(m, n));
            ret[i] = Byte.valueOf((byte)intVal);
        }
        return ret;
    }

byte[] salt = hexToByte("aaef2d3f4d77ac66e9c5a6c3d8f921d1");

iterationCount,设置迭代次数为50000:

int iterationCount = 50000;

keyLength,设置派生密钥长度为32字节/256位:

int keyLength = 256;

调用generateKey函数,返回得到字节数组,并将其转换成hex16进制字符串:

bytesToHex(hash)

测试结果

使用随机的salt

salt值是使用强随机数生成器生成的,每次计算派生的密钥是不一样的。

第一次

第二次

使用固定的salt

salt值是基于hex字符串生成的,每次计算派生的密钥是一样的。

第一次和第二次

标签: 密码学 java 安全

本文转载自: https://blog.csdn.net/xinyu10001/article/details/127955324
版权归原作者 匡河捞小鱼 所有, 如有侵权,请联系我们删除。

“PBKDF2算法Java实现”的评论:

还没有评论