BouncyCastle GCM / CCM ArrayIndexOutOfBoundsException

can someone give me an example of using GCM and / or CCM modes with AES in BouncyCastle?
My code is:

SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); IvParameterSpec ivSpec = new IvParameterSpec(ivBytes); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC"); byte[] block = new byte[1048576]; int i; long st,et; cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); BufferedInputStream bIn=new BufferedInputStream(new ProgressMonitorInputStream(null,"Encrypting ...",new FileInputStream("input"))); CipherInputStream cIn = new CipherInputStream(bIn, cipher); BufferedOutputStream bOut=new BufferedOutputStream(new FileOutputStream("output.enc")); int ch; while ((i = cIn.read(block)) != -1) { bOut.write(block, 0, i); } cIn.close(); bOut.close(); Thread.sleep(5000); cipher.init(Cipher.DECRYPT_MODE, key, ivSpec); BufferedInputStream fis=new BufferedInputStream(new ProgressMonitorInputStream(null,"Decrypting ...",new FileInputStream("output.enc"))); //FileInputStream fis=new FileInputStream("output.enc"); //FileOutputStream ro=new FileOutputStream("regen.plain"); BufferedOutputStream ro=new BufferedOutputStream(new FileOutputStream("regen.plain")); CipherInputStream dcIn = new CipherInputStream(fis, cipher); while ((i = dcIn.read(block)) != -1) { ro.write(block, 0, i); } dcIn.close(); ro.close(); 

but it throws this exception when decrypting in GCM mode (line 70 is equal to bOut.write(block, 0, i); ):

 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException at java.lang.System.arraycopy(Native Method) at org.bouncycastle.crypto.modes.CCMBlockCipher.processPacket(Unknown Source) at org.bouncycastle.crypto.modes.CCMBlockCipher.doFinal(Unknown Source) at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$AEADGenericBlockCipher.doFinal(Unknown Source) at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(Unknown Source) at javax.crypto.Cipher.doFinal(DashoA13*..) at javax.crypto.CipherInputStream.a(DashoA13*..) at javax.crypto.CipherInputStream.read(DashoA13*..) at javax.crypto.CipherInputStream.read(DashoA13*..) at enctest.Main.main(Main.java:70) 

And this is an exception when encrypting in CCM mode (line 70 bOut.write(block, 0, i); ):

 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException at java.lang.System.arraycopy(Native Method) at org.bouncycastle.crypto.modes.CCMBlockCipher.processPacket(Unknown Source) at org.bouncycastle.crypto.modes.CCMBlockCipher.doFinal(Unknown Source) at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$AEADGenericBlockCipher.doFinal(Unknown Source) at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(Unknown Source) at javax.crypto.Cipher.doFinal(DashoA13*..) at javax.crypto.CipherInputStream.a(DashoA13*..) at javax.crypto.CipherInputStream.read(DashoA13*..) at javax.crypto.CipherInputStream.read(DashoA13*..) at enctest.Main.main(Main.java:70) 
+4
source share
1 answer

In CCM mode, there is a small clue: IV size should be smaller than the block size. Your code failed:

 BlockCipher ctrCipher = new SICBlockCipher(cipher); byte[] iv = new byte[blockSize]; byte[] out; iv[0] = (byte)(((15 - nonce.length) - 1) & 0x7); System.arraycopy(nonce, 0, iv, 1, nonce.length); 

Try using "IV" of 15 bytes (IV is actually NONCE, but IvParameterSpec used for NONCE).

Another problem is that the cipher.doFinal() method is called when CipherInputStream cannot retrieve data from the underlying stream, as well as when close() called. Note that CipherInputStream is a very poorly written class that also BadPaddingException when it is thrown - this is the exception that you get when a tag check fails (!!!). You are better off creating your own, based on CipherInputStream . I switched to code to use specific exceptions based on IOException instead of ignoring exceptions and saving boolean state to see if doFinal() was executed on the base cipher. It should not call doFinal() twice.

So you are using Java JCE error here. I can put it in the Oracle Database, where so far all my error messages have been completely ignored.

Tested against the latest version of OpenJDK 7 and Bouncy Castle 1.47 (2012-08-30 or something close).

+6
source

All Articles