2014-02-22 80 views
0

儘管我發現很多關於同一問題的帖子,但我無法解決我的問題。javax.crypto.IllegalBlockSizeException使用AES

我正在使用c#服務器和一個java客戶端(將來會是android)。好奇的是我正在發送/接收很多更長,更復雜的json字符串,並且只是最短和最簡單的失敗。

這是客戶端的代碼:

private static byte[] asegurarCapacidad(byte[] inicial, int tamano){ 

    if(inicial.length<tamano){ 

     return Arrays.copyOf(inicial, tamano);   
    } 

    return inicial; 
}  

    private static String leer(Socket s){ 

    byte[] buffer=new byte[4092]; 
    byte[] bufferFinal = new byte[8092]; 
    int leido=0; 
    int posicion=0; 
    String salida = null; 

    try {  
     SecretKey key = new SecretKeySpec("1212121212121212".getBytes("UTF-8"),"AES"); 
     DataInputStream dis=new DataInputStream(s.getInputStream()); 
     while((leido=dis.read(buffer))>0){ 
      bufferFinal=asegurarCapacidad(bufferFinal,posicion+leido); 
      System.arraycopy(buffer, 0, bufferFinal, posicion, leido); 
      posicion+=leido; 
     } 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.DECRYPT_MODE, key,iv); 
     salida=decodificar(cipher.doFinal(bufferFinal)); 

    } catch (Throwable e) { 
     System.out.println("CLIENTE: ERROR AL LEER: "+e); 
     e.printStackTrace(); 
    } 

    return salida; 
} 

這是服務器的代碼:

private static byte[] codificar(string mensaje) 
    { 
     return System.Text.Encoding.UTF8.GetBytes(mensaje); 
    } 

    private static void escribir(Socket s, string mensaje) 
    { 
     byte[] buffer = new byte[mensaje.Length]; 
     buffer = codificar(mensaje); 

     AesCryptoServiceProvider aes = new AesCryptoServiceProvider(); 
     aes.KeySize = 128; 
     aes.BlockSize = 128; 
     aes.Key = bytKey; 
     aes.Mode = CipherMode.CBC; 
     aes.Padding = PaddingMode.PKCS7; 
     aes.IV = iv; 
     ICryptoTransform AESEncrypt = aes.CreateEncryptor(); 
     buffer = AESEncrypt.TransformFinalBlock(buffer, 0, buffer.Length); 
     s.Send(buffer); 
    } 

任何建議將受到歡迎。

+0

不是專家,但你使用PKCS7填充加密,並與PKCS5Padding解密。我的猜測是,你用Java讀取字節的方式是不正確的:你將bufferFinal分配給一個大字節數組,然後立即用asegurarCapacidad()的結果重新分配它,這沒有顯示。爲什麼不將每個讀取的字節都發送給ByteArrayOutputStream,或者直接發送給Cipher? –

+0

@JBNizet PKCS#7和PKCS#5基本上是相同的,只是名稱不同(除了PKCS#5僅針對64位塊定義,因此在Java中有點用詞不當)。 – ntoskrnl

+0

@ntoskrnl:謝謝你的信息。 –

回答

0

您有一個8092字節的緩衝區(bufferFinal)。假設輸入流只包含1000個字節。您的代碼讀取這些1000個字節,並呼籲

asegurarCapacidad(bufferFinal, posicion + leido); 

其中posicion是0和leido是1000

asegurarCapacidad()執行以下操作的方法:

if (inicial.length < tamano) { 
    return Arrays.copyOf(inicial, tamano);   
} 

return inicial; 

其中inicial.length是8092和tamano是1000 。因此它返回未修改的緩衝區。

所以你最終得到一個8092字節的緩衝區,其中包含從輸入流中讀取的1000字節,而7092字節設置爲0.這就是你傳遞給Cipher的內容,而不是隻傳遞1000個第一個字節。

它有效,當你有一個更大的文本作爲輸入,因爲asegurarCapacidad()最終返回一個大於8092字節的緩衝區只包含加密字節。但是,你的代碼是無效的(它的每一次重新分配一個新的數組),並且可以更簡單:

byte[] buffer = new byte[8092]; 
try {  
    InputStream in = s.getInputStream(); 

    SecretKey key = new SecretKeySpec("1212121212121212".getBytes("UTF-8"),"AES"); 
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    cipher.init(Cipher.DECRYPT_MODE, key, iv); 

    while ((leido = in.read(buffer)) > 0) { 
     cipher.update(buffer, 0, leido); 
    } 

    salida = decodificar(cipher.doFinal()); 
+0

感謝您的幫助。現在異常消失了。但是,我只收到我收到的每個json字符串的最後3個字符。 –