Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aead: generalization of AEADs based on stream ciphers #45

Open
tarcieri opened this issue Aug 25, 2019 · 14 comments
Open

aead: generalization of AEADs based on stream ciphers #45

tarcieri opened this issue Aug 25, 2019 · 14 comments
Labels
aead Authenticated Encryption with Associated Data (AEAD) crate cipher Block and stream cipher crate

Comments

@tarcieri
Copy link
Member

Continuing the discussion from RustCrypto/AEADs#3 (comment)

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?

@newpavlov
Copy link
Member

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.

@tarcieri
Copy link
Member Author

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 tarcieri added the aead Authenticated Encryption with Associated Data (AEAD) crate label Feb 29, 2020
@tarcieri tarcieri changed the title AEADs based on stream ciphers aead: generalization of AEADs based on stream ciphers Feb 29, 2020
@cynecx
Copy link

cynecx commented Mar 30, 2020

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

@tarcieri
Copy link
Member Author

@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.

@cynecx
Copy link

cynecx commented Mar 30, 2020

@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

@tarcieri
Copy link
Member Author

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.

@cynecx
Copy link

cynecx commented Mar 30, 2020

@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.

@tarcieri
Copy link
Member Author

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.

@burdges
Copy link

burdges commented Mar 31, 2020

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.

@cynecx
Copy link

cynecx commented Mar 31, 2020

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 RustCrypto/AEADs#74 from happening?

@tarcieri
Copy link
Member Author

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.

@cynecx
Copy link

cynecx commented Apr 1, 2020

@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.

@tarcieri
Copy link
Member Author

tarcieri commented Apr 1, 2020

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.

@burdges
Copy link

burdges commented Apr 1, 2020

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.

@tarcieri tarcieri added cipher Block and stream cipher crate and removed stream-cipher labels Oct 15, 2020
dns2utf8 pushed a commit to dns2utf8/traits that referenced this issue Jan 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
aead Authenticated Encryption with Associated Data (AEAD) crate cipher Block and stream cipher crate
Projects
None yet
Development

No branches or pull requests

4 participants