ChaCha builds on a 512 bit permutation and then applies a feed-forward by xoring the input into the output. Without truncation, that feed forward is essential for one-way-ness.
We're going to build a one-way function that maps a 32 byte value x
to another 32 byte value y
.
Using truncated ChaCha including the feed-forward
Put the x
into the 32 key
part of the input, put the normal constant into the 16 constant part and put something public (e.g. a constant or perhaps some kind of tweak) into the 16 byte nonce/offset part. Compute ChaCha including the feed-forward. Take whichever 32 bytes of output you like as y
.
Computing x
given y
implies being able to recover the ChaCha key from the key-stream. So this is a secure one way function if ChaCha is a secure stream cipher.
Using truncated ChaCha without the feed-forward
Since you truncate the output to half the permutation size the feed-forward isn't strictly necessary for one-way-ness.
In practice it doesn't matter which 32 bytes of output you choose, but if you want a security reduction to ChaCha it does.
The idea behind the proof is that the attacker knows 32 bytes of the input: the nonce and the constant. So they can undo that part of the feed-forward. This means that if you choose only the part of the output that's xor-ed with the nonce/constant but not the part of the input that's xor-ed with the key, you can omit the xor while retaining a security proof that this is as strong as ChaCha itself.
This construction mirrors the construction of HSalsa, so you could call it HChaCha. One important issue here is that Salsa puts the key into different words than ChaCha, so you need to take different words from the output in HChaCha.
=> take words 0, 1, 2, 3, 12, 13, 14, 15 as output.
My recommendation is to use HChaCha instead of ChaCha. Same security, better performance.
One interesting modification is to use a different nonce for each call, functioning as a tweak. It probably doesn't gain you much, but shouldn't hurt either.