PBKDF2-HMAC-SHA256 for JAVA 的可靠实现

Posted

技术标签:

【中文标题】PBKDF2-HMAC-SHA256 for JAVA 的可靠实现【英文标题】:Reliable implementation of PBKDF2-HMAC-SHA256 for JAVA 【发布时间】:2014-04-30 02:59:18 【问题描述】:

2019 年更新:Bouncycastle 现在支持 PBKDF2-HMAC-SHA256,因为 bouncycastle 1.60


对于 JAVA 是否有可靠的 PBKDF2-HMAC-SHA256 实现?

我曾经使用 bouncycastle 加密,但它不提供 PBKDF2WithHmacSHA256'。

我不想自己写加密模块。

您能否推荐任何替代库或算法(如果我可以坚持使用 bouncycastle)

(这里是 bouncycastle 支持的算法) http://www.bouncycastle.org/specifications.html

【问题讨论】:

***.com/questions/9147463/… @KonstantinV.Salikhov 我已经阅读过,但很难相信它已被完全证明。如果我使用它,我必须为 Jasypt API 实现代码 未来读者:见mkyong.com/java/java-aes-encryption-and-decryption 【参考方案1】:

直接使用 BouncyCastle 类:

PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest());
gen.init("password".getBytes("UTF-8"), "salt".getBytes(), 4096);
byte[] dk = ((KeyParameter) gen.generateDerivedParameters(256)).getKey();

【讨论】:

【参考方案2】:

它在 Java 8 中可用:

public static byte[] getEncryptedPassword(
                                         String password,
                                         byte[] salt,
                                         int iterations,
                                         int derivedKeyLength
                                         ) throws NoSuchAlgorithmException, InvalidKeySpecException 
    KeySpec spec = new PBEKeySpec(
                                 password.toCharArray(),
                                 salt,
                                 iterations,
                                 derivedKeyLength * 8
                                 );

    SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");

    return f.generateSecret(spec).getEncoded();

【讨论】:

奇怪,我无法让 Java 8 版本正常工作。它生成了输出,但输出不同于 Bouncy Castle 和等效的 Node.js @Kirby 确保你只使用 ASCII,Java 8 有点奇怪,因为它只使用 char 的低 8 位(即 Windows-1252 兼容的字符编码)。跨度> 像魅力一样工作。顺便说一句,如果您想使用 512 字节的摘要,只需将“PBKDF2WithHmacSHA256”更改为“PBKDF2WithHmacSHA512”即可。 @MaartenBodewes 它使用UTF8.encodechar[] 转换为ByteBuffer。 IE。 7 位 ASCII 以外的任何内容都会生成多字节序列,如果与 UTF-16 字节序列进行比较,这会给您带来意想不到的结果,但这是因为编码是意外的,而不是因为 Java 忽略了某些东西。 @toolforger 来自PBEKeySpec (Java 14):不同的 PBE 机制可能会占用每个密码字符的不同位。例如,PKCS #5 中定义的 PBE 机制只查看每个字符的低 8 位,而 PKCS #12 则查看每个字符的所有 16 位。 PKCS#5 中指定了 PBKDF2。因此,如果使用 UTF-8,那么文档就不合适了。你能说明你在哪里找到了编码函数吗?【参考方案3】:

使用 spongycastle(android 上的 java)

如果你直接在 java 上使用 bouncycastle 的话,用 bouncycastle 替换 spongycastle

import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.spongycastle.crypto.digests.SHA256Digest;
import org.spongycastle.crypto.params.KeyParameter;

public class Crypto 
    public String pbkdf2(String secret, String salt, int iterations, int keyLength) 
        PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest());
        byte[] secretData = secret.getBytes();
        byte[] saltData = salt.getBytes();
        gen.init(secretData, saltData, iterations);
        byte[] derivedKey = ((KeyParameter)gen.generateDerivedParameters(keyLength * 8)).getKey();    
        return toHex(derivedKey);
    

    private static String toHex(byte[] bytes) 
        BigInteger bi = new BigInteger(1, bytes);
        return String.format("%0" + (bytes.length << 1) + "x", bi);
    

【讨论】:

以上是关于PBKDF2-HMAC-SHA256 for JAVA 的可靠实现的主要内容,如果未能解决你的问题,请参考以下文章

PBKDF2-HMAC-SHA2 测试向量

PBKDF2-HMAC-SHA1

加密 NSString AES256EncryptWithKey 和 AES256DecryptWithKey for ios

ja对象属性—枚举检查删除

crypto-js计算文件的sha256值

错误提示:The project was not built since its build path is incomplete. Cannot find the class file for ja