traits icon indicating copy to clipboard operation
traits copied to clipboard

adding detached tag mode to stream

Open laudiacay opened this issue 3 years ago • 9 comments

Hiiii

I really wanted detached tags on the streaming encryption mode because I was having to do some really messed up things with buffers that were slowing me down.

I wrote it, it compiles and I'm not sure what tests you'd want... I didn't quite get it working with y'all's macros either but I don't think that made sense bc they were meant to deduplicate code between Encryptor and Decryptor, but it only really makes sense for Encryptors to detach tags... Hope this is cleaned up okay enough, lmk what I should change :)

laudiacay avatar Jan 13 '23 06:01 laudiacay

This is OK but it should probably also have the corresponding detached methods on Decryptor too

tarcieri avatar Jan 13 '23 14:01 tarcieri

added- let's see if tests pass now...

laudiacay avatar Jan 13 '23 22:01 laudiacay

This looks good now, however it's a breaking change, so it will have to be part of the next release cycle (which we'll likely be starting soon)

tarcieri avatar Jan 15 '23 19:01 tarcieri

Cool- is there anything else I can do around RustCrypto that might be good for a beginner to this codebase? Always looking for weekend/downtime fun code besides, like, project euler.

On Sun, Jan 15, 2023 at 1:41 PM, Tony Arcieri @.***> wrote:

This looks good now, however it's a breaking change, so it will have to be part of the next release cycle (which we'll likely be starting soon)

— Reply to this email directly, view it on GitHub https://github.com/RustCrypto/traits/pull/1189#issuecomment-1383233989, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACDPMJE7EEEJFMZHBQRMLZ3WSRHFFANCNFSM6AAAAAAT2CI45E . You are receiving this because you authored the thread.Message ID: @.***>

laudiacay avatar Jan 15 '23 23:01 laudiacay

I also wrote a silly little Writer impl for Encryptor:

can obviously be improved in multiple places (generalizing over ciphers, for one, haha), but it works

here's how i used it to make my code a little nicer...

    let mut gzencoder = GzEncoder::new(encrypted_writer, Compression::default());
...
        gzencoder.write_all(&buf_for_input[..n])?;
        gzencoder.flush()?;
...
    let encryptor = gzencoder.finish()?;
    let bytes_written = encryptor.finish()?;

and here's the code:

pub struct EncryptionWriter<W: Write> {
    buf: Vec<u8>,
    writer: W,
    encryptor: Encryptor<Aes256Gcm, StreamBE32<Aes256Gcm>>,
    bytes_written: usize,
}

impl<W: Write> EncryptionWriter<W> {
    pub fn new(writer: W, key: &[u8]) -> Self {
        let mut nonce = [0u8; 12];
        OsRng.fill_bytes(&mut nonce);
        let cipher = Aes256Gcm::new(key.as_ref().into());
        let encryptor = StreamBE32::from_aead(cipher, nonce.as_ref().into()).encryptor();
        Self {
            buf: Vec::new(),
            writer,
            encryptor,
            bytes_written: 0,
        }
    }

    fn finish(mut self) -> Result<usize> {
        self.flush()?;
        self.encryptor
            .encrypt_last_in_place(b"".as_ref(), &mut self.buf)
            .unwrap();
        self.writer.write_all(&self.buf)?;
        self.bytes_written += self.buf.len();
        Ok(self.bytes_written)
    }
}

impl<W: Write> Write for EncryptionWriter<W> {
    // TODO better buffering? bufwriter?
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.buf.extend_from_slice(buf);
        Ok(buf.len())
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.encryptor
            .encrypt_next_in_place(b"", &mut self.buf)
            .unwrap();
        self.writer.write_all(&self.buf)?;
        self.writer.flush()?;
        self.bytes_written += self.buf.len();
        self.buf.clear();
        Ok(())
    }
}

laudiacay avatar Jan 16 '23 04:01 laudiacay

sorta like #641 but not for hashes

laudiacay avatar Jan 16 '23 04:01 laudiacay

@laudiacay yeah, the buffering is what makes that tricky, but also without either fixed size chunks or some kind of framing protocol you can't write a corresponding decryptor because you don't know the boundaries of the AEAD messages (I personally prefer the fixed-sized chunks approach because it has no size overhead beyond the tags)

If you're looking for other small things to work on, we could use some help here: https://github.com/RustCrypto/hashes/issues/87

tarcieri avatar Jan 16 '23 15:01 tarcieri

What is the status of this PR? I have a use case where I need to use a &mut [u8] instead of &mut dyn Buffer (like the standard AeadInPlace::*_detached methods). Would changing this PR to match that signature be a blocker?

Also re:

This looks good now, however it's a breaking change, so it will have to be part of the next release cycle (which we'll likely be starting soon)

Not sure if that has already come and gone, or was delayed since that was 6 months ago. So this may be a consideration as well.

kbknapp avatar Jul 25 '23 17:07 kbknapp

Still waiting on the next breaking release cycle, which will come after #1174

tarcieri avatar Jul 25 '23 17:07 tarcieri

aead-stream has been moved to: https://github.com/RustCrypto/AEADs/tree/master/aead-stream

tarcieri avatar Sep 28 '24 17:09 tarcieri