13

Public nonces can be problematic for privacy when they can be considered metadata. They can also be troublesome for security if you do things like using a hash of the message as the nonce.

PASETO now derives the nonce alongside the key using HKDF on the input keying material with a 256-bit salt. Thus, the actual nonce passed to AES-CTR and XChaCha is not revealed publicly.

The nonce used by AES-256-CTR and XChaCha20 will be derived from the HKDF output (which is now 48 bytes for v3.local and 56 bytes for v4.local). The first 32 bytes of each HKDF output will be used as the key. The remaining bytes will be used as the nonce for the underlying cipher.

TripleSec, an overkill multiple encryption library by Keybase, encrypts inner nonces.

The TripleSec technique takes one futher step not suggested by Schneier, which is to protect the inner IVs with the outer encryption algorithms, and only exposing the outermost IV in the clear. Though we can't prove this makes the scheme more secure, it seems like a reasonable idea: why reveal cipher inputs if we don't have to?

As the nonce is secret as well as the key from an attacker, how much security is likely gained from these types of approaches? Would it still be meaningfully beneficial with small nonces (e.g. 64 and 96 bits)?

I assume this is quite good with XChaCha20 due to the subkey derivation.

samuel-lucas6
  • 2,211
  • 9
  • 20

3 Answers3

17

Nonces (and initialization vectors) are generally public. Assuming a sensible implementation (using a hash of the message as the nonce is not sensible), then no meaningful security is gained by making the nonce private.

Nonces are often simple counters that never repeat. For algorithms that accept large nonces (such as XChaCha20's 192-bit nonce), nonce-generation with a CSPRNG is also secure (and easier to manage).

In all likelihood, you're more likely to reduce security by implementing a home-baked scheme that derives the nonce by some other deterministic means. This advice may not seem intuitive, similar to how one may naively think that double-encryption increases security. My advice would be to use XChaCha20 and a public nonce generated by a decent CSPRNG.

hunter
  • 4,051
  • 6
  • 29
  • 42
16

Hiding the nonce provides no tangible benefit. In the case of ChaCha where the input block is the concatenation of a constant, the key, a nonce, and a counter, using a random and secret nonce could be thought of as extending the key and reducing the size of the nonce. For IETF ChaCha with a 256-bit key, a 96-bit nonce and 32-bit counter, you could effectively turn it into a cipher with a 352-bit key and a 32-bit counter. Sure, this does increase the keyspace which technically improves security, but there's no need to do that as 256 bits is plenty. It works a little differently with block ciphers.

Interestingly, the Linux kernel's random driver uses a secret nonce (and secret counter) to initialize ChaCha20 as its CSPRNG. It uses random a 64-bit counter and nonce, so the key is effectively 320 bits (although the kernel only reseeds the 256-bit key). This is not done explicitly to improve security, but because it's easier to initialize the entire ChaCha input block with a constant and random data.

I have to echo what others have said though and warn you that going out of your way to hide the nonce is probably a bad idea! If your design is such that the nonce is naturally secret, then there's no reason to make it public, but there's also no reason to try to design a system where it must be secret.

My advice: If it would take more work to make the nonce public, then keep it secret. If it would take more work to make it secret, then keep it public. There's no need to complicate things.

forest
  • 15,626
  • 2
  • 49
  • 103
7

You can go back to the definition of the word. "Nonce" means "number once". It is a number with one and one feature only - that it is only used once. By definition and design, it should not be used in any manner which relies on it being secret. Algorithms will use it in places where it avoids replay attacks and similar things, i.e., attacks where you can repeat inputs to the algorithm without knowing the key.

To put it the other way 'round: if an algorithm requires the nonce to be secret, or if an algorithm becomes more secure if the nonce is kept secret, then by definition the nonce is not a nonce anymore, but part of the secret (i.e. the key).

Compare this to the general concept of differing the secret (i.e. the key) from anything else in cryptography. A good first benchmark for thinking about whether an algorithm is good is to verify that the key is literally the only thing that benefits from being secret, and assuming everything else (including nonces, salts etc.) can be public. Anything else would be either mislabeling, or just security by obscurity.

AnoE
  • 343
  • 1
  • 3