RustCrypto / stream-ciphers

Collection of stream cipher algorithms
255 stars 49 forks source link

chacha20: 64-bit counter support #334

Open tarcieri opened 10 months ago

tarcieri commented 10 months ago

The ChaCha20Legacy construction, i.e. the djb variant, is supposed to use a 64-bit counter but currently uses a 32-bit counter because it shares its core implementation with the IETF construction which uses a 32-bit counter.

This results in a counter overflow after generating 256 GiB of keystream. Compatible implementations are able to generate larger keystreams.

I'm not sure how much of a practical concern this actually is, but it did come up in discussions here: https://github.com/rust-random/rand/issues/934#issuecomment-1778069288

We can probably make the counter type generic between u32/u64 in the core implementation if need be.

nstilt1 commented 9 months ago

I have some seemingly working code for this, but it builds on the Rng PR with variants.rs. Would you like me to try to adjust it for the current state of chacha20 or wait for the potential merge before opening a PR for it?

tarcieri commented 9 months ago

Let's try to land #333 first

nstilt1 commented 3 months ago

I took another look at my 64-bit counter code, and it isn't working correctly on the NEON backend atm.

It uses a const bool in variants.rs to determine which way the counter should be added in the backend, but if there's a better way to do this that doesn't involve modifying the backend code... it might be better. It is currently failing a test shortly after reaching the u32::MAX block pos.

The largest use-case for a 64-bit counter (that I can think of) is file system encryption for mobile devices. I've ran some benches, and chacha20 and even chacha20poly1305 is faster than AES on aarch64. I've benched it on the cloud, on a compute EC2 instance. I would imagine that it's also faster on mobile devices. So... if the 64-bit counter only works for x86 and the software implementation, then there wouldn't really be a point if the main use case is on aarch64.

I will keep working on it a little, but I'd probably prefer a solution that doesn't need to modify the backends, if that's possible. Because the way it is now, every new backend would also need to have specific code for updating the counter