You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Bouncy Castle实现PBKDF2时哈希重复问题求助

问题

尝试用PBKDF2+Bouncy Castle实现密码哈希函数,每次输入同一密码生成的哈希却完全相同,明明每次都用SecureRandom生成了新盐。代码如下:

SecureRandom random = new SecureRandom();
byte[] salt = new byte[8];
final int iterationCount = 20000;
final int keyLength = 256;
random.nextBytes(salt);

try {
     SecretKeyFactory factoryBC =  SecretKeyFactory.getInstance("PBKDF2WithHmacSHA3-256", "BC");
     KeySpec keySpecBC = new PBEKeySpec(password.toCharArray(), salt, iterationCount, keyLength);
     SecretKey keyBC = factoryBC.generateSecret(keySpecBC);
     String hashedPW = keyBC.getEncoded().toString();
}

比如输入“hello”,每次得到的都是[B@44af588b。

问题原因

核心问题出在keyBC.getEncoded().toString()这行代码:

  • keyBC.getEncoded()返回的是字节数组,但Java中字节数组的toString()方法不会把字节内容转成可读字符串,它返回的是[B@加上数组对象的哈希码,这个值和数组里的实际哈希内容完全无关。
  • 你看到的[B@44af588b只是数组对象的标识,不是真正的密码哈希值,所以不管盐怎么变化,这个标识都可能重复(或仅在不同运行环境下改变,但本质和哈希无关)。
修复方案
  1. 正确转换字节数组为字符串:用Base64编码把哈希字节数组转成可读字符串(也可以用十六进制,Base64格式更紧凑)。
  2. 保存盐:哈希验证时需要用到相同的盐,所以生成哈希时要把盐和最终哈希值一起存储(比如用分隔符拼接,或者分开存入数据库字段)。

修复后的代码示例:

SecureRandom random = new SecureRandom();
byte[] salt = new byte[8];
final int iterationCount = 20000;
final int keyLength = 256;
random.nextBytes(salt);

try {
     SecretKeyFactory factoryBC = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA3-256", "BC");
     KeySpec keySpecBC = new PBEKeySpec(password.toCharArray(), salt, iterationCount, keyLength);
     SecretKey keyBC = factoryBC.generateSecret(keySpecBC);
     byte[] hashBytes = keyBC.getEncoded();
     // 将哈希字节数组转成Base64字符串
     String hashedPW = Base64.getEncoder().encodeToString(hashBytes);
     // 将盐也转成Base64字符串,和哈希拼接后存储
     String storedValue = Base64.getEncoder().encodeToString(salt) + ":" + hashedPW;
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
     e.printStackTrace();
}
哈希验证思路

验证时需要从存储内容中拆分出盐和哈希值:

  1. 按存储时用的分隔符拆分字符串,得到盐的Base64字符串和哈希的Base64字符串。
  2. 将盐的Base64字符串解码回字节数组。
  3. 用相同的PBKDF2参数(输入密码、盐、迭代次数、密钥长度)重新生成哈希。
  4. 用Arrays.equals()比较新生成的哈希字节数组和存储的哈希字节数组(或转成字符串后比较)。

内容的提问来源于stack exchange,提问作者Jeremy Romano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 20:55:20