Start: `Source<R>`: chacha20_poly1305 en/decryption wrapper over `io::Read` types.

TODO: `AsyncSource<R>`: Async version of `Source<R>`, and the `AsyncRead` couterpart of `AsyncSink<R>`.

TODO: `Stream<RW>`, `AsyncStream<RW>`: Combines both `Sink<W>` and `Source<R>` for `Read+Write` types (and async counterparts) using the same cipher key.

Fortune for chacha20stream's current commit: Small curse − 小凶
read-stream-wrapper_reuse-buffer-old
Avril 3 years ago
parent b64ae499ad
commit 42dbd94392
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -28,6 +28,11 @@ async = ["tokio", "pin-project"]
# Explicitly clear in-memory buffers with `explicit_bzero()` instead of normal `bzero()`. # Explicitly clear in-memory buffers with `explicit_bzero()` instead of normal `bzero()`.
explicit_clear = [] explicit_clear = []
# Reuse the output buffer for `Source`'s raw bytes read from the backing stream
#
# This can increase speed as no allocations are needed, however it can leak potentially sensitive data so is unsafe.
reuse-buffer = []
# Build with C interface bindings # Build with C interface bindings
ffi = ["libc"] ffi = ["libc"]

@ -56,55 +56,35 @@ pub type Error = ErrorStack;
/// The `flush()` implementation *does* clear this buffer. /// The `flush()` implementation *does* clear this buffer.
/// You can use the `prune()` function to zero out this buffer manually too. /// You can use the `prune()` function to zero out this buffer manually too.
//#[derive(Debug)] //#[derive(Debug)]
pub struct Sink<W> pub struct Sink<W: ?Sized>
{ {
stream: W,
crypter: Crypter, // for chacha, finalize does nothing it seems. we can also call it multiple times. crypter: Crypter, // for chacha, finalize does nothing it seems. we can also call it multiple times.
buffer: BufferVec, // used to buffer the operation buffer: BufferVec, // used to buffer the operation
}
impl<W: fmt::Debug> fmt::Debug for Sink<W> stream: W,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "Sink({:?}, ({} buffer cap))", self.stream, self.buffer.capacity())
}
} }
impl<W> Sink<W> /// TODO: Document
where W: Write //#[derive(Debug)]
{ pub struct Source<R>
/// Create a new Chacha Sink stream wrapper
#[inline] fn new(stream: W, crypter: Crypter) -> Self
{ {
Self{stream, crypter, buffer: BufferVec::new()} crypter: Crypter,
} #[cfg(not(feature="reuse-buffer"))] buffer: BufferVec, // When `reuse-buffer` is enabled, this isn't needed. We re-use the output buffer for the initial read of untransformed data from `stream` and the actual transformation of the read bytes.
/// Create an encrypting Chacha Sink stream wrapper stream: R
pub fn encrypt(stream: W, key: Key, iv: IV) -> Result<Self, Error>
{
Ok(Self::new(stream, cha::encrypter(key, iv)?))
} }
/// Create a decrypting Chacha Sink stream wrapper impl<W: ?Sized+ fmt::Debug> fmt::Debug for Sink<W>
pub fn decrypt(stream: W, key: Key, iv: IV) -> Result<Self, Error>
{ {
Ok(Self::new(stream, cha::decrypter(key, iv)?)) fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
}
/// Consume into the inner stream
#[inline] pub fn into_inner(self) -> W
{ {
self.stream write!(f, "Sink({:?}, ({} buffer cap))", &self.stream, self.buffer.capacity())
}
} }
/// Consume into the inner stream and crypter impl<W: ?Sized> Sink<W>
#[inline] pub fn into_parts(self) -> (W, Crypter) where W: Write
{ {
(self.stream, self.crypter)
}
/// The crypter of this instance /// The crypter of this instance
#[inline] pub fn crypter(&self) -> &Crypter #[inline] pub fn crypter(&self) -> &Crypter
@ -162,7 +142,44 @@ where W: Write
} }
} }
impl<W: Write> Write for Sink<W> impl<W> Sink<W>
where W: Write
{
/// Create a new Chacha Sink stream wrapper
#[inline] fn new(stream: W, crypter: Crypter) -> Self
{
Self{stream, crypter, buffer: BufferVec::new()}
}
/// Create an encrypting Chacha Sink stream wrapper
pub fn encrypt(stream: W, key: Key, iv: IV) -> Result<Self, Error>
{
Ok(Self::new(stream, cha::encrypter(key, iv)?))
}
/// Create a decrypting Chacha Sink stream wrapper
pub fn decrypt(stream: W, key: Key, iv: IV) -> Result<Self, Error>
{
Ok(Self::new(stream, cha::decrypter(key, iv)?))
}
/// Consume into the inner stream
#[inline] pub fn into_inner(self) -> W
{
self.stream
}
/// Consume into the inner stream and crypter
#[inline] pub fn into_parts(self) -> (W, Crypter)
{
(self.stream, self.crypter)
}
}
impl<W: ?Sized + Write> Write for Sink<W>
{ {
#[inline] fn write(&mut self, buf: &[u8]) -> io::Result<usize> { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let n = self.transform(buf)?; let n = self.transform(buf)?;

Loading…
Cancel
Save