我目前正在研究Raspberry Pi与Android设备之间的连接。
此连接使用河豚加密,并且在较小的大小(通常小于1 kB)下似乎可以正常工作。在下一步中,我尝试将照片从我的Pi发送到我的设备,该照片也应加密。我的设备抛出异常javax.crypto.BadPaddingException: pad block corrupted,经过一些调试后,我发现传输的数据中约有90%设置为零(使用大小为2444368的数组进行测试,位置212536之后,一切均为零)。

我的第一个猜测是Android不能为我的数组分配足够的内存,但是也没有异常告诉我,在我告诉Android我的应用通过largeHeap=true使用了很多ram之后,这不再是问题了。可能是因为我对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;
}


服务器端:

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


经过更多测试后,我发现树莓派无法正确发送数据,因此我现在尝试按块发送数据。

最佳答案

我怀疑您的问题是对in.read的调用没有读取整个输入流。 InputStream.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的返回值以查看实际读取了多少字节。

10-07 20:12
查看更多