2015-07-11 52 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