This seemed like an option if the hash is unpredictable.

It could be the hash of the message or the hash of the message + some common secret (apart from the key).

The only circumstance in which the hash would be predictable is when the message is the same. In that case, looking at the same nonce/hash wouldn't provide the attacker with any new information.

So it seems like a hash could work like a random number. Would it be safe to use the message hash as the IV in ChaCha?

  • $\begingroup$ ChaCha does not need an unpredictable IV. You can set it to zero for the first message you encrypt, then increment it every time you use the same key. Or you can leave it always zero and never reuse keys. $H(m)$ is bad because I can determine $m$ with high confidence by comparing $H(m)$ to $H(\text{known plaintext})$. $H_k(m)$ (mac-then-encrypt without nonce) reveals when messages are repeated. Additionally it may make replay attacks easier. $H_k(nonce, message)$ is better but using that nonce for encryption with encrypt-then-mac is much much better. $\endgroup$ Commented Jun 9, 2018 at 20:34

1 Answer 1


First, this is not safe with ChaCha because the ChaCha nonce is only 64 bits long, since ChaCha nonces are normally chosen sequentially, so there would be a nonnegligible danger of collision with a reasonable number of messages. Let's say XChaCha instead, with a 192-bit nonce, which is large enough to choose at random without danger of collision.

The recipient must know the nonce in order to decrypt the message, so we presumably have to transmit it alongside the ciphertext. Call the hash $h$; the ciphertext is $E_k(h, m) \mathbin\Vert h$, where $E_k(h, m)$ is the XChaCha encryption under key $k$ and nonce $h$ of the message $m$.

  • If you use a fixed public hash $h = H(m)$, such as SHA-256, then the ciphertext $E_k(h, m) \mathbin\Vert H(m)$ reveals information about the plaintext that the adversary can exploit: they can confirm a guess about what a plaintext was, e.g. Attack at dawn! vs. Attack at dusk!, by evaluating $H(m)$ themselves on their guesses and checking.

  • If you use a secret hash $h = H_\kappa(m)$, such as keyed BLAKE2s-192, you have a kind of MAC-and-encrypt composition. The adversary doesn't know the secret $\kappa$, and so can't confirm guesses. It doesn't quite achieve the security goal of authenticated encryption because if you repeat a message, the ciphertext will be repeated too. But that's the only leak that a cost-limited adversary will get, as you observed.

  • If you add a nonce parameter back into your system and use a secret hash $h = H_\kappa(n, m)$, then you get a nonce-misuse-resistant authenticated cipher. If you never repeat a nonce, it's authenticated encryption; if you do repeat a nonce, whether accidentally or cetaceaously, repeated ciphertexts are the only leak that a cost-limited adversary will get as above.

This is an SIV or synthetic initialization vector scheme, similar to others on the market like AES-SIV, AES-GCM-SIV, and various CAESAR gladiators with names that are too cool for a bird like me to remember. Using BLAKE2 won't beat any speed records—with BLAKE2, you pay for collision resistance, not just pseudorandomness—but it'll do the job if those are the parts you have on hand. A much faster approach might be to use a universal hash family to compress the message into 256 bits, say hash256, and feed that through a 256-to-192-bit PRF; one could probably do better by exploiting the structure of XChaCha as a composition of ChaCha and HChaCha.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.