When transmitting or storing user data, especially private conversations, it's essential to consider employing cryptographic techniques to ensure p...
For further actions, you may consider blocking this person and/or reporting abuse
The usage of constant IV with AES-GCM completely breaks its security. With AES-GCM, the application must guarantee that the IV is never repeated. Otherwise, it's a catastrophic failure.
If you use AES-GCM, each direction needs a different key or use a different IV range, and the IV should include a counter portion that is incremented for each AES block, then the keys must be rotated once the counter reaches the maximum.
It's simpler to use AES-CBC with random IV, and send the IV together with each message.
Hi! Thanks a lot for the feedback. I missed this information while doing my very superficial research about AES-GCM (I just saw it wasn't sensitive, but didn't see it had to change every time). I'm currently changing the tutorial's approach to this and removing the misleading info.
Edit: done
Last time I designed a system using random IV with AES-GCM and it got rejected in security review. Crypto expert says IV must have three parts:
totally agree I flipped when I read this:
Thanks a lot for the feedback. I made wrong assumptions while reading something quickly. I'm fixing the tutorial :)
Edit: done
How does the user trust that the server is not a Man In The Middle during key exchange? What if the server gives each party its own ECDH public key during key exchange, and then decrypt-reencrypt each message?
You could verify the public key fingerprint if you wanted to make sure. It is impossible as far as I know to be able to verify identity without each participant getting a certificate with their public key from some sort of CA.
My buddy made an Android app that lets users scan each other's QR code that encodes the public key. Basically MITM is not preventable without an out of band channel.
Thanks a lot for your comment! Although I think it's out of scope for this basic tutorial, I've had this same question before. I believe It's not something that can be solved cryptographically. You need some approach like handing out the public key physically by the person (much like the QR code approach you described in another comment), and/or at least using TOFU (Trust on First Use) which is the approach partially taken by Signal (they just display a warning): en.wikipedia.org/wiki/Trust_on_fir...
As Junxiao said, it is dangerous to imply that IV is not an important parameter when using GCM. When reusing the IV in GCM, if an attacker captures a few encrypted messages, since basically GCM is an xor of the plaintext and the keystream (and the keystream is the same when using the same iv), then it is trivial to implement an attack that gets the keystream and unencrypts all the captured messages. It is basically the same attack that you would use for reused keys in One Time Pad. I highly encourage you to edit that part, otherwise the article is very useful, thanks.
Thanks a lot for the feedback! I'm changing the tutorial's approach to this.
Edit: done
Why do you generate the key as exportable and save the JWK?
It's more secure to use non-exportable private keys, and store the key object in IndexedDB.
Thanks for your comment! I didn't want to touch on private key persistence methods in this tutorial. If I got into that, I'd also need to tell how to recover or rotate the key pair in case the persistent storage is lost. So it was better just to leave it like this and tell that the private key is sensitive.
Then you should use non-exportable key and pass it around as a variable.
I left it like that to allow more than one session per user, mostly for not making the test app annoying to use. But I'll add further notes to emphasize that it's not great practice. Thanks :)
I see you are using ECDH shared secret as AES key. This is not advisable because the shared secret could have bias. It needs to pass through HKDF step.
Also, P-256 can only provide 128-bit strength, so that you should be using AES-128, not AES-256.
Thank you! I'll try improving this part as well
This is still wrong:
IV in AES-GCM must be unique but does not need to be random.
IV in AES-CBC must be random.
Thanks for your feedback! I considered switching to CBC, but didn't find a strong enough reason, since the AES-GCM is safe for encrypting 2^32 times with a randomly generated IV using the CSPRNG provided by the Web Crypto API.
Edit: but yes, I removed the "must" and added further details. Thanks again :)