8

I'm trying to encrypt big files (> 1GB) using the WebCrypto API.

Encrypting small files works great but when I try to encrypt big files, my browser hangs and it seems the encryption is never finished.

I think the best option would be to read and encrypt chunks of the file and than merge the chunks together when done reading.

Does anyone here have experience with encrypting and merging chunks together? If so, I would highly appreciate it if someone could show me an example or point me into the right correction.

Thanks in advance!

1 Answer 1

5

Obviously the high level WebCrypto API was not designed with streaming / large messages in mind. However, if you look at common cipher modes of operation then you'll find that you can use the different modes in such a way that you can concatenate different ciphertext and get a full ciphertext.

You could use AES-CBC for a 1 MiB chunk (or any multiple of 16 bytes) and use the first-to-last 16 bytes of ciphertext as IV to encrypt the next chunk. You will have to dismiss last block as it contains encrypted padding for any chunk except of course the last. Unfortunately, this is not an integrity / authentication mode and the result is vulnerable against padding oracle attacks, so I would still not recommend it. Also, as you dismiss the padding, you cannot decrypt using the same method.

Similarly, you can use counter (CTR) mode with a counter and start with counter value <nonce>|0000000000000000 and then after 1 MiB continue encrypting with counter value <nonce>|0000000000010000 (as 1 MiB contains 65536 blocks), then use <nonce>|0000000000020000 after 2 MiB etc.. The nonce is a unique 8 byte value in the previous IV / initial counter blocks. This cipher has perfect symmetry between encryption & decryption and doesn't use padding. However, it is very vulnerable against change by an adversary; basically an adversary may flip any byte in the ciphertext and thereby flip any bit in the plaintext. This could also lead to further plaintext oracles and leak additional information.

Beware that you cannot do the same thing for AEAD ciphers such as GCM. In that case you need to expand the ciphertext with an nonce and the authentication tag. But you can still encrypt, say, 1 MiB and expand it to a 12 byte nonce, 1 MiB of ciphertext and a 16 byte authentication tag. Then you can decrypt using that larger block size and get 1 MiB plaintext blocks back. Note that you still have to perform a MAC over the authentication tags, otherwise an attacker may reorder the 1 MiB + 28B sized blocks. One way to do that is to perform a 0 byte GCM encryption using the authentication tags as AAD input.

Whew, I guess that's what you get for using an API outside its original intent. It is perfectly possible, but yeah, some study required I guess.


Using 1 MiB to mean 1024 x 1024 bytes here, or 1024 KiB. Mega means million, not - uh, I again forgot the exact amount.

Sign up to request clarification or add additional context in comments.

8 Comments

Thank you so much for the detailed explanation. I'm currently using AES-CBC. Is there anything I can do to prevent the padding oracle attacks? Also, as I dismiss the padding, what method can I use to decrypt the data?
1. Well, yes, you can perform a HMAC over all the bytes. However, if that function also just allows full message input then you may need to use e.g. a Merkle list create a hash over the chunks and then perform a HMAC over the hash values. 2. You only dismiss the spurious padding in between the chunks. The result of above scheme would be identical to normal CBC ciphertext. So the receiver can use any function that provides (piecemeal) CBC decryption.
@Maarten-reinstateMonica are there any plaintext oracle example for CTR mode in academics?
Not sure, but it would be rather simple to devise a hypothetical one, right?
If using AES-GCM is it feasible to encrypt each chunk in order with a hash of the previous result becoming the IV for the next chunk? Basically instead of attempting to stream via the cipher, stream at the application level having each chunk be their own isolated cypher-text?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.