# Chacha20 internal counter/position and nonce

I have to encrypt the communications between two devices. I was planning on using a timestamp(in seconds) and the serial number as the nonce. I know its impossible for me to send more than 100 messages a second. So potentially the nonce can repeat a couple of times in a second, but the internal chacha counter should work to make each nonce unique correct?

So potentially the nonce can repeat a couple of times in a second, but the internal chacha counter should work to make each nonce unique correct?

No.

YOUR OBLIGATION in the ChaCha security contract is to choose a unique nonce for every message you send; IN EXCHANGE, ChaCha provides IND-CPA security, meaning roughly confidentiality against a passive eavesdropper.

ChaCha does nothing to fulfill its contractual obligations for you if you violate your contractual obligations to ChaCha. The ‘counter’ is an implementation detail of how ChaCha encrypts a single message; ChaCha itself keeps no state between messages—that is your job. If you repeat a nonce, the security contract is null and void, and ChaCha provides no security whatsoever.

• If you're exchanging messages sequentially in a conversation, I recommend that you simply count the number of messages you have sent so far and use that as the nonce. This way you can cheaply reject replays too by refusing to accept old message numbers.

• If you have no persistent state, but you do have access to an entropy source, you could use XChaCha instead of ChaCha (it is easy to write an XChaCha implementation in terms of a ChaCha implementation); then you can pick the 192-bit nonce independently and uniformly at random for each message, and send it along with the message. But I recommend using message sequence numbers instead if you can.

By the way: You are actually using ChaCha as part of the authenticated cipher ChaCha/Poly1305, right? I hope you're not building an application out of an unauthenticated cipher!

• Thanks for the info. Its used on a network where you can have many devices talking to many devices. So if we only use counters as the nonce, two devices can use the same nonce when transmitting. Also on power loss the counter is lost. The libsodium documentation states: "Internally, ChaCha20 works like a block cipher used in counter mode. It includes an internal block counter to avoid incrementing the nonce after each block." so not sure why the nonce can't repeat. I ws looking into the IETF version and that should work for my use case since its 4Byte ctr and 12Byte nonce Nov 4 '19 at 16:15
• @FranLovera In that case, you probably want to use XSalsa20 or XChaCha with a random nonce per message. (What the libsodium documentation says isn't wrong, but it's not relevant here. The counter starts at zero for each message. The security relies on having a different nonce for each message. And, of course, if you can't keep state for a nonce, how could ChaCha magically keep state internally?) Nov 4 '19 at 16:18
• Ok, i'll see if I can switch to XChacha or use the IEFT version to avoid messing with the counters. My original plan was to send the counter in the msg and the reciever would set the counter prior to decrypting it. Nov 4 '19 at 16:20
• Thanks for the help btw. Nov 4 '19 at 16:21
• @FranLovera Unfortunately, there's no standard NMR authenticated cipher built out of ChaCha and Poly1305, although there are easy constructions to build one: derive $k_0 \mathbin\| k_1 = \operatorname{ChaCha}_k(n),$ $t = \operatorname{HChaCha}_{k_0}(\operatorname{Poly1305}_{k_1}(m)),$ $k' = \operatorname{HChaCha}_{k_0}(t),$ and $c = m + \operatorname{ChaCha}_{k'}(0)$; ciphertext is $(c, t)$. To open, recover $k' = \operatorname{HChaCha}_{k_0}(t)$ and $m = c + \operatorname{ChaCha}_{k'}(0)$, and verify $t \stackrel?= \operatorname{HChaCha}_{k_0}(\operatorname{Poly1305}_{k_1}(m))$. Nov 4 '19 at 16:30