9

I am writing an app where users can communicate between devices with end to end encryption. For this I use the libsodium encryption library. The asymmetric encryption function, crypto_box(...) requires a nonce as one of the arguments.

I am a bit confused about how to handle nonces. Does every message to one person need to be encrypted using different nonces? This does not seem right since I would have to store the used nonces on a server with public access where an attacker could just use one of the used nonces again.

Is it enough that all messages sent from A to B have different nonces or can the nonce use to send a message from A to B not be used to send from C to B?

Can someone please explain this to me.

joakimb
  • 553
  • 1
  • 7
  • 19
  • 2
    "nonce" is actually a contraction of "Number used ONCE". So YES, you use different numbers! – OJFord Jul 09 '14 at 10:44

2 Answers2

7

A unique nonce is required for every message sent using a given shared secret key. The nonce doesn't have to be secret; a simple counter is totally fine; changing a single bit in the nonce is going to make the ciphertext look totally different even if the same message is sent twice.

What's a shared secret? It a key calculated from (A's secret key, B's public key) or (A's public key, B's secret key). A and B perform a different calculation, based on what they have, but end up with the same shared secret.

The shared secrets used in crypto_box are 256-bit long. Which is huge. You can safely consider that shared secrets are going to be unique for each "conversation".

So, (A, B), (A, C) and (C, B) can safely exchange messages using the same nonces. But if A sends a message to B using a given nonce, B cannot send a message to A using the same nonce. Nonces have to be unique for everything exchanged during a conversation between A and B.

So, a simple counter can be fine. Have A pick even numbers, leave odd numbers to B, increment the nonce by 2 after every message sent and you're good to go.

But the cipher used in the crypto_box construction actually has a really huge nonce. 192 bits.

Which means that if you ignore everything I wrote and just pick a random nonce every time you send a message, the probability to get a collision is so small that you can rest assured that it will never ever happen in practice.

Some stream ciphers included in Sodium (AES128-CTR, ChaCha20, Salsa20) have a shorter nonce, and require a counter to avoid collisions. This is why they are in the "advanced" section of the documentation.

But with crypto_box and crypto_secretbox, just pick a random nonce every time (randombytes_buf(nonce, sizeof nonce)) and you will be safe.

Frank Denis
  • 1,475
  • 9
  • 12
6

Does every message to one person need to be encrypted using different nonces?

Yes. In fact, never, ever use the same nonce more than one for the same private key. It is true that you would have to keep track of the nonce to accomplish this.

This does not seem right since I would have to store the used nonces on a server with public access where an attacker could just use one of the used nonces again.

Why would you have to store your nonce on a server with public access? And how do you think an attacker could "use" the nonce? They would need your private key to do so.

Why can't you store the nonce in the same place as your private key?

Jay Sullivan
  • 17,332
  • 11
  • 62
  • 86
  • But when A wants to send an encrypted message to B, A encrypts the message with B:s PUBLIC key. This is where i get confused. Therefore, A decides the nonce and B has no control over which nonce is used to encrypt messages that is sent to B and later decrypted with B:s private key. What am I missing here? – joakimb Jun 12 '14 at 21:31
  • Found this link: http://curvecp.org/nonces.html which says, "After a particular nonce has been used to encrypt a packet, the same nonce must never be used to encrypt another packet from the sender's secret key to this receiver's public key, and the same nonce must never be used to encrypt another packet from the receiver's secret key to this sender's public key." Now I understand, it is only between A and B that the same nonce cannot be used twice. – joakimb Jun 13 '14 at 11:21
  • 6
    If A sends a Encrypted message to B. Does B have to use the same nonce (used to encrypt the message by A) to decrypt the message ? Or it generates a new nonce to decrypting the message. I understand the encryption and decryption requires each others public key. What I'm trying to figure out is if the nonce need to be exchanged between A and B for en/decryption of data other than public keys. – Feru Feb 17 '15 at 22:29
  • 1
    @Feru yes, the nonce is not a secret and is included as part of the cipher text payload. – Woodstock Oct 22 '20 at 14:01