1

At the moment, I deal with PyNaCl (Docs) and have a question about it:

My situation is that I want to create a server that interacts with clients. Both the server and the client will have a long-term private key/keypair.

So, the situation will be that the client will send an encrypted request to the server and the server decrypt it.

The encryption process (by the client) is relatively easy:

encrypted = client_box.encrypt(message, nonce)

And the server can decrypt it with this way (the Docs say):

plaintext = server_box.decrypt(encrypted)

Now to the question:

For the encryption a 24-byte nonce is used for better security. But what I don't understand: Does the server have to know this 24-byte nonce too? In the Docs the decryption is done without a nonce it seems.

But the Docs say that I can also use a nonce for decryption (link) so that it looks this way:

plaintext = server_box.decrypt(encrypted, nonce)

But in the example in the docs they don't use the nonce in the decryption process.

Can, please, somebody explain me when I have to use the nonce and which nonce I have to use then?

3

Wow, I am very unimpressed with that PyNaCl doc page that you linked to; Among other things, they don't explain what this nonce is being used for internally. That makes it hard to answer your question. That said, the example code has some comments that give some hints about what it's doing inside, so I think we can puzzle through it.

Usually, a "nonce" is a random string that you insert into the message before hashing / signing it to make the hash unique each time, and prevent replay attacks. You don't usually see nonces with encryption functions.

The actual documentation lists both encrypt and decrypt as follows:

encrypt(plaintext, nonce, encoder)

decrypt(ciphertext, nonce, encoder)

with no evidence that nonce or encoder are optional, and no explanation of why an encryption function needs a nonce, but then the example code goes and does this:

# Encrypt our message, it will be exactly 40 bytes longer than the 
#  original message as it stores authentication information and nonce
#  alongside it.
encrypted = bob_box.encrypt(message, nonce)

...

# Decrypt our message, an exception will be raised if the encryption was
#   tampered with or there was otherwise an error.
plaintext = alice_box.decrypt(encrypted)

So:

  1. It appears that both encrypt and decrypt can be used with 1 or 2 parameters missing. It would be nice if it explained exactly what the behaviour is in those cases, but no matter.

  2. The nonce will be stored inside the ciphertext, so you shouldn't need to send it separately.

  3. The comment "an exception will be raised if the encryption was tampered with" leads me to believe that the ciphertext is MACed, which would explain why they need a nonce - it's for the MAC hash.

  • I think I know now why there are to options. PyNaCl seems to add the nonce automatically to the ciphertext while encryption, so "plaintext = server_box.decrypt(encrypted)" is enough because probably PyNaCl gets the nonce out of the ciphertext. And perhaps some other implementation like the original NaCl implementation doesn't include the nonce to the ciphertext, so then I need also the extra "nonce" in the function. At least it sounds logical. ;) – Aliquis Jun 5 '16 at 17:58
  • 1
    @Aliquis Oh I see, I'll update my answer. – Mike Ounsworth Jun 5 '16 at 18:10
  • That docs page drives me completely up the wall. What kind of idiot puts key information in comments in the example code, but does not include that information in the actual function doc. gggrrrrr. I'm tempted to send hate-mail to whoever wrote those docs. – Mike Ounsworth Jun 5 '16 at 18:39
  • 1
    @MikeOunsworth It's probably more productive to file that as some kind of bug report. The author is probably simply unaware. Also I'd note that a "nonce" emphasizes not randomness, but uniqueness. I'd disagree that they are not normally used in encryption; You frequently see nonces used with stream ciphers. – Ella Rose Jun 5 '16 at 20:33
  • I agree with Ella here. Stream ciphers and counter mode (which is used within many authenticated ciphers) require a nonce. It is however often "hidden" behind a more general term: the IV. Thing is that CBC mode requires an unpredictable value, not just a nonce. Many generic interfaces therefore stick with an IV parameter even though that IV may be a nonce. – Maarten Bodewes Jun 13 '16 at 12:49

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.