java AES:如何为每个算法大小从密码生成密钥
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7467798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AES: how to generate Key from password for every algorithm size
提问by Mister Smith
Is it possible to write a single method that generates valid Keys from a password for AES-128, AES-192 and AES-256?
是否可以编写一种从 AES-128、AES-192 和 AES-256 的密码生成有效密钥的方法?
I'm thinking in something like this:
我在想这样的事情:
SecretKeyFactory f;
try {
f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
} catch (NoSuchAlgorithmException e) {
throw new Exception("Key derivation algorithm not available.", e);
}
KeySpec ks = new PBEKeySpec(password.toCharArray());
SecretKey s;
try {
s = f.generateSecret(ks);
} catch (InvalidKeySpecException e) {
throw new Exception("Key generation failed.", e);
}
Key k = new SecretKeySpec(s.getEncoded(),"AES");
I was using a similar approach to generate salted Keys for AES-256. However, now I have to generate Keys just from a password (with no salt and no iterations), and I need them to work for AES-128, AES-192 and AES-256. My question is, does this code return Keys compatible with every AES-XXX size, or should I write diferent code for each size?
我使用类似的方法为 AES-256 生成加盐密钥。但是,现在我必须仅从密码生成密钥(没有盐和没有迭代),我需要它们为 AES-128、AES-192 和 AES-256 工作。我的问题是,此代码是否返回与每个 AES-XXX 大小兼容的密钥,还是我应该为每个大小编写不同的代码?
Also, is there a better (in terms of security or simplicity) way of generating a Key from a password?
另外,是否有更好的(在安全性或简单性方面)从密码生成密钥的方法?
UPDATE: Finally I made some tests and it turns out that this constructor:
更新:最后我做了一些测试,结果是这个构造函数:
KeySpec ks = new PBEKeySpec(password.toCharArray());
Always throws an InvalidKeySpecException on this block:
始终在此块上抛出 InvalidKeySpecException:
try {
s = f.generateSecret(ks);
} catch (InvalidKeySpecException e) {
throw new Exception("Key generation failed.", e);
}
So I'm stuck with the other constructor, that needs a salt as parameter:
所以我坚持使用另一个构造函数,它需要一个盐作为参数:
KeySpec ks = new PBEKeySpec(password.toCharArray(), "somepredefinedsalt".getBytes(), numIters, keySizeInBits);
As I don't have a salt, I've thought in hardcoding a predefined one. Now I don't know which option is more secure, coding a predefined salt ant using PBKDF2 or using a truncated hash.
因为我没有盐,所以我想硬编码一个预定义的。现在我不知道哪个选项更安全,使用 PBKDF2 或使用截断的哈希编码预定义的盐蚂蚁。
回答by curiousguy
If you can, do not do that.A user selected password typically has very poor entropy.
如果可以,请不要这样做。用户选择的密码通常具有非常差的熵。
Ifthe "password" is not user selected, but instead produced by a cryptographically strongRNG, use the password, or a hash of the password. In this case, you do not need PBKDF2.
如果“密码”不是用户选择的,而是由加密的强RNG 生成的,请使用密码或密码的散列。在这种情况下,您不需要 PBKDF2。
PBKDF2 is really the last resort solution.
PBKDF2 确实是最后的解决方案。
Please also read Lessons learned and misconceptions regarding encryption and cryptology
另请阅读有关加密和密码学的经验教训和误解
回答by Ivo
Truncate a 256bit length key to the size needed. The key should be random, or generated using a secure method such as PBKDF2. If in doubt, hash for more length / even-randomness-distribution before truncating.
将 256 位长度的密钥截断为所需的大小。密钥应该是随机的,或者使用诸如 PBKDF2 之类的安全方法生成。如果有疑问,请在截断之前散列更多长度/偶数随机分布。
You can also see that PBEKeySpecallows you to optionally specify the key length.
您还可以看到PBEKeySpec允许您有选择地指定密钥长度。