Java BouncyCastle GCM/CCM阵列索引边界外异常

Java BouncyCastle GCM/CCM阵列索引边界外异常,java,cryptography,aes,bouncycastle,aes-gcm,Java,Cryptography,Aes,Bouncycastle,Aes Gcm,有谁能给我一个在BouncyCastle中使用AES的GCM和/或CCM模式的例子吗? 我的代码是: SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); IvParameterSpec ivSpec = new IvParameterSpec(ivBytes); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC"); byte[] block =

有谁能给我一个在BouncyCastle中使用AES的GCM和/或CCM模式的例子吗?
我的代码是:

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);
):

在CCM模式下加密时出现此异常(第70行是
bOut.write(块,0,i);
):


对于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()
方法在
cipheriputstream
无法从底层流检索任何数据时调用,以及在调用
close()
时调用。请注意,
CipherInputStream
是一个编写非常糟糕的类,在抛出时也会删除
BadPaddingException
——这是标记验证失败时得到的异常(!!!)。您最好基于
CipherInputStream
创建自己的一个。我已更改代码,以抛出基于特定
IOException
的异常,而不是忽略异常,并保持
boolean
状态,以查看是否已对底层密码执行了
doFinal()
。它不应该调用
doFinal()
两次

因此,您在这里运行的是一个JavaJCE错误。我可能会把它放在Oracle bug数据库中,但到目前为止,我所有的bug报告都被完全忽略了


针对最新版本的OpenJDK 7和Bouncy Castle 1.47(2012-08-30或类似版本)进行测试。

我认为您对第70行的定义是错误的。它不是
而((i=cIn.read(block))!=-1)
?@DuncanJones:不,它是
。write
行!若删除close调用,那个么代码应该运行,但不会得到任何身份验证,这就是关键所在。
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)
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);