2012-09-01 2 views
4

누구나 BouncyCastle에서 AES와 함께 GCM 및/또는 CCM 모드를 사용하는 예를 제공 할 수 있습니까?
내 코드는 이것이다 :BouncyCastle GCM/CCM ArrayIndexOutOfBoundsException

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 모드에서 암호화 할 때

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) 

그리고이 예외 (선은 70이다 bOut.write(block, 0, i);) CCM 모드의

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) 
+0

나는 당신이 어떤 라인 70인지에 대해 착각했다고 생각한다. 'while ((i = cIn.read (block))! = -1)'입니까? –

+0

@DuncanJones : 아니요,'.write' 라인입니다! – RYN

답변

6

조금하다가가 다음 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에 사용됩니다) : 귀하의 코드는 다음에 충돌합니다.

이 호출 될 때뿐만 아니라 CipherInputStream이 기본 스트림에서 데이터를 검색 할 수없는 경우 cipher.doFinal() 메서드가 모두 호출되는 다른 문제가 있습니다. CipherInputStream은 던져 질 때 BadPaddingException을 제거하는 매우 잘못 작성된 클래스입니다. 이것은 태그 유효성 검사가 실패 할 때 예외입니다 (!!!). CipherInputStream을 기반으로 자신 만의 광고를 만드는 것이 좋습니다. 예외를 무시하는 대신 특정 IOException 기반 예외를 throw하고 doFinal()이 기본 암호에서 실행되었는지 확인하기 위해 boolean 상태를 유지하는 코드로 변경했습니다. doFinal() 번을 두 번 호출해서는 안됩니다.

그래서 Java JCE 버그로 실행 중입니다. Oracle 버그 데이터베이스에 넣을 수 있습니다. 지금까지 모든 버그 보고서가 완전히 무시 된 것입니다.

최신 버전의 OpenJDK 7 및 Bouncy Castle 1.47 (2012-08-30 또는 가까운 버전)에 대해 테스트되었습니다.

+0

닫기 호출을 제거하면 코드가 실행되어야하지만 인증 방법이 필요하지 않습니다. –

관련 문제