2

I'm using the sodium_crypto_secretbox and sodium_crypto_secretbox_open functions in PHP (currently PHP 5.6, using paragonie/sodium_compat).

If a user has cypher text, nonce and decrypted plain text, can they determine the key that was used to encrypt the information?

The context: I'm encrypting the user's login token (a cookie, stored on the machine) and using this as a CSRF token. The CSRF token necessarily includes the nonce for decryption when submitted. The CSRF token is decrypted and verified on submission of form POSTs to protect against CSRF attacks.

My concern is not so much for CSRF attackers who won't have access to the cookies, but for the key itself. For simplicity, it would be useful to use the same key for other encryption functions in the software, but I can't if it can easily be exposed via this information. A legitimate user can see CSRF token and cookie: could they discover the key?

8

If a user has cypher text, nonce and decrypted plain text, can they determine the key that was used to encrypt the information?

Depending on the encryption algorithm used, knowledge of the plaintext and ciphertext does not reveal the key. Otherwise, a single block of known plaintext (a common header or an attacker-controlled value, for example) would break the cipher! Such a key-recovery attack is very rare for any modern, well-designed cipher. The library you are using supports several secure ciphers based on DJB's Salsa20 algorithm. All the ciphers used are secure from key-recovery attacks.

For simplicity, it would be useful to use the same key for other encryption functions in the software

It is generally a very bad idea to re-use a key for any other purposes. Each distinct use of encryption should use a new key. For example, your CSRF token encryption key should not be the same as a link encryption key. If you really do have one key-sized value, you can expand it safely into multiple keys. A safe way to do this is with the popular HKDF function. You give the function one master key, and it spits out any number of cryptographically secure keys fit for use.

2

forest definitely answers things, but I would also like to add a similar aside:

Why are you reusing the user's login token for the CSRF token?

While reusing the user's login for CSRF doesn't rise to the level of "security blunder", I also wouldn't consider it best practice and would avoid it unless there is a good reason. Reusing it like you are doing doesn't immediately create security holes, but in general reusing keys/tokens is how you inadvertently introduce a security problem down the road. Typically this ends up happening because someone making a change on one part of the system doesn't realize the implications it has somewhere else.

However, this does create one security short-coming, which is that you can't regenerate your CSRF token after each request. Regenerating CSRF tokens after each use is a recommended (although not necessary) security step, and it can also help protect against accidental double submits. As a result I'd suggest just implementing a separate CSRF token if doing so isn't a big hassle for you system. After all, why bother with the encryption/nonce/etc for the login token to make a CSRF? All a CSRF token needs is to be unique and unpredictable. It is just as easy to generate a long (cryptographically secure) random string and store that in the cookie for your CSRF token. No login token reuse required.

  • Bit of a nitpick: "All a CSRF token needs is to be unique" is inaccurate, it must also be unpredictable. – AndrolGenhald Jul 2 '18 at 16:56
  • 1
    :) Good call. True story - I was taking that as a given, but explicit is better than implicit – Conor Mancone Jul 2 '18 at 17:12
  • I do need to allow for multiple submissions from a form (via AJAX). I appreciate this means back-end checks for duplicate form submissions. It is more the "CS" of CSRF I'm interested in here. Would it be an acceptable solution, if I may attempt to extrapolate your advice, to set a session cookie with random data and simply include that value in the form as the CSRF token? – Philip Jul 3 '18 at 7:17
  • @Philip yup, that's pretty much the standard way to build CSRF tokens. Regarding double submits, you don't have to have double submit protection server side if you have javascript that guarantees it client side. It can still be nice to change the CSRF token after each request so that there is simply one less way for attacks to figure out what the token is. However, the actual security gains from doing so are pretty minimal, so it is a reasonable one to ignore if it makes your life harder. – Conor Mancone Jul 3 '18 at 12:09
  • @ConorMancone Since we're talking about CSRF I initially thought when you said "double submit" you were referring to double submit cookies rather than multiple requests :P – AndrolGenhald Jul 3 '18 at 15:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.