1

so, I want to implement server which validates registration with captcha. First I thought about storing captchas in a server, but then I thought it would be hassle on caching, memory, what if I need to write it into file, etc... But then I had this genius idea (probably someone else already did it), how about just send captcha to the client, also send the encrypted answer, and when user answers he sends the captcha (or maybe a digest of it, if it's a little bigger) and I can simply decrypt the answer out of the client. BOOM, I don't need to store bazillions of images at all and I can scale these up as much as I want! (different server could send out captcha and different could serve the response).

Now, I just have one problem. I need a nonce to encrypt stuff in libsodium. Like in here http://doc.libsodium.org/public-key_cryptography/authenticated_encryption.html . Now, if I generate this every time, send to the user for the user to send it back, then it is public, what is the point of that? Or, if I use constant nonce then, still, what is the point of that? Server and client can look it up.

What should I do here? Should I use constant nonce in this situation or should I generate it every time and why?

Shazzlow
  • 123
  • 2
  • You generate a new nonce each time and send it to the client. A nonce means a number used once. You must not repeat it. But it is not secret. It is not a key. – Z.T. Oct 27 '15 at 18:41

1 Answers1

1

If it is stateless, your scheme is vulnerable to replay attacks.

A client can respond with the same captcha+ciphertext every time, no matter what ciphertext was initially sent.

Use a timetamp+random bytes as a nonce. This doesn't have to be secret, only the key must remain secret.

Instead of encrypting the captcha, you can use a keyed hash.

  • Server sends Hk(captcha) || timestamp || randombytes with k = secret || timestamp || randombytes. You can use crypto_auth() or crypto_generichash() for this, and use a 192-bit secret, a 32-bit coarse timestamp and a 32-bit random part.
  • Client sends Hk(captcha) || timestamp || randombytes || captcha
  • Server computes H'k(captcha) using the captcha, timestamp and randombytes sent by the client, and verifies that the timestamp is close to the current time and that H'k(captcha) matches Hk(captcha).
Frank Denis
  • 273
  • 1
  • 4