Search code examples
javaencryptionaes

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 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.


Solution

  • 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