问题
Is it possible to get the final length of decrypted data before decrypting it? Here's an example:
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();
This code has been simplified.  The source data is encrypted and is retrieved as a Stream from the GetDataStream() method. If the content-length header is not included, the browser won't be able to give a percent complete or time estimate for downloading the file. Decrypting the stream ahead of time is out of the question because the stream could be in the gigabyte size range and is read over a network.  
回答1:
If you know the block cipher mode and padding mode being used, then yes, it is possible to determine the length ahead of time. (For example, if you're using CBC, then you could use the penultimate ciphertext block as the IV and the final ciphertext block as the actual ciphertext, then calculate how many padding bytes were present.)
Most developers just go "???" at the above and solve the problem in a far easier way: store the plaintext length somewhere during the initial encryption process.
回答2:
No, you cannot know that precisely even after you've received it because of the final block of encryption that is used for CBC. Furthermore, CBC encryption does not store the size of the ciphertext anywhere. You do know that the plaintext inside is the same as the ciphertext, minus one to 15 bytes (blocksize - 1) for AES though, excluding the IV size. After you've received the last two blocks you can check the precise plaintext length by using the first-to-last block as IV and decrypting the final block though (same as Levi's answer).
The content header is for the entire content in the body, so that would be the ciphertext:
The Content-Length entity-header field indicates the size of the entity-body, in decimal number of OCTETs, sent to the recipient or, in the case of the HEAD method, the size of the entity-body that would have been sent had the request been a GET.
so ?????? in your question should not be the size of the plaintext but the size of the ciphertext (including IV, authentication tag and other overhead, if present).
If you want to know the exact plain text size in bytes beforehand, simply store a 64 bit (big endian) integer in front of the ciphertext. It's very much linked to the ciphertext size, so I don't think it is very confidential.
Another neat trick is to use CTR or GCM mode encryption. The ciphertext of CTR is - bar the IV size - exactly the size of the plaintext. GCM adds an authentication tag, but otherwise it uses CTR for the encryption inside. Note that the IV should never be repeated for the same key for either of these modes.
来源:https://stackoverflow.com/questions/26239442/can-the-length-of-a-cryptostream-be-determined-before-decryption