我正在使用AES / CTR / NoPadding算法来加密使用PC和Android之间的套接字发送的数据。
我写了单元测试,它将[1; 512]字节发送到Android设备并接收相同的数据 - 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();
}
我用localhost测试了这段代码 - 一切正常。
当我使用Android设备对其进行测试时,如果它未满,则最后一个块将丢失。 因此,如果它是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 ...
有什么不对?
答案 0 :(得分:0)
在关闭加密流之前,您是否完全刷新了加密流? AES以块大小的块处理数据,在CTR模式下,它是密钥流。如果在关闭流之前没有完全刷新流,无论是加密还是解密,您可能会丢失最后一个块。
同样,您需要确保从Android和PC之间的传输文件流中写入/读取所有内容。在缓冲区关闭时,您的最后一些数据可能位于文件传输缓冲区中,等待写入。
Android确实与Java不同,所以我怀疑你的错误可能在Android方面。也许试试Android - &gt; Android以及PC - &gt; PC,只是为了确保Android端的一切都很好。
答案 1 :(得分:0)
似乎问题是由Android和Hotspot JVM使用不同的密码提供程序引起的。
Android使用一个名为Bouncy Castle的游戏,它在AES / CTR模式下有一个已知的'bug'。在进行加密/解密时,它将错过最后一个块。 (参见许多其他stackoverflow问题)
如果您只想要CTR模式。已知的解决方法是在Android上自己实现它,通过“动态”重复生成密钥流块(通过0的加密字节数组),并用缓冲区对它们进行异或。
希望这有帮助