谁能给我一个在BouncyCastle中将GCM和/或CCM模式与AES一起使用的示例吗?
我的代码是这样的:
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();
但是在GCM模式下解密时会抛出此异常(第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)
而在CCM模式下进行加密时,此异常(第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)
最佳答案
对于CCM模式,有一点障碍:IV的大小应小于块大小。您的代码在以下情况下崩溃:
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);
尝试使用15字节的“IV”代替它(IV实际上是NONCE,但是
IvParameterSpec
用于NONCE)。另一个问题是,当
cipher.doFinal()
无法从基础流中检索任何数据时以及调用CipherInputStream
时,都会调用close()
方法。请注意,CipherInputStream
是一个编写得很差的类,当抛出BadPaddingException
时也会删除CipherInputStream
-这是在标签验证失败时得到的异常(!!!)。您最好基于IOException
创建自己的代码。我已更改为代码,以引发基于特定boolean
的异常,而不是忽略异常,并保持doFinal()
状态以查看doFinal()
是否已在基础密码上执行。它不应两次调用ojit_code。因此,您正在此处运行Java JCE错误。我可能会将其放在Oracle bug数据库中,直到现在我所有的bug报告都已被完全忽略。
已针对最新版本的OpenJDK 7和Bouncy Castle 1.47(2012-08-30或类似版本)进行了测试。