Is it possible to determine the length of the CryptoStream before decryption?

Is it possible to get the final length of the 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 original data is encrypted and retrieved as Stream

from a method GetDataStream()

. If the header is content-length

not included, the browser will not be able to provide a percentage full or temporary estimate for the file download. Decrypting the stream ahead of time is out of the question, because the stream can be in the gigabyte size range and read over the network.

+3


source to share


2 answers


If you know the block cipher mode and padding mode, then yes, you can determine the length ahead of time. (For example, if you are using CBC, then you can use the penultimate ciphertext block as IV and the last ciphertext block as the actual ciphertext, and then calculate how many padding bytes were present.)



Most developers just go "???" in the above and the problem is much simpler: store the length of the plaintext somewhere during the initial encryption process.

+1


source


No, you cannot know exactly what exactly even after you received it due to the last cipher block used for CBC. Also, CBC encryption does not store the size of the cipher text anywhere. You know the plaintext inside is the same as the ciphertext minus one to 15 bytes (blockize-1) for AES, though, except for the IV size. ... After you've gotten the last two blocks, you can check the exact length of the plaintext by using the first-last block as the IV and decrypting the last block (just like Levy's answer).

The content header is for all content in the body, so it will be ciphertext:

The object's header field Content-Length indicates the size of the object's body, in decimal OCTET, sent to the recipient or, in the case of the HEAD method, the size of the face body that was sent, would the request have been RECEIVE.



So?????? your question should not be the size of the plaintext, but the size of the ciphertext (including IV, authentication tag, and other overhead if any).

If you want to know in advance the size of the plaintext in bytes, just store the 64-bit (big endian) integer before the ciphertext. It has a lot to do with the size of the ciphertext, so I don't think it's very confidential.

Another neat trick is to use CTR or GCM encryption. The cipher text CTR is the IV size - exactly the size of the plain text. GCM adds an authentication tag, but otherwise it uses the CTR to encrypt internally. Note that the IV should never be repeated for the same key for any of these modes.

0


source







All Articles