我正在与服务器通信,我已经到了最后阶段,在协商密钥和设置会话密钥之后,我发送了一条加密消息,服务器回复了。
目前,我们正在使用AES-256 CBC,随机IV将被发送到服务器并在本地存储。我目前面临的问题是当我解密从服务器获得的数据时:
decryptCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(cipher.getIV(), 0, 16));
//Get the array after the 7 bytes from the header
byte[] encrypted = Arrays.copyOfRange(sbResponse.toString().getBytes(), 7, sbResponse.toString().length());
当我尝试解密该解析后的数组时,发生以下任何一种情况,但服务器的响应根本不会改变长度或内容:
由于以下错误,我无法解密:
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
我无法解密,出现此错误:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
我可以解密它,某些块很好,但其中一些块在明文中有奇怪的字符:
k¤kC²O©æÖ—Õw½QøX»ÌEXøÀWHÌËùtiÓaÚo at?the application
一切都很好。
所以,我必须做一堆调用,直到我从服务器得到一个干净的响应。
我注意到服务器确实改变了IV,但是,在我的结尾,当我向Cipher询问它时,IV总是保持不变,所以我真的不知道在哪里看。
以下是从服务器获取响应的代码摘录:
StringBuilder sb = new StringBuilder();
while (ConnectionStatus.LISTENING.equals(status)) {
if (in.ready()) {
sb.append((char) in.read());
} else {
if (sb.length() > 0) {
status = ConnectionStatus.OPEN;
}
}
}
if (ConnectionStatus.TIMEOUT.equals(status)) {
status = ConnectionStatus.OPEN;
throw new TimeoutException();
}
有没有人知道可能发生的事情?
如果您需要更多详细信息,代码或任何内容,请与我们联系。
答案 0 :(得分:1)
问题在于将二进制数据存储到String
。
如果InputStreamReader
期望UTF-8,则很可能遇到无效数据,因为大多数二进制流都不是有效的UTF-8。当读者遇到不是有效字符的字节序列时,数据会丢失。
至少有两到三个解决方案:
InputStream
以获取二进制数据。由于InputStreamReader
可能会执行缓冲,因此这是有问题的 - 即使只有一些字符集可能会发生这种情况(To enable the efficient conversion of bytes to characters, more bytes may be read ahead from the underlying stream than are necessary to satisfy the current read operation.
)