在Java中使用Bouncy Castle的SHA-256哈希和AES密码存储
问题描述:
我是新来的密码存储和Bouncy城堡。在Java中使用Bouncy Castle的SHA-256哈希和AES密码存储
- 加密:是否有一个理由,更喜欢Pkcs5S2ParametersGenerator 了AES加密(盐+哈希(密码+盐))?
- 举例:How to encrypt and salt the password using BouncyCastle API in Java?
- 我的Java代码:有没有更好的方法从密码中取回salt比字节数组提取?
这里是我的Java代码:
// salt
java.security.SecureRandom rgen = new SecureRandom();
byte[] salt = rgen.generateSeed(20);
// add Bouncy Castle
java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
// aes secret key
javax.crypto.KeyGenerator kgen = KeyGenerator.getInstance("AES", "BC");
Key cleSecrete = kgen.generateKey();
// aes
javax.crypto.Cipher cipher = Cipher.getInstance("AES", "BC");
// sha-256
java.security.MessageDigest sha256 = MessageDigest.getInstance("SHA-256","BC");
// hash the clear password with the salt to avoid collisions
byte[] motDePasseHash = hasherSaler(motDePasseClair.getBytes("UTF-8"),salt);
// Encrypt the hash with the salt to get the salt back
byte[] chiffreBDD = chiffrerSalerHash(salt,motDePasseHash,cleSecrete);
// Store the cipher in DB
...
// Get back the hash and the salt from DB
byte[] deChiffreBDD = deChiffrer(chiffreBDD,cleSecrete);
byte[] saltBDD = extraireOctets(deChiffreBDD,0,19);
byte[] hashBDD = extraireOctets(deChiffreBDD,20,deChiffreBDD.length-1);
// hash the user intput
byte[] motDePasseHashCandidat = hasherSaler(motDePasseClairCandidat.getBytes("UTF-8"),saltBDD);
// Compare hased user input with DB hash
boolean isMotDePasseOK = Arrays.equals(hashBDD,motDePasseHashCandidat);
private final byte[] hasherSaler(byte[] clair,byte[] salt) {
byte[] concat = concatenerOctets(clair,salt);
return sha256.digest(concat);
}
private final byte[] chiffrerSalerHash(byte[] salt,byte[] hash, Key cle) {
cipher.init(true,cle);
return cipher.doFinal(concatenerOctets(salt,hash));
}
private final byte[] deChiffrer(byte[] chiffre, Key cle) {
cipher.init(false,cle);
return cipher.doFinal(chiffre);
}
谢谢。
答
如果你只是想验证密码,你应该只使用PBKDF2(或bcrypt/scrypt)。密码不应该是必需的。盐可以不加密地存储。您可能希望使用额外的秘密来附加到您保存在其中的盐,例如源代码。不要忘记将密码存储在协议中,否则您将无法再升级。
至于你的代码,你不应该使用盐generateSeed
。你应该使用更多的update
。 "AES"
默认使用ECB模式,因此请指定其他模式。不要依赖违约。使用(可能派生的)IV。不必要时不要明确使用提供者。
好的,我可以继续相当长一段时间,但现在必须做。
此代码是否运行?我没有看到任何'Cipher.init()'调用。或者这是一个原型? – 2014-10-02 13:07:12
它不运行,它现在在我的文本编辑器中。我想先收集必要的步骤。 – Fanilo 2014-10-02 13:46:04
你说我的aes密码没有启动向量?非常感谢 ! – Fanilo 2014-10-02 13:57:52