traits icon indicating copy to clipboard operation
traits copied to clipboard

aead: generalization of AEADs based on stream ciphers

Open tarcieri opened this issue 5 years ago • 14 comments

Continuing the discussion from https://github.com/RustCrypto/AEADs/pull/3#issuecomment-523557454

It'd be good to have traits for implementing AEADs based on stream ciphers. The aead crate presents an interface which is generic enough to incorporate the one AEAD mode based on a block cipher, but most useful AEADs are based on stream ciphers, so it'd be nice to have trait(s) with blanket impls for StatelessAead which support generic composition based on the stream-cipher traits.

I'm not sure what crate these belong in. Should the aead crate have a stream-cipher feature? Or should the stream-cipher crate have an aead feature?

tarcieri avatar Aug 25 '19 18:08 tarcieri

I think that AEAD is a higher level concept than steam ciphers, so it would make sense to include this functionality to the aead crate.

newpavlov avatar Aug 25 '19 21:08 newpavlov

Another issue is that I have deliberately not impl'd the Mac trait for Poly1305, and feel the same way about POLYVAL/GHASH, as these are, at best, "one time authenticators". But we still need something generic to bound on for a generic stream cipher AEAD.

@newpavlov what do you think about adding a trait like OneTimeMac which a generic stream cipher AEAD can bound on, with a blanket impl for all Mac types, which can be used to express the idea that things like Poly1305/POLYVAL cannot be reused with the same key?

tarcieri avatar Aug 25 '19 21:08 tarcieri

Ping? I guess this will provide an api which allows encrypting/decrypting "chunk-wise" data? (The current aead api doesn't support this.)

cynecx avatar Mar 30 '20 17:03 cynecx

@cynecx AEADs are inherently all-or-nothing by design.

You're probably interested in something like Rogaway's STREAM construction, which we've also discussed adding, and perhaps I can work on soon.

This issue pertains to constructing AEADs from unauthenticated stream ciphers in a generic way, whereas the current implementations all contain some repetitive logic.

Having a single generic core is also a single place to focus on improvements to e.g. buffering strategies.

tarcieri avatar Mar 30 '20 17:03 tarcieri

@tarcieri Ehrm, perhaps my comment is more or less ambiguous. I simply seek a way to do aead with known-sized data, however the environment is resource-constrained (limited ram), so I can't fully load the buffer into memory, so I would like to read the data chunks-wise and encrypt/decrypt accordingly.

pseudocode:

let aead = ChaCha20Poly1305::encrypt(nonce, key);
aead.update(data1); // This encrypts data1 in-place
aead.update(data2);
aead.update(data3); // there are only 3 chuncks, but only one chunk can be loaded into memory at a time.
let tag = aead.finish(); // the aead auth tag

cynecx avatar Mar 30 '20 18:03 cynecx

I'd still suggest using STREAM for that. AEADs are only safe if they do not disclosed unauthenticated data. STREAM allows for chunk-wise processing while still ensuring all chunks are authenticated.

tarcieri avatar Mar 30 '20 18:03 tarcieri

@tarcieri Sorry I don’t quite understand. How does encrypting in chunks affect safety? Let’s say I want to encrypt 100 bytes. I could simply use the current api as it is. However because the environment has limited memory I can only load 50 bytes at a time, so I basically have to encrypt/hash the first and second part. I don’t see why I shouldn’t use aead here and how would STREAM help here? because I see it mostly as an api limitation.

cynecx avatar Mar 30 '20 21:03 cynecx

Aah, sorry, for some AEAD modes streaming encryption is possible and safe.

The security issue is around streaming decryption and exposing unauthenticated plaintexts before the MAC tag has been checked.

tarcieri avatar Mar 30 '20 21:03 tarcieri

We've three-ish choices for Poly1305:

  • Poly1305 : Mac + !MacPlus,
  • Poly1305 : MacOnce + !Mac,
  • impl Poly1305 for Mac { const Plus : bool = false; ... }

Associated constants break trait objects completely now, but maybe they'll get fixed eventually, and generic array sucks for trait objects anyways.

burdges avatar Mar 31 '20 10:03 burdges

The security issue is around streaming decryption and exposing unauthenticated plaintexts before the MAC tag has been checked.

An authentication-only api could help here, so the user can authenticate and then do the decryption/encryption accordingly, however this raises ergonomics issues, like you are required to provide each buffer twice. In terms of efficiency, it would be the same, as the current implementation does two passes anyway.

@tarcieri Wouldn't this also prevent https://github.com/RustCrypto/AEADs/issues/74 from happening?

cynecx avatar Mar 31 '20 21:03 cynecx

Doing two passes like that where it can't take ownership of one contiguous buffer carries a risk that an attacker could potentially provide a different ciphertext for the second pass.

Generally I'd consider anything besides an all-or-nothing API for decryption pretty risky.

tarcieri avatar Mar 31 '20 21:03 tarcieri

@tarcieri Yeah, I agree. However, how about we could drop in-place decryption then? I've settled for sodiumoxide's secretstream for now which supports specifying an output buffer and also supports encrypting and decrypting in chunks (pull_to_vec). The api feels really nice to use and I would hope something similar could land here too.

cynecx avatar Apr 01 '20 01:04 cynecx

I discussed secretstream in the post about Rogaway's STREAM I linked earlier. They accomplish the same goals, but secretstream imposes its own bespoke message framing, and unlike Rogaway's STREAM doesn't have security proofs.

tarcieri avatar Apr 01 '20 03:04 tarcieri

I agree with Tony that AEADs need all-of-nothing APIs. We're talking about 16 byte MACs in the case of Poly1305, and never more than 32 bytes, so you can afford one tag per chunk even under rather tight memory constraints. Also, your computation time depends primarily upon the total message length, not the number of tags.

There are scenarios in which MACs to not work, like fitting data into the expected disk sector size, or 512 byte Tor frames, but normally you want wide block ciphers for this, quite a different construction.

burdges avatar Apr 01 '20 09:04 burdges