简体   繁体   English

在PC和Android之间发送加密数据时,AES / CTR / NoPadding最后一块丢失

[英]AES/CTR/NoPadding last block is lost when sending encrypted data between PC and Android

I'm using AES/CTR/NoPadding algorithm to encrypt data sent using socket between PC and Android. 我正在使用AES / CTR / NoPadding算法来加密通过PC和Android之间的套接字发送的数据。

I wrote unit-test, it sends [1;512] bytes to Android device and receive back the same data - echo service. 我编写了单元测试,它向Android设备发送[1; 512]字节并接收回相同的数据-echo服务。 Received data must be equal to data that was sent. 收到的数据必须等于发送的数据。

Test client: 测试客户:

for (int n = 1; n <= 512; n++) {
... skip ...
    try {
        Object connection = socketFilter.openConnection(socket);
        in = new CipherInputStream(socket.getInputStream(), encryptor);
        out = new CipherOutputStream(socket.getOutputStream(), decryptor);

        byte buf[] = new byte[n];
        byte received[] = new byte[n];

        TestUtils.numbers(buf);

        out.write(buf, 0, buf.length);
        socket.shutdownOutput();

        int len = in.read(received, 0, received.length);

        if (buf.length != len) {
            System.err.println("Expected: " + buf.length + " but was: " + len);
        }
    }
    finally {
        ... skip close streams ... 
    }

}

Echo server: 回声服务器:

Socket clientSocket = socket.accept();
CipherInputStream in = new CipherInputStream(clientSocket.getInputStream(), decryptor);
CipherOutputStream out = new CipherOutputStream(clientSocket.getOutputStream(), encryptor);

try {
    byte buf[] = new byte[512];
    int len;

    if ((len = in.read(buf)) > 0) {
        out.write(buf, 0, len);
        out.close();
    }
}
finally {
    in.close();
    out.close();
}

I tested this code with localhost - all works fine. 我用localhost测试了此代码-一切正常。

When i testing it with Android device, the last block is lost if it's not full. 当我使用Android设备对其进行测试时,如果未满,则会丢失最后一个块。 So, if it was 30 bytes, then only 16 bytes received. 因此,如果它是30个字节,则仅接收到16个字节。

Messages from the test: 来自测试的消息:

... skip ...
Expected: 30 but was: 16
Expected: 31 but was: 16
Expected: 33 but was: 32
... skip ...
Expected: 207 but was: 192
Expected: 209 but was: 208
Expected: 210 but was: 208
... skip ...

What can be wrong? 有什么事吗

It seems that the problem is caused by the fact that Android and Hotspot JVM uses different Cipher Provider. 似乎该问题是由于Android和Hotspot JVM使用不同的密码提供程序这一事实引起的。

Android uses one called Bouncy Castle which has a known 'bug' in AES/CTR mode. Android使用一个叫做Bouncy Castle的城堡,该城堡在AES / CTR模式下具有一个已知的“错误”。 It will miss the last block when doing encryption/decryption. 进行加密/解密时,它将错过最后一个块。 (see many other stackoverflow questions) (请参阅其他许多stackoverflow问题)

If you want only CTR mode. 如果只需要点击率模式。 Known work around is that you implement it yourself on Android by generating blocks of keystream repeatedly "on the fly"(by encrypt byte array of 0's), and XOR them with your buffer. 已知的解决方法是,您可以在Android上自己实现它,方法是“动态”重复生成密钥流块(通过加密0的字节数组),然后将它们与缓冲区进行XOR。

Hope this helps 希望这可以帮助

Have you completely flushed the encryption streams before you close them? 在关闭加密流之前,您是否已完全清除它们? AES processes data in block sized chunks, in CTR mode it is the keystream. AES以块大小的块处理数据,在CTR模式下,它是密钥流。 If you don't fully flush the stream before closing it, on either encryption or decryption, you will probably lose the last block. 如果在关闭流之前没有完全刷新流,则无论是加密还是解密,您都可能会丢失最后一个块。

Similarly, you need to be sure that you have written/read everything from the transfer file streams between Android and PC. 同样,您需要确保已编写/读取了Android和PC之间传输文件流中的所有内容。 Your last pieces of data may have been sitting in a file transfer buffer somewhere waiting to be written when the buffer was closed. 您的最后几条数据可能已经放在文件传输缓冲区中,而该缓冲区关闭时,该缓冲区正等待写入。

Android does differ from Java, so I suspect that your error is probably on the Android side. Android确实与Java不同,因此我怀疑您的错误可能是在Android方面。 Perhaps try Android -> Android as well as PC -> PC, just to make sure that everything on the Android side is fine. 也许尝试Android-> Android以及PC-> PC,只是为了确保Android方面的一切都很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM