Is it safe to convert a 256-bit nonce into a 192-bit nonce by SHA-256ing and then truncating it?

I'd expect a 192-bit nonce derived from a 256-bit nonce by computing the SHA-256 hash and then truncating it to 24 bytes to behave like an approximately uniformly randomly generated 192-bit nonce and hence be good enough for using it e.g. as a nonce for XChaCha20-Poly1305 encryption. Is this correct? If yes, could maybe someone sketch the formal argument, and if no, explain the problem with this approach?

• I suggest reading through the Truncated Message Digest section of NIST's Recommendation for Applications Using Approved Hash Algorithms (nvlpubs.nist.gov/nistpubs/Legacy/SP/…). While it doesn't discuss XChaCha20, it does go through what's required for truncating a message digest as you are interested in doing. – Swashbuckler Mar 26 at 1:37

I'd expect a 196-bit nonce derived from a 256-bit nonce by computing the SHA-256 hash and then truncating it to 24 bytes to behave like an approximately uniformly randomly generated 196-bit nonce [...]

Actually, we don't need to appeal to the truncated SHA-256 being random; we can get away with appealing to collision resistance. Even if we allow an adversary to control the 256-bit nonces (with the stipulation that we don't let the adversary repeat a nonce), if they demonstrated the practical ability find a pair of distinct such nonces that would collide in your scheme, then their attack would imply a correspondingly practical collision-finding attack on 192-bit truncated SHA-256.

Truncated SHA-256 is believed to be as secure as the truncated output size allows, so your strategy should be alright.

XChaCha20 requires a 192-bit nonce size. As a rule of Stream ciphers, the nonce should not be repeated under the same key.

Note that; Daniel J. Bernstein is pointed in the XSalsa20 article for Salsa20 which has 64-bit nonces.

There is a standard argument that a 64-bit nonce is long enough. Nonce security does not mean unpredictability; it means uniqueness. Applications can generate a nonce as a monotonic timestamp or simply a counter 1,2,3,...

and

There is also a standard counterargument. Counters might sound simple but are sometimes mismanaged by applications, destroying security. Rather than blaming the application for this failure, we can append random bits to the nonce, adding protection that is likely to succeed even if the counter fails.

For Salsa20 using random nonce is not secure since the birthday bound on the collisions. One expects at least collision after $$2^{32}$$ random generation with 50% probability.

For XChaCha20 using random nonce is secure since the collision probability becomes nonnegligible if you encrypt $$2^{96}$$ messages under the same key.

I'd expect a 196-bit nonce derived from a 256-bit nonce by computing the SHA-256 hash and then truncating it to 24 bytes to behave like an approximately uniformly randomly generated 196-bit nonce and hence be good enough for using it e.g. as a nonce for XChaCha20-Poly1305 encryption.

If the input to the SHA256 is a good random source then we expect the usual collision probability. Except it doesn't guarantee that there is no repeat, however, that is negligible.

(This was in the comments by OP) In the extreme case the input is just a counter.

Your proposition is similar to building a CTR mode encryption from hash function. As long as the hash function has pseudo randomness properties the construction will work (most modern hash functions have this property). It will work, too.

You have the same problem as mentioned by Bernstein, the mismanagement of the counter that usually occurs system failures. The system may start from a previously used counter that will regenerate the same SHA256 values and that is insecurity may be more than one nonce.

Generate the nonce like $$nonce = random \mathbin\| counter$$ is a better and safe way. Now, the mismanagement of the only counter is handled.

Or, generate the nonce like $$nonce = random \mathbin\| \operatorname{SHA256}(counter).$$