我使用 AES/CTR/NoPadding 算法来加密 PC 和 Android 之间使用套接字发送的数据。
我编写了单元测试,它向 Android 设备发送 [1;512] 字节并接收回相同的数据 - echo 服务。接收到的数据必须等于发送的数据。
测试客户端:
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 ...
}
}
回显服务器:
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();
}
我用本地主机测试了这段代码 - 一切正常。
当我使用 Android 设备测试它时,如果最后一个 block 未满,则会丢失。 因此,如果是 30 字节,则仅收到 16 字节。
来自测试的消息:
... 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 ...
可能出了什么问题?
最佳答案
看来该问题是由于 Android 和 Hotspot JVM 使用不同的 Cipher Provider 造成的。
Android 使用名为 Bouncy CaSTLe 的工具,该工具在 AES/CTR 模式下存在已知“错误”。进行加密/解密时,它会错过最后一个 block 。 (查看许多其他 stackoverflow 问题)
如果您只想要 CTR 模式。已知的解决方法是您自己在 Android 上实现它,方法是“即时”重复生成 key 流 block (通过加密 0 的字节数组),并将它们与缓冲区进行异或。
希望这有帮助
关于java - PC 和 Android 之间发送加密数据时 AES/CTR/NoPadding 最后一 block 丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21220878/