Michele Mariotti
Michele Mariotti

Reputation: 7449

AES random key generation

I see many examples where the secret key is generated this way:

KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(KEY_LEN);
SecretKey secretKey = generator.generateKey();

I'm in doubt if there's a difference (even conceptual) with the following:

byte[] material = new byte[KEY_LEN / Byte.SIZE];
SecureRandom.getInstanceStrong().nextBytes(material);
SecretKey secretKey = new SecretKeySpec(material, "AES");

Stated that both methods are 3 lines, is there some practical impact in preferring the first over the second?

Thanks

Upvotes: 2

Views: 1124

Answers (3)

Maarten Bodewes
Maarten Bodewes

Reputation: 93948

There are many reasons why you would want to use the KeyGenerator method, which was designed for the purpose:

  • readability: generateKey tells you exactly what the algorithm is doing;
  • portability: e.g. when choosing a different algorithm);
  • correctness: SecretKeySpec may not validate the key entirely;
  • security: you would leave the key material exposed in the material variable, which may not be cleared or even garbage collected after the key is not required anymore;
  • hardware support: importing key material is often not supported for hardware devices; keys should be generated on the device itself (using a specialized KeyFactory implementation).

There is no reason at all to use the second method. If you want to use a very specific random number generator for generating the key then you can use one of the specialized init methods but beware that this may not be compatible with hardware devices.

Upvotes: 2

gusto2
gusto2

Reputation: 12075

The two code examples seem to be doing the same and as already answered usually they are.

However using security devices (e. g. HSM, smartcards or other crypto devices) by default they won't allow exposing the key bytes so you would be able to generate a key from arbitritrary byte array only in very limited cases..

Upvotes: 2

President James K. Polk
President James K. Polk

Reputation: 41958

You could look at the actual source code for generateKey() to see the difference but ultimately they are both going to do the same steps to generate an AES key. I would argue the latter

byte[] material = new byte[KEY_LEN / Byte.SIZE];
SecureRandom.getInstanceStrong().nextBytes(material);
SecretKey secretKey = new SecretKeySpec(material, "AES");

is a little more brittle for the average coder, requiring them to understand the SecureRandom class. If you eliminate the second line altogether the code runs just fine with an all zero key, an obvious vulnerability that's also easy for an attacker to check. Also, using generateKey() can produce a properly formatted key if the algorithm has some particular requirements. For example, the now obsolete DES and Triple DES algorithms had a weird parity bit in each byte that some DES implementations expected to see.

Upvotes: 5

Related Questions