Java cipher.doFinal() 写入额外的字节
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1226083/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java cipher.doFinal() writing extra bytes
提问by wadesworld
I'm implementing encryption / decryption using Java Cipher and AES. Everything is working well except that there's 5 extra bytes written on the call to doFinal(). So, I end up with a correctly decoded string with 5 extra bytes appended.
我正在使用 Java Cipher 和 AES 实现加密/解密。除了在调用 doFinal() 时写入了 5 个额外字节外,一切都运行良好。所以,我最终得到了一个正确解码的字符串,并附加了 5 个额外的字节。
I believe the reason is that the entire block of 16-bytes is being written. I see 3 16-byte blocks written, including the last one. The input encrypted file is 64-bytes. The unencrypted text should be 43 bytes.
我相信原因是正在写入整个 16 字节块。我看到写了 3 个 16 字节的块,包括最后一个。输入的加密文件为 64 字节。未加密的文本应为 43 个字节。
The documentation for doFinal indicates that it can return the number of bytes written to the output buffer. However, it's 0,16,16,16. I've tried every form of doFinal and update and get no change in behavior.
doFinal 的文档表明它可以返回写入输出缓冲区的字节数。但是,它是 0,16,16,16。我已经尝试了各种形式的 doFinal 和 update 并且行为没有改变。
It kind of makes sense that it's writing out a full-block, since that's how most of these algorithms operate. However, if it's not going to tell me the size of the output data, how am I supposed to prevent excess data?
它写出一个完整的块是有道理的,因为大多数这些算法都是这样运行的。但是,如果它不会告诉我输出数据的大小,我应该如何防止数据过多?
Should perhaps I be using another algorithm? AES256 is a requirement, but I wonder if a different block type or padding type might allow it to write the correct number of bytes.
也许我应该使用另一种算法?AES256 是必需的,但我想知道不同的块类型或填充类型是否可能允许它写入正确的字节数。
Any guidance?
任何指导?
Snipped for (some) brevity:
为(某些)简洁而剪下:
decryptCipher = Cipher.getInstance("AES");
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey);
Business part of the decryption routine.
解密例程的业务部分。
long bytesToRead = inputFile.length();
while ((inLen = in.read(buffer)) > 0) {
int bytesOut = 0;
byte[] cryptBytes = null;
int outLen = cipher.getOutputSize(inLen);
cryptBytes = new byte[outLen];
if (bytesToRead <= buffer.length) {
try {
bytesOut = cipher.doFinal(buffer, 0, inLen, cryptBytes, 0);
} catch (ShortBufferException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else
try {
bytesOut = cipher.update(buffer, 0, inLen, cryptBytes, 0);
} catch (ShortBufferException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.write(cryptBytes, 0, bytesOut);
bytesToRead -= inLen;
}
try {
out.flush();
in.close();
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
采纳答案by caf
You must specify a padding mechanism when you call Cipher.getInstance() - obviously it must be the same at both encryption and decryption time. eg:
您必须在调用 Cipher.getInstance() 时指定填充机制 - 显然它在加密和解密时必须相同。例如:
decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
Without a padding mechanism, the decryption side has no information on where the end of the plaintext is (within the last block).
在没有填充机制的情况下,解密方没有关于明文结尾在哪里(在最后一个块内)的信息。
回答by Lasse V. Karlsen
AES is a block cipher, naturally it's going to give you entire blocks, as will all block ciphers.
AES 是一个分组密码,它自然会为您提供整个块,所有分组密码也是如此。
See the Wikipedia article on AESfor more information.
You said you wanted it to output the "correct number of bytes". How have you decided what is the correct number of bytes?
你说你希望它输出“正确的字节数”。您如何确定正确的字节数是多少?