2015-07-11 58 views
0

我目前正在研究我的Raspberry Pi和我的Android設備之間的連接。 這個連接是用blowfish加密的,似乎可以在較小的尺寸下正常工作(通常低於1 kB)。在下一步中,我嘗試從我的Pi發送一張照片到我的設備,該設備應該被加密。我的設備拋出異常javax.crypto.BadPaddingException: pad block corrupted,經過一些調試後,我發現大約90%的數據傳輸被設置爲零(使用大小爲2444368的數組進行測試,在位置212536之後所有數據都爲零)。Android - 流不能正確讀取數組

我的第一個猜測是Android無法爲我的陣列分配足夠的內存,但因爲沒有任何異常告訴我,所以我告訴Android,我的應用程序通過largeHeap=true使用很多內存,這不是問題了。這可能是因爲我對Android的工作方式不夠了解,所以我想請你幫助我。有問題的零部件(EncryptionUtil沒有顯示,這不是問題的一部分):

客戶端:

public final byte[] readWithAppend() throws IOException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException{ 
    byte[] b = new byte[read()]; //works fine, tells me the size of the array 
    System.out.println("Trying to read an array with the size " + b.length); 
    in.read(b,0,b.length);//No Exception here, so allocation works 
    if(b.length >= 10000){ //Just some debug for me to compare both sides, server and client. 
     File f; 
     FileOutputStream out = new FileOutputStream(f = new File(debugFile,EncryptionUtil.randomString(80))); 
     System.out.println("PATH: " + f); 
     out.write(b);out.close(); 
    } 
    System.out.println("After position " + searchPos(b) + " everything is 0 ?!?!?"); 
    b = EncryptionUtil.decrypt(enc, b, sessionKey); //The Exception gets thrown here. 
    return b; 
} 

private int searchPos(byte[] b){ 
    int pos = b.length; 
    for(int i = b.length-1;i >= 0;i--){ 
     if(b[i] != 0)return pos; 
     else pos--; 
    } 
    return pos; 
} 

Serverside集團:

private final void write(byte[] b,int off,int len,boolean appendLength) throws IOException{ 
    try { 
     byte[] b2; 
     if(len != b.length || off != 0){ //Just ignore this case 
      byte[] buffer = new byte[len-off];System.arraycopy(b, off, buffer, 0, len); 
      b2 = EncryptionUtil.encrypt(enc, buffer, sessionKey); 
     }else{ //This is the case we have to look at 
      b2 = EncryptionUtil.encrypt(enc, b, sessionKey); 
      System.out.println("Sending an array with the size " + b2.length); 
      System.out.println("Decrypting to check for mistakes"); 
      EncryptionUtil.decrypt(SymmetricEncryption.Blowfish, b2, sessionKey); //Debug. 
      if(b2.length >= 10000){ //Again, debug to compare the both files 
       FileOutputStream out2 = new FileOutputStream(new File("serverFile")); 
       out2.write(b2);out2.close(); 
      } 
     } 
     if(appendLength)write(b2.length); //Works as well 
     System.out.println("Length: " + b2.length + "; only writing: " + ((int)len/b.length)*b2.length);// it writes everything. 
     out.write(b2,0,((int)len/b.length)*b2.length); //The flush part happens somewhere else. 
    } catch (InvalidKeyException | NoSuchAlgorithmException| NoSuchPaddingException | IllegalBlockSizeException| BadPaddingException e) { 
     e.printStackTrace(); 
     //throw new IOException(e.getMessage()); 
    } 
} 

我知道,它需要一些時間來工作到我的代碼,但我會很感激,如果你能幫助我。

編輯: 關於EncryptionUtil

public static final byte[] encrypt(final SymmetricEncryption enc,final byte[] content,final SecretKey key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException { 
     final Cipher cipher = Cipher.getInstance(enc.toString()); 
     cipher.init(Cipher.ENCRYPT_MODE, key); 
     return cipher.doFinal(content); 
    } 

    public static final byte[] decrypt(final SymmetricEncryption enc,final byte[] text,final SecretKey key) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException { 
     final Cipher cipher = Cipher.getInstance(enc.toString()); 
     cipher.init(Cipher.DECRYPT_MODE, key); 
     return cipher.doFinal(text); 
    } 

更多的測試後的代碼我發現這些數據不會被我的樹莓派發送正確的,所以我想在現在的塊發送。

+0

我猜你的加密有問題 – rainash

+0

我正在使用'Blowfish/CBC/PKCS5Padding'進行加密,加密本身是通過Java提供的Ciper類進行的,沒有增加。看起來,Android將給定位置後的所有內容都設置爲零。 – Ch4t4r

+0

什麼是'','read()'做了什麼? 'in.read()'中沒有分配,緩衝區在這個階段已經被分配了。 –

回答

1

我懷疑你的問題是對in.read的調用沒有讀取整個輸入流。不保證讀取您請求的全部長度。這是相當正常的做法來讀取while循環中輸入流,讀入緩衝區,直到到達流的末尾 - 更像是:

byte[] buffer = new byte[1024]; 
int read; 

while ((read = in.read(buffer)) != -1) { 
    out.write(buffer, 0, read); 
} 
out.flush(); 
out.close(); 

請注意,您現有的代碼不會檢查返回值in.read查看實際讀取的字節數。

+0

它到目前爲止,但我瞭解到,沒有什麼是真正安全的網絡,所以你是對的。我做了一些更多的測試,看到問題實際上是服務器,現在我要將陣列拆分爲更小的陣列。但是,感謝您的回答 – Ch4t4r

+0

考慮到您的編輯,我自己打印了實際讀取的字節長度,並且它與陣列中只包含零的位置相匹配。我的猜測是Pi的TCP緩衝區不夠大,無法同時包含2MB的數據(但我非常懷疑) – Ch4t4r

+0

你是對的。我的Raspberry以塊的形式發送數據,因此我只讀取第一個塊。 爲了解決這個問題,我有兩個選擇:要麼讀直到我想要的大小滿足或使用由java提供的另一個流,這對我來說。我將我的字節包裝在一個ObjectStream中,並用它來傳輸它們。 – Ch4t4r