> 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?
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_Stor... [1]: https://datatracker.ietf.org/doc/rfc9106/