3

I have an (offline) shared secret key (symmetric) which is used to encrypt/decrypt data.

Now this data belongs to a specific user which is known on the backend and frontend. My idea was to use the username/id as salt. But for AES we only have the iv.

Doing this would make sure that the data on the frontend can only be encrypted if the correct user is logged in, because without the correct salt/iv. The data would be nonsense.

But this iv would not be random anymore.

So do you have a suggestion for me on how to deal with the problem? Also, the secret key and the username/id is the only thing both endpoints know.

kelalaka
  • 48,443
  • 11
  • 116
  • 196
Shurpion
  • 33
  • 3

2 Answers2

1

You did not mention the mode of operation for any block cipher that is necessary.

  • CBC mode requires the IV random and unpredictable so this is not your way.

  • CTR mode requires an $(IV,Key)$ pair never occurs more than once. One must never use the same $(IV,key)$ pair again, otherwise, confidentiality is lost.

    CTR mode generally uses 96-bit nonce and 32-bit counter to form the Initial value. If the nonce reoccurs and counters repeat then these blocks can be revealed with crib-dragging. The nonce can be chosen randomly that will have a 50% probability of collision after $2^{48}$ random nonce generation. Counter/LFSR-based nonce generation is also recommended by NIST.

CTR mode can be a solution for you.

The above modes don't provide you more than confidentiality. We can, and we should go more;

  • GCM provides you confidentiality, integrity, and authentication. Since GCM uses the CTR mode for encryption, you will have the same (IV, key) reuse problem.

    If the IV has 92-bit length then $J_0 =IV || 0^{31} ||1$ is passed to the CTR mode as the IV where the 32 bits is used as a counter which starts form $1$. SO if you reuse the same IV under the same key, you will have the same problem in the CTR mode.

  • XChaCha20-poly1305 is ChaCha20 with an extended nonce that we can use random nonce more securely. It has 192-bit nonce sizes and one has a collision with 50% probability once generates $2^{96}$ random nonces under the same key. Though this has the same $(IV,key)$ problem the probability of getting it is not-going-to-happen.

  • There is also AES-GCM-SIV mode. This is nonce-misuse resistant and even the IVs are the same the mode will only leak that the messages are the same. This requires additional passes over the data.

Therefore, one can use AES-GCM-SIV to mitigate all possible problems or use xChaCha20-poly1305.

For the user, you should note that the IV/nonce of the encryption is never meant to be secret. They can be stored, usually prepended, with the ciphertext. During the client-side encryption, they can be created. Therefore the user doesn't need to know anything about the IV/nonce after the encryption, the server can store them with the ciphertext. The user only needs the secret key and must keep it secret all the time.

kelalaka
  • 48,443
  • 11
  • 116
  • 196
  • Okay, so username obviously can be the same, but so does data. So it might happen that data and username combination is the same but using AES-GCM-SIV this would not be a problem? Also if I use a random IV and prepend it to the cipher text in CTR mode it would be perfectly safe? I did not know that I can just send the IV in plain text. So not using the username it all would be the best solution? – Shurpion May 03 '21 at 10:44
  • AES-GCM-SIV only leaks that the encrypted data are the same even you use the same $(IV,key)$ pair. The key is different per user, therefore it is the problem of the same user. Nothing is perfectly safe, CTR. In the CTR mode just make sure that the IV never accurs with the same key – kelalaka May 03 '21 at 10:55
  • Okay, will read on this one. So I think I just go with random IV and prepend it to the data and then use CBC mode. Looks like the simplest solution. Follow up question: Does it make sense to include username in the secret, like exchanging first x bytes of secret with username? Does this provide any additional benefits or worse leaks security? – Shurpion May 03 '21 at 10:59
  • Use XChaCha20-Poly1305 ( or only XChaCha20 if you only need encryption). CBC mode IV has a higher chance of collision than XChaCha20. Include the user name in the secret? Do you mean encrypt? AES-CTR, CBC, GCM, ChaCha ara all CPA secure, no problem there. – kelalaka May 03 '21 at 11:03
  • Okay. Thank you that helped. No I meant really include it in the secret with. Like if the secret would ABCDEF1234567890... Does it make sense to encrypt data for user1 with the secret user11234567890...and data for user2 with user21234567890. So different secrets per user but where part of the secret is not random anymore? – Shurpion May 03 '21 at 11:08
  • Do you mean adding the user name into the key? – kelalaka May 03 '21 at 11:11
  • Yes. As a salt. Not as easy as above but. Maybe like using the key as password and the username as salt. For every user I would generate a key by hashing the static key with the username? – Shurpion May 03 '21 at 11:13
  • The keys must be generated uniformly random. Like generating from getrandom syscall. You can use the same method to generate the IV/nonce. If you want to derive multiple keys and from a master key you can use HKDF. If the user store a strong password for the key generation than you can use PBKDF2 with some good iteration like 250K. – kelalaka May 03 '21 at 11:20
  • Okay. Thank you. This answers all my questions:) – Shurpion May 03 '21 at 11:23
  • CTR does not merely require the IV to be unique: it requires counter values to be unique. Using successive IV values for messages that are potentially more than one block long would be disastrous. GCM requires the IV to be unique, no more no less. It's perfectly fine to increment the IV by 1 for each message (and in fact it's the best way to do it if you can). GCM uses CTR under the hood, but that's an internal detail that you don't need to know to use the algorithm. The ICV that GCM uses for CTR is not the IV passed to GCM. – Gilles 'SO- stop being evil' May 03 '21 at 18:44
  • @Gilles'SO-stopbeingevil' Where did I said CTR requires unique? CTR mode requires an (IV,Key) pair never occurs more than once – kelalaka May 03 '21 at 18:45
  • @Gilles'SO-stopbeingevil' You may right about I did not mention the counter-based IV that has reuse problem during system failures, random IV that has collision problem and the combination is necessary. I rather based my solution AES-GCM-SIV and better xChaCha. There is nothing wrong in the answer except less talk! – kelalaka May 03 '21 at 18:51
  • @kelalaka CTR requires a (counter value, key) to never occur more than once. You stated that it “requires an (IV,Key) pair never occurs more than once”, which is technically true by a purely logical interpretation but is dangerously wrong in ordinary language since this is not a sufficient condition. The same mistake comes up again when you claim that for GCM “you will have the same (IV, key) reuse problem”, which is wrong since GCM does not have the same IV constraint as CTR. – Gilles 'SO- stop being evil' May 03 '21 at 18:55
  • @Gilles'SO-stopbeingevil' So it is true technically that I wrote always technically! GCM has the same problem as CTR mode and even more to may cause forgeries! – kelalaka May 03 '21 at 19:00
  • @Gilles'SO-stopbeingevil' See page 18 If under the same key the same IV is used than CTR mode uses the same IV again, i.e. the (IV,key) pair re-occured! – kelalaka May 03 '21 at 19:07
  • @Gilles'SO-stopbeingevil' https://crypto.stackexchange.com/a/68525/18298 – kelalaka May 03 '21 at 19:11
  • @kelalaka Once again, no. GCM does not have the same problem as CTR. GCM is perfectly fine with encrypting a two-block message with IV=0, then another two-block message with IV=1: all it cares about is IV reuse. For CTR mode, this would allow recovery of the second block of the first message and the first block of the second message assuming plausible partial knowledge of the plaintext. CTR requires strictly more than the absence of IV reuse. You seem to understand GCM's nonce misuse problem correctly, but to be mistaken about CTR. – Gilles 'SO- stop being evil' May 03 '21 at 19:11
0

The IV is normally stored with the ciphertext. It is not derived from some other secret. To decrypt some encrypted data, all you need to know is the key and the encrypted data.

because without the correct salt/iv. The data would be nonsense.

I'm not sure what you're trying to say. If you're thinking “if someone has the key but not the IV, then they can't decrypt the data”, this is not necessarily true. It depends on the encryption mode and on the partial knowledge that the adversary has about the data. If you want to protect against decryption, the key must be secret.

make sure that the data on the frontend can only be encrypted if the correct user is logged in

To do this, arrange for the encryption key to be “unlocked” when the user logs in. How to do this depends on how users log in. Remember to take into account both what happens on a normal login, what happens on a resumed session (if that's a thing), and what happens for account recovery (e.g. lost password), as well as what happens when the user's authentication method changes (password change).

If users authenticate with a password, here's a common design. Use the password as input to a key stretching function to calculate a user master key $K_m$. A key stretching function is essentially the same as a password hashing function which is used to check that the user provided the expected password: it applies a slow transformation to the password, to reduce the rate at which the output can be guessed by brute force. For password hashing, the expected output is stored in the user database. For key stretching, the output is not stored anywhere, and is used as a key.

To encrypt some data associated with the user, generate a random key $K_d$ for your data encryption method, and encrypt the data with that key. If $K_d$ is used to encrypt more than once, use a random IV/nonce; if you generate a unique $K_d$ each time you encrypt some data, the IV/nonce can be fixed (e.g. always 0). Either way, you'll need to recover $K_d$ to decrypt the data later, so store a copy of $K_d$ encrypted with $K_m$. The next time the user logs in, you'll calculat the same $K_m$ again from their password, which will allow you to decrypt the encrypted copy of $K_m$, which will allow you to decrypt the data.

When the user changes their password, $K_m$ will change. Decrypt the saved encrypted copy of $K_d$ with the old $K_m$ and write a copy of $K_m$ encrypted with the new $K_m$. Don't forget to securely wipe the old encrypted copy, since it would be a vulnerability if the user's old password became known (and that may be a reason why the user is changing their password).

If the user can authenticate by some method other than their password, you may need to keep other copies of $K_m$ “locked” by the other authentication method. For example, if you have a lost password procedure, you'll need to make a choice between telling the user that all their encrypted data is lost, or having a way to recover $K_d$. One possible way to offer a way to recover $K_d$ is to generate a random key $K_r$, save a copy of $K_d$ encrypted with $K_r$, and provide the user with a “recovery code” (a long string that they should print and save securely) which allows you to recover $K_r$ (you would not store $K_r$ itself).

Coming back to the IV for each piece of encrypted data, as I've explained above, it isn't secret. So you just store it with the rest of the ciphertext.

As for choosing an encryption mode, the best choice is Libsodium's crypto_secretbox or a similar API. Let a cryptographer decide what algorithm is best. If you need to know the mode, for example because you need a ciphertext format that is interoperable between multiple pieces of software, ChaCha20-Poly1305 and AES-GCM are two popular choices. SIV variants are better if your library provides them, but they're still relatively new and not available everywhere. Avoid unauthenticated modes like CBC and CTR: they're older and harder to use, and the lack of authentication can open you to subtle attacks.

  • Thank you for all this insight. I will take this into account. Also thanks for providing the info on crypto_secretbox. I cannot upvote, because I only posted as guest. But you have my thanks – Shurpion May 06 '21 at 09:25