AES: how to generate key from password for every algorithm size
Is it possible to write a single method that generates valid keys from a password for AES-128, AES-192, and AES-256?
I'm thinking in something like this:
SecretKeyFactory f;
try {
f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
} catch (NoSuchAlgorithmException e) {
throw开发者_如何学Go 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 different code for each size?
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:
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 a parameter:
KeySpec ks = new PBEKeySpec(password.toCharArray(), "somepredefinedsalt".getBytes(), numIters, keySizeInBits);
As I don't have a salt, I've thought of hardcoding a predefined one. Now I don't know which option is more secure, coding a predefined salt and using PBKDF2 or using a truncated hash.
If you can, do not do that. A user selected password typically has very poor entropy.
If the "password" is not user selected, but instead produced by a cryptographically strong RNG, use the password, or a hash of the password. In this case, you do not need PBKDF2.
PBKDF2 is really the last resort solution.
Please also read Lessons learned and misconceptions regarding encryption and cryptology
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.
You can also see that PBEKeySpec allows you to optionally specify the key length.
精彩评论