0


PBKDF2算法Java实现

PBKDF2

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

  1. 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实现

  1. import javax.crypto.SecretKeyFactory;
  2. import javax.crypto.spec.PBEKeySpec;
  3. import java.security.NoSuchAlgorithmException;
  4. import java.security.SecureRandom;
  5. import java.security.spec.InvalidKeySpecException;
  6. import java.security.spec.KeySpec;
  7. public class PBKDF2Test {
  8. //字节数组转换成十六进制字符串
  9. private static String bytesToHex(byte[] bytes) {
  10. StringBuilder sb = new StringBuilder();
  11. for (byte b : bytes) {
  12. sb.append(String.format("%02x", b));
  13. }
  14. return sb.toString();
  15. }
  16. public static byte[] generateKey(String algorithm, char[] password, byte[] salt, int iterationCount, int keyLength)
  17. throws NoSuchAlgorithmException, InvalidKeySpecException {
  18. KeySpec keySpec = new PBEKeySpec(password, salt, iterationCount, keyLength);
  19. SecretKeyFactory factory = SecretKeyFactory.getInstance(algorithm);
  20. byte[] key = factory.generateSecret(keySpec).getEncoded();
  21. return key;
  22. }
  23. public static void main(String[] args) {
  24. String algorithm = "PBKDF2WithHmacSHA256";
  25. SecureRandom sRandom = new SecureRandom();
  26. byte[] salt = new byte[16];
  27. sRandom.nextBytes(salt);
  28. String pwdText = "password1";
  29. int iterationCount = 50000;
  30. int keyLength = 256;
  31. try {
  32. byte[] hash = PBKDF2Test.generateKey(algorithm,password.toCharArray(), salt, iterationCount, keyLength);
  33. System.out.println("hash字节数组长度: " +hash.length);
  34. System.out.println("Hex字符串输出: "+ bytesToHex(hash));
  35. } catch (NoSuchAlgorithmException e) {
  36. e.printStackTrace();
  37. } catch (InvalidKeySpecException e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. }

其中,algorithm使用的是PBKDF2WithHmacSHA256

String algorithm = "PBKDF2WithHmacSHA256";

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

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

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

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

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实现”的评论:

还没有评论