I am trying to replace PBEWithMD5AndDES with PBEWithMD5AndTripleDES in existing code. So far, I am using the same passphrase that I was using before, and receiving this Exception:
java.security.InvalidKeyException: Illegal key size
I looked online and saw that DES uses a 64 bit key and TripleDES uses a 128 bit key. I am not clear on the details of how my passphrase is used to generate a key, and not sure where to look to understand this fully. My passphrase is 260 characters long. I tried doubling the length, but I get the same Exception.
I am generating a PBEKeySpec from my passphrase, with an 8 byte salt and an iteration count of 12. I see that there's another constructor that takes a keyLength argument, but the documentation describes it as "to be derived," and I don't understand that. I have the idea that I need to modify the iteration count and/or supply a keyLength argument, but I don't want to just do this blindly without fully understanding what I am doing.
Here is the basic outline of the code I'm currently using:
String passphrase = ...
byte[] salt = ...
int iterationCount = 12;
String algorithm = "PBEWithMD5AndTripleDES";
KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount);
SecretKey key = SecretKeyFactory.getInstance(algorithm).generateSecret(keySpec);
Cipher cipher = Cipher.getInstance(key.getAlgorithm());
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
byte[] encoded = cipher.doFinal(data);
This algorithm uses a 168-bit key (although due to vulnerabilities, it has an effective strength of 112 bits). To use a symmetric key of that length, you need the "unlimited strength jurisdiction policy" installed in your Java runtime.
An "Illegal key size" message indicates the key length is not permitted by policy; if the key length is incorrect for the algorithm, the SunJCE provider uses the message, "Wrong key size".
Note that "PBEWithMD5AndTripleDES" is a bad algorithm to use.
Password-based encryption generally follows PKCS #5. It defines an encryption scheme for DES (or RC2) called PBES1. Because PBES1 was designed to generate 64-bit (or less) keys, Oracle has created a proprietary extension to generate longer keys. It hasn't been exposed to the same scrutiny that PKCS #5 has, and if you need to inter-operate with any other platform, you'll have to dig into the source code to find out how the key and initialization vector are derived.
It's also strange that the initialization vector is derived from the password. The purpose of an IV is to create different cipher texts each time a given plain text is encrypted with the same key. If the IV is generated from the key, this purpose is defeated. The key-derivation algorithm used by PBES1 avoids this by incorporating a "salt" that is supposed to be different each time the password is used. But, it could be easy to screw this up; providing an IV directly to the cipher initialization is more conventional, and makes it more obvious what is happening.
PKCS #5 also defines an key-derivation algorithm called PBKDF2 that is now supported by Java. It provides superior security to PBES1 because the initialization vector and any other parameters required by the cipher are not derived from the password, but are selected independently.
Here's an example with PBKDF2, using AES. If you can't follow the recommendation to update to AES, the example can be applied to DESede by using a key length of 192, and changing occurrences "AES" to "DESede".
There are three keying options that can be used with TDEA ("Triple DES" or "DESede"). They take 64-, 128-, or 192-bit keys (including parity bits), depending on the option.
The key sizes accepted by the TDEA implementation depend on the provider; a few require you to form a 192-bit key, even if you are using the 56-bit key option which is effectively DES instead of TDEA. Most implementations will take 16 or 24 bytes as a key.
Only the three-key option (168 bits, or 192 bits with parity) can be considered "strong encryption". It has 112 bits of effective strength.
As erickson says, the "right" answer to this question is to install the unlimited strength jurisdiction policy files in the JRE.
That will make encryption with PBEWithMD5AndTripleDES "work," but the resulting data cannot be decrypted as far as I can tell. You will get a padding error exception. There may be some way to fix it, but this was proof enough to me that pursuing this route was not worth it as it seems to be a road that is not traveled enough to get the bugs worked out or to popularize working examples.
I also discovered a PBEWithSHA1AndTripleDES and tried it, but got the same padding error upon decryption.
I was able to get our requirements changed from PBEWithMD5AndTripleDES to just TripleDES (DESede), and that eliminated the whole issue for me!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With