1pub mod chacha20;
2
3use std::cmp::min;
4use std::marker;
5use std::vec;
6
7use num_derive::FromPrimitive;
8use num_traits::FromPrimitive;
9use rand::prelude::*;
10
11use crate::encoding::base64::Base64Encoding;
12use crate::encoding::EncodingTrait as _;
13use crate::hash::crc::Crc32cHasher;
14use crate::hash::crc::CRC32_OUTPUT_LENGTH;
15use crate::hash::sha256::Sha256Hasher;
16use crate::hash::HasherTrait;
17use crate::*;
18
19pub enum CipherAlgorithm {
21 ChaCha20,
22}
23
24#[derive(Clone)]
26pub enum CipherAlgorithmType {
27 Stream,
28 Block(usize),
29}
30
31pub trait CipherAlgorithmBaseTrait {
33 const IV_LENGTH: usize;
34 const KEY_LENGTH: usize;
35 const CIPHER_ALGORITHM_TYPE: CipherAlgorithmType;
36
37 fn iv_length() -> usize {
39 Self::IV_LENGTH
40 }
41
42 fn key_length() -> usize {
44 Self::KEY_LENGTH
45 }
46
47 fn cipher_algorithm_type() -> CipherAlgorithmType {
49 Self::CIPHER_ALGORITHM_TYPE
50 }
51}
52
53pub trait CipherAlgorithmTrait: CipherAlgorithmBaseTrait {
55 fn crypt(&mut self, src_data: &[u8], dst_data: &mut [u8]) -> Result<()>;
59}
60
61pub trait IVKeyNewTrait {
63 fn new(iv: &[u8], key: &[u8]) -> Result<Self>
65 where
66 Self: Sized;
67}
68
69pub trait StreamGeneratorTrait {
71 fn generate(&mut self, len: usize) -> Result<ByteVector>;
73}
74
75pub trait StringCrypterTrait {
77 fn encrypt(&self, data: &str, password: &str) -> Result<String>;
78 fn decrypt(&self, data: &str, password: &str) -> Result<String>;
79}
80
81#[derive(FromPrimitive, Clone)]
84pub enum StreamGeneratorMode {
85 Short = 1,
86 Medium = 32,
87 Large = 1024,
88}
89#[inline]
91const fn stream_temp_block_count(m: StreamGeneratorMode) -> usize {
92 return m as usize * 64;
93}
94
95#[inline]
97const fn stream_temp_buffer_size(m: StreamGeneratorMode) -> usize {
98 return m as usize * 1024;
99}
100
101pub struct StreamGenerator<CA: CipherAlgorithmTrait + IVKeyNewTrait> {
104 m_cipher_algorithm: CA,
106 m_mode: StreamGeneratorMode,
108 m_max_buffer_size: usize,
110 m_current_index: usize,
112 m_current_buffer: ByteVector,
114 m_plaintext_buffer: ByteVector,
116}
117
118impl<CA: CipherAlgorithmTrait + IVKeyNewTrait> StreamGenerator<CA> {
119 fn new(iv: &[u8], key: &[u8], mode: StreamGeneratorMode) -> Result<Self> {
121 let calc_stream_temp_buffer_size = |mode: StreamGeneratorMode| -> usize {
122 if let CipherAlgorithmType::Block(n) = CA::cipher_algorithm_type() {
123 return stream_temp_block_count(mode) * n;
124 }
125 stream_temp_buffer_size(mode)
126 };
127 let buffer_size = calc_stream_temp_buffer_size(mode.clone());
128 Ok(StreamGenerator::<CA> {
129 m_cipher_algorithm: CA::new(iv, key)?,
130 m_mode: mode.clone(),
131 m_current_index: buffer_size,
133 m_max_buffer_size: buffer_size,
134 m_current_buffer: vec![0x00; buffer_size],
135 m_plaintext_buffer: vec![0x00; buffer_size],
136 })
137 }
138
139 fn flush(&mut self) -> Result<()> {
141 if self.m_current_index != self.m_max_buffer_size {
142 return Err(CURRENT_INDEX_NOT_AT_THE_END_OF_BUFFER_WHEN_FLUSHING.clone());
143 }
144 self.m_cipher_algorithm
145 .crypt(&self.m_plaintext_buffer, &mut self.m_current_buffer)?;
146 self.m_current_index = 0;
147 Ok(())
148 }
149}
150
151impl<CA: CipherAlgorithmTrait + IVKeyNewTrait> IVKeyNewTrait for StreamGenerator<CA> {
152 fn new(iv: &[u8], key: &[u8]) -> Result<Self> {
154 Self::new(iv, key, StreamGeneratorMode::Medium)
155 }
156}
157
158impl<CA: CipherAlgorithmTrait + IVKeyNewTrait> StreamGeneratorTrait for StreamGenerator<CA> {
159 fn generate(&mut self, len: usize) -> Result<ByteVector> {
160 if len == 0 {
161 return Ok(ByteVector::new());
162 }
163 if self.m_current_index >= self.m_max_buffer_size {
165 self.flush()?;
166 }
167 let mut dst_data = vec![0x00 as u8; len];
169 let mut index: usize = 0;
171 let mut once_gen: usize = self.m_max_buffer_size - self.m_current_index;
173 while index + once_gen < len {
175 memcpy(
176 &mut dst_data[index..index + once_gen],
177 &self.m_current_buffer[self.m_current_index..self.m_current_index + once_gen],
178 )?;
179 index += once_gen;
180 self.m_current_index += once_gen;
181 self.flush()?;
182 once_gen = self.m_max_buffer_size - self.m_current_index;
183 }
184 let last_gen = len - index;
186 memcpy(
187 &mut dst_data[index..index + last_gen],
188 &self.m_current_buffer[self.m_current_index..self.m_current_index + last_gen],
189 )?;
190 index += last_gen;
191 self.m_current_index += last_gen;
192 Ok(dst_data)
193 }
194}
195
196#[inline]
198fn rand_iv(n: usize) -> ByteVector {
199 let mut res = vec![0x00; n];
200 let mut rng = rand::thread_rng();
201 rng.fill_bytes(&mut res);
202 res
203}
204
205#[inline]
208fn generate_key_from_password<HR: HasherTrait + Default>(password: &str, n: usize) -> ByteVector {
209 let mut hasher = HR::default();
211 hasher.update_message(password);
212 let mut buffer = hasher.finalize();
213 let mut cnt: usize = 0;
214 let mut res = vec![0x00; n];
215 while cnt < n {
216 let once_gen = min(n - cnt, buffer.len());
218 for i in 0..once_gen {
220 res[cnt + i] = buffer[i];
221 }
222 cnt += once_gen;
223 if cnt >= n {
224 break;
225 }
226 hasher.update_bytes(&buffer);
228 buffer = hasher.finalize();
229 }
230 res
231}
232
233pub struct StringCrypter<
235 CA: CipherAlgorithmTrait + IVKeyNewTrait,
236 HR: HasherTrait + Default = Crc32cHasher,
237> {
238 _ca: marker::PhantomData<CA>,
239 _hr: marker::PhantomData<HR>,
240}
241
242impl<CA: CipherAlgorithmTrait + IVKeyNewTrait, HR: HasherTrait + Default> StringCrypter<CA, HR> {
243 pub fn rand_iv(n: usize) -> ByteVector {
244 crate::crypter::rand_iv(n)
245 }
246
247 pub fn generate_key_from_password(password: &str, n: usize) -> ByteVector {
248 generate_key_from_password::<Sha256Hasher>(password, n)
249 }
250}
251
252impl<CA: CipherAlgorithmTrait + IVKeyNewTrait, HR: HasherTrait + Default> Default
253 for StringCrypter<CA, HR>
254{
255 fn default() -> Self {
256 StringCrypter::<CA, HR> {
257 _ca: marker::PhantomData::<CA>,
258 _hr: marker::PhantomData::<HR>,
259 }
260 }
261}
262
263impl<CA: CipherAlgorithmTrait + IVKeyNewTrait, HR: HasherTrait + Default> StringCrypterTrait
264 for StringCrypter<CA, HR>
265{
266 fn encrypt(&self, data: &str, password: &str) -> Result<String> {
267 if data.is_empty() {
268 return Err(CANNOT_DO_CRYPTION_TO_EMPTY_STRING.clone());
269 }
270 if password.is_empty() {
271 return Err(PASSWORD_CANNOT_BE_EMPTY.clone());
272 }
273
274 let iv = rand_iv(CA::IV_LENGTH);
276 let key = Self::generate_key_from_password(password, CA::KEY_LENGTH);
277 let mut stream_generator =
278 StreamGenerator::<CA>::new(&iv, &key, StreamGeneratorMode::Short)?;
279 let plain_data_bytes = data.as_bytes();
281 let plain_data_checksum = {
283 let mut c = HR::default();
284 c.update_bytes(&plain_data_bytes);
285 c.finalize()
286 };
287 let cipher_data_bytes = {
289 let cipher_stream = stream_generator.generate(plain_data_bytes.len())?;
290 xor(&cipher_stream, plain_data_bytes)?
291 };
292 let cipher_data_checksum = {
294 let cipher_stream = stream_generator.generate(plain_data_checksum.len())?;
295 xor(&cipher_stream, &plain_data_checksum)?
296 };
297 let res = [&iv[..], &cipher_data_checksum[..], &cipher_data_bytes[..]].concat();
298 Ok(Base64Encoding::default().encode(&res))
300 }
301
302 fn decrypt(&self, data: &str, password: &str) -> Result<String> {
303 if data.is_empty() {
304 return Err(CANNOT_DO_CRYPTION_TO_EMPTY_STRING.clone());
305 }
306 if password.is_empty() {
307 return Err(PASSWORD_CANNOT_BE_EMPTY.clone());
308 }
309
310 let b64 = Base64Encoding::default();
312 let data = b64.decode(data)?;
313 let mut iv = vec![0u8; CA::IV_LENGTH];
315 let mut cipher_data_checksum = vec![0u8; HR::OUTPUT_LENGTH];
316 let mut mt = MemoryTaker::new(&data);
317 let cipher_data_bytes = mt
318 .take(&mut iv)?
319 .take(&mut cipher_data_checksum)?
320 .take_all()?;
321 let key = Self::generate_key_from_password(password, CA::KEY_LENGTH);
323 let mut stream_generator =
324 StreamGenerator::<CA>::new(&iv, &key, StreamGeneratorMode::Short)?;
325 let plain_data_bytes = {
327 let cipher_stream = stream_generator.generate(cipher_data_bytes.len())?;
328 xor(&cipher_data_bytes, &cipher_stream)?
329 };
330 let plain_data_checksum = {
332 let cipher_stream = stream_generator.generate(cipher_data_checksum.len())?;
333 xor(&cipher_data_checksum, &cipher_stream)?
334 };
335 let calced_plain_data_checksum = {
337 let mut c = HR::default();
338 c.update_bytes(&plain_data_bytes);
339 c.finalize()
340 };
341 if plain_data_checksum != calced_plain_data_checksum {
342 return Err(FAILED_WHEN_CHECKING_CRC32_VALUE_OF_DECRYPTED_CONTENT.clone());
343 }
344 Ok(String::from_utf8(plain_data_bytes)
345 .map_err(|e| FAILED_WHEN_DECODING_STRING.add_opt_mess(&format!("{:?}", e)))?)
346 }
347}
348
349#[cfg(test)]
350mod tests {
351
352 use super::*;
353 use crate::encoding::hex::HexEncoding;
354 use crate::encoding::EncodingTrait;
355
356 #[test]
357 fn test_generate_key_from_password() {
358 let hexe = HexEncoding::default();
359 let res = generate_key_from_password::<Sha256Hasher>("123456", 32);
361 assert_eq!(
362 "8D969EEF6ECAD3C29A3A629280E686CF0C3F5D5A86AFF3CA12020C923ADC6C92".to_string(),
363 hexe.encode(&res)
364 );
365 let res = generate_key_from_password::<Sha256Hasher>("123456", 48);
367 assert_eq!("8D969EEF6ECAD3C29A3A629280E686CF0C3F5D5A86AFF3CA12020C923ADC6C9213619CFEA04EEB088EA04D789731EFED".to_string(), hexe.encode(&res));
368 }
369}