AES: how to generate key from password for every algorithm size

13,278

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

Share:
13,278
Mister Smith
Author by

Mister Smith

Android freak, but still a noob.

Updated on June 04, 2022

Comments

  • Mister Smith
    Mister Smith almost 2 years

    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.