rw_builder/
stream_cipher.rs1use std::{
2 io::{Read, Write},
3 marker::PhantomData,
4};
5
6use anyhow::Result;
7#[cfg(feature = "chacha20")]
8use chacha20::ChaCha20;
9use cipher::{KeyIvInit, StreamCipher};
10#[cfg(feature = "salsa20")]
11use salsa20::Salsa20;
12
13use crate::RwBuilder;
14
15#[derive(Debug)]
18pub struct Builder<B, C, K, N>
19where
20 B: RwBuilder,
21 C: StreamCipher,
22{
23 builder: B,
25 key: K,
27 nonce: N,
29 _marker: PhantomData<C>,
31}
32
33impl<B, C, K, N> Builder<B, C, K, N>
34where
35 B: RwBuilder,
36 C: StreamCipher,
37{
38 pub const fn new(builder: B, key: K, nonce: N) -> Self {
40 Self { builder, key, nonce, _marker: PhantomData }
41 }
42}
43
44#[cfg(feature = "chacha20")]
46pub type ChaCha20Key = chacha20::Key;
47
48#[cfg(feature = "chacha20")]
50pub type ChaCha20Nonce = chacha20::Nonce;
51
52#[cfg(feature = "chacha20")]
54pub type ChaCha20Builder<B> = Builder<B, ChaCha20, ChaCha20Key, ChaCha20Nonce>;
55
56#[cfg(feature = "salsa20")]
58pub type Salsa20Key = salsa20::Key;
59
60#[cfg(feature = "salsa20")]
62pub type Salsa20Nonce = salsa20::Nonce;
63
64#[cfg(feature = "salsa20")]
66pub type Salsa20Builder<B> = Builder<B, Salsa20, Salsa20Key, Salsa20Nonce>;
67
68trait CipherFactory<C> {
70 fn create_cipher(&self) -> C;
72}
73
74#[cfg(feature = "chacha20")]
75impl<B> CipherFactory<ChaCha20> for Builder<B, ChaCha20, ChaCha20Key, ChaCha20Nonce>
76where
77 B: RwBuilder,
78{
79 fn create_cipher(&self) -> ChaCha20 {
80 ChaCha20::new(&self.key, &self.nonce)
81 }
82}
83
84#[cfg(feature = "salsa20")]
85impl<B> CipherFactory<Salsa20> for Builder<B, Salsa20, Salsa20Key, Salsa20Nonce>
86where
87 B: RwBuilder,
88{
89 fn create_cipher(&self) -> Salsa20 {
90 Salsa20::new(&self.key, &self.nonce)
91 }
92}
93
94impl<B, C, K, N> RwBuilder for Builder<B, C, K, N>
95where
96 B: RwBuilder,
97 C: StreamCipher,
98 Self: CipherFactory<C>,
99{
100 type Reader = Reader<B::Reader, C>;
101 type Writer = Writer<B::Writer, C>;
102
103 fn reader(&self) -> Result<Self::Reader> {
104 let reader = self.builder.reader()?;
105 let cipher = self.create_cipher();
106 Ok(Reader { cipher, reader })
107 }
108
109 fn writer(&self) -> Result<Self::Writer> {
110 let writer = self.builder.writer()?;
111 let cipher = self.create_cipher();
112 Ok(Writer { cipher, writer })
113 }
114}
115
116#[derive(Debug)]
118pub struct Reader<R, C>
119where
120 R: Read,
121 C: StreamCipher,
122{
123 cipher: C,
125 reader: R,
127}
128
129impl<R, C> Read for Reader<R, C>
130where
131 R: Read,
132 C: StreamCipher,
133{
134 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
135 let bytes_read = self.reader.read(buf)?;
136 self.cipher
137 .try_apply_keystream(buf)
138 .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
139 Ok(bytes_read)
140 }
141}
142
143#[derive(Debug)]
145pub struct Writer<W, C>
146where
147 W: Write,
148 C: StreamCipher,
149{
150 cipher: C,
152 writer: W,
154}
155
156impl<W, C> Write for Writer<W, C>
157where
158 W: Write,
159 C: StreamCipher,
160{
161 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
162 let mut buffer = buf.to_owned();
163 self.cipher
164 .try_apply_keystream(buffer.as_mut_slice())
165 .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
166 self.writer.write(buffer.as_slice())
167 }
168
169 fn flush(&mut self) -> std::io::Result<()> {
170 self.writer.flush()
171 }
172}