3 ms·
> I suspect the encryption here is broken due to CTR mode AES with IV reuse. Try printing out the IV in the segment function. It's the same value across session
by d-z-m 3y ago
> I suspect the encryption here is broken due to CTR mode AES with IV reuse. Try printing out the IV in the segment function. It's the same value across sessions.
I think it's a little more subtle. IVs are being generated deterministically, but keys are generated randomly per session. The nonce uniqueness requirement in CTR is per key. That said, there doesn't seem like there's any guard against replays of messages, or dropping of messages, or altering of messages.
> Another thing I see is that AES-CTR is being used alone, so there is no integrity guarantee for the messages.
Indeed. They seem to try and do some integrity checking at the start of a session by sending an encrypted all-zero block, as a way of verifying that the client has the correct key (stored in the url hash). From what I can tell, there's no integrity checking on any subsequent messages.
Also the KDF parameters for Argon2id seem way underpowered (19MB RAM, 1 lane, should probably be using at least 2GB RAM in a KDF setting)
- ekzhang 3y agoThanks for the comment, happy to elaborate. You're correct that the IVs are not reused. Replays and dropping messages are not possible due to the indexing of the stream. This is a necessary precaution from a distributed systems sense because networks can fail or deliver messages twice. Integrity / detecting server tampering of data is not really part of the security model here — I've discussed this in my comment below, but the aim of the encryption is to make sure to preserve confidentiality. --- Argon2id parameters are set as strong as possible while allowing for execution in a browser context.
- d-z-m 3y ago> Thanks for the comment, happy to elaborate. You're correct that the IVs are not reused. Perhaps you can elaborate a little more on this? For subsequent calls to the segment() function, holding the stream ID constant, how are IVs generated? > Replays and dropping messages are not possible due to the indexing of the stream. This is a necessary precaution from a distributed systems sense because networks can fail or deliver messages twice. I see. I was mainly looking at the encryption side of things, not the application layer. > Integrity / detecting server tampering of data is not really part of the security model here This seems like an own-goal, especially since you could've gotten it pretty much for free using an AEAD construction like GCM(I understand you're using the seeking capability of CTR, but it isn't clear to me why). > Argon2id parameters are set as strong as possible while allowing for execution in a browser context. This is incorrect. They're actually set to as weak as possible while still being safe for use in a password hashing context. I hunted around a while for the parameter set you've opted for here, and finally found it[0]. Is this where you got it from? Importantly, that parameter set is optimized for a minimum security margin in the context of hashing passwords. None of the KDF parameter sets in the Argon2 RFC[1] approach that level of RAM usage. I just ran Argon2id with 5 passes 500 MB RAM in my browser and it executed in a couple seconds. It's also unclear why you need a KDF at all. From what I can tell, users can't specify the password that gets KDF'd into your AES key. Why are you trying to key stretch a 14 character alphanumeric password? Why aren't you just reading 16 random bytes and storing that in the URL hash? [0]: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html https://cheatsheetseries.owasp.org/cheatsheets/Password_Stor... [1]: https://datatracker.ietf.org/doc/rfc9106/ https://datatracker.ietf.org/doc/rfc9106/