I have a private file encryption project that I'm working on that currently uses Encrypt-then-MAC. However, I've been looking at age and the article that's referenced in the spec that discusses encrypting streams with AEADs. It's not possible to load entire GB files into memory to get one authentication tag, and it would be nice to catch errors as soon as possible for speed reasons.

Ideally, I'd use crypto_secretstream in libsodium, but it hasn't been implemented in the libsodium binding I'm using, and I don't understand how to implement it due to not being able to read C, the secretstream state not being explained very well, and unhelpful parameter/variable naming.

So if I want to implement something similar myself, how would I go about dealing with truncation of the ciphertext?

Preventing chunks from being removed/duplicated/reordered can be fixed with a counter nonce (obviously using a different key for each file). You could also use the previous authentication tag as associated data. That's easy enough to implement.

Unfortunately, it doesn't seem possible to prevent truncation without appending a MAC to the end of the file again, which defeats the purpose of implementing this.

It seems like age and the ImperialViolet article suggest setting the associated data to 1 when you reach the last chunk, but how does this help? If you authenticate the previous chunks and write each plaintext chunk to a file, then you've already exposed some plaintext before you can authenticate the last chunk - it doesn't stop truncation.

Should I just stick with Encrypt-then-MAC? This is harder than I thought due to this truncation issue. I might be glossing over other potential issues too as I'm only a beginner.

  • "It's not possible to load entire GB files into memory to get one authentication tag" - that's not needed with common hashes. They can be read chunk by chunk. And why not simply include the size information as part of the data to notice truncation? – Steffen Ullrich Dec 23 '20 at 11:47
  • @SteffenUllrich I know, but I'm talking about AEADs, which require reading an entire file into a byte array to get one tag. Where would you store the number of chunks? How would you authenticate that number? – Zachary Dec 23 '20 at 12:00
  • If you know the file size up front you can put it at the very beginning of the data, i.e. first 8 bytes or so. If it is part of the encrypted data no additional authentication is needed. You could also prefix each block with a simple indicator if this is the last block or if more are following - and again this is part of the encrypted and authenticated data. – Steffen Ullrich Dec 23 '20 at 12:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.