2
votes

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

2
A salted, lengthened hash is pretty strong. You could just truncate the result to whatever length you need after generating 256 bits.user684934
@bdares If I use a portion of a 256 bit hash to get a key of 128 or 192 bits, then two different passwords could generate the same truncated key.Mister Smith
that, alas, is so very true. Unfortunately, an infinite number of passwords could generate the same key with hashing functions. You just have to take solace in the fact that it's really bloody difficult to intentionally do it.user684934
Each bit is very hard to predict, so predicting and colliding just the top 128 bits, or the bottom 128 bits, or every other bit, is just as hard (per bit). That's why it's a desirable property of cryptographic hashes. If you consider that they're effectively random from the attacker's point of view, a subset of a random set of digits is still random, and is just as good as another, smaller, differently generated random set of numbers.user684934
@MisterSmith "then two different passwords could generate the same truncated key" It's ridiculously unlikely. If you care about such odds, why not assume your adversary can find the 128 bits key by randomly trying 128 bits numbers? ;)curiousguy

2 Answers

3
votes

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

0
votes

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.