How to use nonces in asymmetric encryption (libsod

2020-03-16 07:11发布

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.

2条回答
神经病院院长
2楼-- · 2020-03-16 07:28

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.

查看更多
Rolldiameter
3楼-- · 2020-03-16 07:52

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?

查看更多
登录 后发表回答