rozbb / rust-hpke

An implementation of the HPKE hybrid encryption standard (RFC 9180)
Other
62 stars 32 forks source link

Make Serializable trait capable of serializing into user specified buffers #44

Closed wucke13 closed 11 months ago

wucke13 commented 1 year ago

I've been assembling a demonstrator with HPKE where I need to transmit public keys as byte slices. AFAICT the current design of Serializable forces a stack allocated array for keys. In hindsight of the recent merger of PQ support with Kyber, where the public keys are of significant size, this really breaks things. I.e. I had to up the default stack size in my demo code to 16KiB to avoid stack-overflows just when dumping a couple of public keys.

Also forcing double copying if there already is a destination where I need the keys bytes to go is unnecessary.

I think the serializable trait should include a method that I can provide with a &mut [u8] where it tries to write into that byte slice, returning the length written or a subslice. For example:

// almost like the one from std::io::Write 
fn write(&self, buf: &mut [u8]) -> Result<usize>;

// or like this, with the return value being the sub-slice containing the actual key
fn write(&self, buf: &mut [u8]) -> Result<&mut [u8]>;
rozbb commented 1 year ago

I agree with the reasoning here. More broadly, I would like to look more carefully at all the places we're implicitly copying things in the crate. I'm curious if there's any standard no-std Read/Write traits out there so we can avoid reinventing the wheel

tarcieri commented 1 year ago

I've found it's not too painful to make some crate-specific traits then in a std feature add blanket impls of Read/Write for the internal traits. That allows the traits to seamlessly plug into std use cases while still making trait-based abstraction possible on no_std.

rozbb commented 1 year ago

Oh, that's a nice way to do it

rozbb commented 11 months ago

I ended up taking the least-code route in #48. Since all the relevant sizes are fixed and generally quite small, I don't think there's much need for a Write-like trait. The new method, Serializable::write_exact, simply takes a mutable buffer of precisely the correct length and writes the serialization to it.

rozbb commented 11 months ago

@wucke13 merged the new trait defs into the Xyber branch, so you should be able to play with this now. Lmk how it works for you.