I need to encrypt and authenticate a stream of data so that it is resilient against unexpected power loss, so I cannot write authentication data at the end of the stream.
This is a fairly confusing question you're asking, and I needed to read the whole thing over and over to come to a point where I felt I understood it. What you want is to authenticate the data you're sending incrementally so that the recipient can establish the authenticity of chunks or prefixes without having to wait for the end of the whole stream.
The solution to this is to move the authenticated encryption inside the protocol that you're using to send data over the stream. Instead of globally encrypting and authenticating a stream of plaintexts, you probably should send a stream of individually encrypted and authenticated ciphertexts. AES-GCM will work fine for that—don't play around with homebrew ideas like what you're proposing. You do have to be very careful about IV reuse. (And about writing your own cryptography—are you sure you want to do this?)
One nuance here is whether you're trying to authenticate individual messages or stream prefixes. This is related to the question of what should the recipient do if one message in the stream is adulterated:
- Skip it and carry on processing the subsequent ones;
- Abort the whole thing and don't process any more messages.
What's the correct thing to do depends on the application. I'd put a bit of thought into that question. But for case #2, there are tricks that can be done to cause the authenticity of later messages to depend on that of earlier ones.
I am currently using AES-GCM, just for encryption, as my understanding is that the authentication tag for GCM must be written at the end of the stream.
There is no logical requirement to write the authentication tag at the end of the stream. It's just a very convenient way of doing it, since:
- It allows you to write the ciphertext into the stream incrementally as you compute it;
- You can't emit the tag until you've encrypted the whole message anyway.
If you buffer the whole ciphertext and tag into memory before writing them to the stream you could write them in the opposite order if you so preferred. I figure some specific AES-GCM implementations may be hardcoded to write the tag at the end, though.
My understanding is that truncating the SHA512 sum to save space is okay.
If you're truncating to 256 bits, there's a newer SHA-2 variant called SHA-512/256 which already does that. But the larger issue is that SHA-2 is not a message authentication code, so it's not a substitute for GCM's authentication.