-1

I am attempting to encrypt/decrypt strings using AES-256-CBC and BouncyCastle. I have completed this for keys that are of length 16 bytes (128 bits) but I am required to use a key of 128 bytes (1024 bits).

I have read numerous suggestions on SO and found that the restricted policy files for the JVM I am using had not been installed. This, theoretically, should allow keys greater than 128 bits to be used. However, after installing the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction policy files to my jdk (1.6.0.jdk/Contents/Home/lib/security) the issue remains.

The code I am using to encrypt a String is as follows:

String my_key =  "2bc7fa12d..." // String of length 128

Security.addProvider(new BouncyCastleProvider());

byte[] original = my_key.getBytes();
key = new SecretKeySpec(original, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encrypted = cipher.doFinal(toEncrypt.getBytes());
byte[] encryptedValue = Base64.encode(encrypted);

return new String(encryptedValue);

But after replacing the .jar's found in the Unlimited JCE download I still experience the error:

java.security.InvalidKeyException: Key length not 128/192/256 bits.
    at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(Unknown Source)
    at javax.crypto.Cipher.init(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    at EncyrptionTest.encrypt(EncyrptionTest.java:58)
    at EncyrptionTest.main(EncyrptionTest.java:33)

Any advice or solutions to this issue would be greatly appreciated.

Edit:

As requested, the code I am trying to port from Ruby into Java is as follows:

 WithCred.entials_for(:to_encrypt) do |c|
    attr_encrypted :my_key,
      :algorithm => 'aes-256-cbc',
      :key => c[:key]
  end

The gem it uses to encrypt (I believe) is attr_encypted. (I am afraid I know very little about Ruby)

Ed Holloway-George
  • 5,092
  • 2
  • 37
  • 66
  • It -should- work (been there myself), so are you really, really sure that the runtime you updated is the runtime that is used to run this stuff? I see it is going into a lib of a JDK, that is not the lib of a runtime. Generally it is easy to know you did it right because you have to overwrite existing files. – Gimby Jul 03 '14 at 15:26
  • Secondary: are you sure AES supports such keys? If I quickly scan the wiki, I don't think so. I used a different encryption methodology myself. http://en.wikipedia.org/wiki/Advanced_Encryption_Standard – Gimby Jul 03 '14 at 15:29
  • @Gimby Not sure, I am porting some ruby code that is able to encrypt using a key of that length!? It is driving me bananas – Ed Holloway-George Jul 03 '14 at 15:45
  • 1
    Exception message explicitly lists key sizes supported by AES. 1024 bit keys could mean RSA or some other asymmetric cipher. – Oleg Estekhin Jul 03 '14 at 16:34
  • Please show us the ruby code, otherwise this question is going nowhere. Maybe you should learn something about cryptography before continuing? – Maarten Bodewes Jul 03 '14 at 16:38
  • @owlstead I have updated the question to provide the ruby code and the gem I believe it is using to encrypt. – Ed Holloway-George Jul 03 '14 at 16:56
  • Thank you @OlegEstekhin, but I am told it is _"definitely AES-256-CBC"_ (even though I am not convinced). – Ed Holloway-George Jul 03 '14 at 17:08

1 Answers1

0

You need to perform (the old, deprecated) MD5 key generation that is used in OpenSSL. Your Ruby code points to this source file. So the key is not really a key, it's a password which is converted to a key. Note that it uses MD5, doesn't use a salt and that it uses 2000 iterations by default.

Finally, it comes back to this:

EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt,
               (unsigned char *)RSTRING_PTR(vpass), RSTRING_LEN(vpass), iter, key, iv);

Of course you then need this OpenSSL proprietary key derivation option in Java. Fortunately, you wouldn't be the first one to require OpenSSL compatibility:

How to decrypt file in Java encrypted with openssl command using AES?

I apologize in advance that I did not post my object oriented implementation instead in that answer :)

Community
  • 1
  • 1
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • One thing has left me wandering though. `EVP_BytesToKey` actually returns the size of the hash generated. This is ignored in the Ruby code. The rest of the key bytes are simply generated by `unsigned char key[EVP_MAX_KEY_LENGTH]`. What will be in the bytes that are *not* generated by `EVP_BytesToKey`? I probably don't want to know... – Maarten Bodewes Jul 03 '14 at 17:27
  • Thanks for your response, but this seems to be quite confusing. Is there an `openssl` command on the terminal that can be used to get the password? – Ed Holloway-George Jul 04 '14 at 12:38
  • Does this code also require a password? I apologise, but I am not sure how to use the link you provided to help. Converting `my_string` to `byte[]` and putting it in the function you provided causes the error `javax.crypto.BadPaddingException: pad block corrupted` – Ed Holloway-George Jul 04 '14 at 14:29
  • Did you put in the same number of iterations/count? Oh, and you may want to put in keyLength as 16, the output size of MD5. Then copy the result into a new array of the right size (because of the issue above). – Maarten Bodewes Jul 05 '14 at 07:44
  • Note that you will get a BadPaddingException when the key is incorrect, or when one or two of the last blocks of ciphertext has become corrupted.. – Maarten Bodewes Jul 05 '14 at 15:47