2

I read some examples about using Java Cipher to encrypt and decrypt data. For example:

KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = new SecureRandom();
keyGenerator.init(256, secureRandom);
SecretKey secretKey = keyGenerator.generateKey();
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, secretKey);

I have 2 questions about the decryption process.

  1. Although an IV is required, we can leave it implicit by using Cipher.init(Cipher.ENCRYPT_MODE, Key). A random IV will be automatically applied to it. However, in decryption mode, the same IV must be used. Does it mean only the Cipher.init(int opmode, Key key, AlgorithmParameters params) should be used and the IV should be get from the encryption, stored and passed here?

Beside the '''KeyGenerator''', I also saw the example to generate key with '''SecretKeyFactory''':

String key = ...
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
SecretKeySpec keySpec = factory.generateSecret(new DESKeySpec(key));

I suppose I can use it for AES if I change last line to

SecretKeySpec keySpec = factory.generateSecret(new SecretKeySpec(key,"AES"));
  1. I am confused about when to use SecretKeyFactory to generate a key and when to use KeyGenerator. It seems the latter is generate a random key, the former is generated from a given key material. So does it mean in decryption mode, only SecretKeyFactory can be used?
Ya Xiao
  • 861
  • 8
  • 16

1 Answers1

0

Does it mean only the Cipher.init(int opmode, Key key, AlgorithmParameters params) should be used and the IV should be get from the encryption, stored and passed here?

Yes, exactly that, unless you are able to communicate it in other ways. Generally though the IV is randomized during encryption, then prefixed to the ciphertext. For AES-CBC it is always the same size as the block size: 16 bytes.

So does it mean in decryption mode, only SecretKeyFactory can be used?

Yes, although for AES there is a neat little shortcut; you can simply do:

SecretKey aesKey = new SecretKeySpec(keyBytes, "AES");

and be done with it. This is because SecretKeySpec implements SecretKey. For 3DES keys that's not a good idea because it would mean that the parity bits of DES are not set correctly. However, modern keys such as AES keys and HMAC keys solely consist of random data, so for those it is fine. There is one caveat: it will be a problem if you try and generate a key in a hardware device that way: it must be kept in software.

Note that I won't delve too much in key management and how keys need to be created. I've answered that question here, although that answer is certainly far from complete. Heck you could use dice and share the numbers over the phone for all I care :)

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Thank you for answer. Is there any difference between ```SecretKey aesKey = new SecretKeySpec(keyBytes, "AES")```; and ```SecretKeySpec keySpec = factory.generateSecret(new SecretKeySpec(keyBytes,"AES"))```; ? I saw some cases always use the generateSecret again after obtaining a SecretKey. Is it necessary or just useless? – Ya Xiao Apr 15 '20 at 01:21
  • For AES keys in software it really shouldn't matter. I slightly prefer the factory method because of hardware and software tricks that may make the AES key more secure. But as far as I can see, no such trickery is currently involved, so... Anyway, way too late, cannot spend all my time on my crypto book :) – Maarten Bodewes Apr 15 '20 at 01:23