在解密之前是否可以获得解密数据的最终长度?这是一个例子:
RijndaelManaged RMCrypto = new RijndaelManaged();
RMCrypto.Padding = PaddingMode.ISO10126;
Response.Buffer = false;
Response.ClearHeaders();
Response.ClearContent();
Response.AddHeader("Content-length", ??????);
CryptoStream crypto = new CryptoStream(Response.OutputStream, RMCrypto.CreateDecryptor(Key, IV), CryptoStreamMode.Write);
using (Stream orig = GetDataStream())
{
int bufferSize = 100000;
int bytesReceived = bufferSize;
byte[] buffer = new byte[bufferSize];
while (bytesReceived == bufferSize)
{
bytesReceived = orig.Read(buffer, 0, bufferSize);
crypto.Write(buffer, 0, bytesReceived);
}
crypto.FlushFinalBlock();
}
Response.End();
此代码已简化。源数据已加密,并从Stream
方法检索为GetDataStream()
。如果未包含content-length
标头,则浏览器将无法提供下载文件的完成百分比或时间估算。提前解密流是不可能的,因为流可能在千兆字节大小范围内并通过网络读取。
答案 0 :(得分:1)
如果您知道正在使用分组密码模式和填充模式,那么可以提前确定长度。 (例如,如果你正在使用CBC,那么你可以使用倒数第二个密文块作为IV,最后的密文块作为实际的密文,然后计算出存在多少填充字节。)
大多数开发者只是去“???”在上面并以更容易的方式解决问题:在初始加密过程中将明文长度存储在某处。
答案 1 :(得分:0)
不,由于用于CBC的最后加密块,即使在收到后,也无法确切知道 。此外,CBC加密不会在任何地方存储密文的大小。 您确实知道内部的明文与密文相同,但对于AES,减去一个到 15个字节(blocksize - 1),不包括IV大小。在您之后我们收到了最后一个两个块,您可以使用倒数第一个块作为IV来检查精确的明文长度,然后解密最后一个块(与Levi的答案相同)。
内容标题用于正文中的整个内容,因此这将是密文:
Content-Length entity-header字段表示实体主体的大小, 在十进制数的OCTET中,发送给收件人,或者在HEAD的情况下 方法,本已发送的实体主体的大小有请求 是一个GET。
所以??????在您的问题中,不应该是明文的大小,而是密文的大小(包括IV,身份验证标记和其他开销,如果存在的话)。
如果您想事先知道确切的纯文本大小(以字节为单位),只需在密文前面存储一个64位(大端)整数。它与密文大小密切相关,所以我认为它不是很保密。
另一个巧妙的技巧是使用CTR或GCM模式加密。 CTR的密文是 - 禁止IV大小 - 正好是明文的大小。 GCM添加了身份验证标记,但在其中使用CTR进行加密。请注意,对于这些模式中的任何一种,都不应对相同的键重复IV。