magic_crypt/ciphers/
des64.rs

1use alloc::vec::Vec;
2#[cfg(feature = "std")]
3use std::intrinsics::copy;
4#[cfg(feature = "std")]
5use std::io::{ErrorKind, Read, Write};
6#[cfg(feature = "std")]
7use std::ops::Add;
8
9#[cfg(feature = "std")]
10use aes::cipher::{
11    block_padding::RawPadding,
12    generic_array::typenum::{IsGreaterOrEqual, PartialDiv, True, B1, U16},
13    ArrayLength,
14};
15use crc_any::CRCu64;
16use des::{
17    cipher::{
18        block_padding::Pkcs7, generic_array::GenericArray, BlockDecryptMut, BlockEncryptMut, Iv,
19        Key, KeyIvInit,
20    },
21    Des,
22};
23
24#[cfg(feature = "std")]
25use crate::functions::to_blocks;
26use crate::{MagicCryptError, MagicCryptTrait};
27
28type Des64CbcEnc = cbc::Encryptor<Des>;
29type Des64CbcDec = cbc::Decryptor<Des>;
30
31#[cfg(feature = "std")]
32const BLOCK_SIZE: usize = 8;
33
34/// This struct can help you encrypt or decrypt data via AES-64 in a quick way.
35#[derive(Debug, Clone)]
36pub struct MagicCrypt64 {
37    key: Key<Des64CbcEnc>,
38    iv:  Iv<Des64CbcEnc>,
39}
40
41impl MagicCryptTrait for MagicCrypt64 {
42    fn new<S: AsRef<[u8]>, V: AsRef<[u8]>>(key: S, iv: Option<V>) -> MagicCrypt64 {
43        let iv = match iv {
44            Some(s) => {
45                let mut hasher = CRCu64::crc64we();
46                hasher.digest(s.as_ref());
47
48                GenericArray::clone_from_slice(&hasher.get_crc_vec_be())
49            },
50            None => GenericArray::default(),
51        };
52
53        let key = {
54            let mut hasher = CRCu64::crc64we();
55            hasher.digest(key.as_ref());
56
57            GenericArray::clone_from_slice(&hasher.get_crc_vec_be())
58        };
59
60        MagicCrypt64 {
61            key,
62            iv,
63        }
64    }
65
66    #[inline]
67    fn encrypt_to_bytes<T: ?Sized + AsRef<[u8]>>(&self, data: &T) -> Vec<u8> {
68        let data = data.as_ref();
69
70        let cipher = Des64CbcEnc::new(&self.key, &self.iv);
71
72        cipher.encrypt_padded_vec_mut::<Pkcs7>(data)
73    }
74
75    #[cfg(feature = "std")]
76    fn encrypt_reader_to_bytes(&self, reader: &mut dyn Read) -> Result<Vec<u8>, MagicCryptError> {
77        let mut final_result = Vec::new();
78
79        let data_length = reader.read_to_end(&mut final_result)?;
80
81        let padding_length = BLOCK_SIZE - (data_length % BLOCK_SIZE);
82        let final_length = data_length + padding_length;
83
84        final_result.reserve_exact(padding_length);
85
86        unsafe {
87            final_result.set_len(final_length);
88        }
89
90        let cipher = Des64CbcEnc::new(&self.key, &self.iv);
91
92        cipher.encrypt_padded_mut::<Pkcs7>(&mut final_result, data_length).unwrap();
93
94        Ok(final_result)
95    }
96
97    #[cfg(feature = "std")]
98    fn encrypt_reader_to_writer2<
99        N: ArrayLength<u8> + PartialDiv<U16> + IsGreaterOrEqual<U16, Output = True>,
100    >(
101        &self,
102        reader: &mut dyn Read,
103        writer: &mut dyn Write,
104    ) -> Result<(), MagicCryptError> {
105        let mut buffer: GenericArray<u8, N> = GenericArray::default();
106
107        let mut cipher = Des64CbcEnc::new(&self.key, &self.iv);
108
109        let mut l = 0;
110
111        loop {
112            match reader.read(&mut buffer[l..]) {
113                Ok(c) => {
114                    if c == 0 {
115                        break;
116                    }
117
118                    l += c;
119
120                    if l < BLOCK_SIZE {
121                        continue;
122                    }
123
124                    let r = l % BLOCK_SIZE;
125                    let e = l - r;
126
127                    cipher.encrypt_blocks_mut(to_blocks(&mut buffer[..e]));
128
129                    writer.write_all(&buffer[..e])?;
130
131                    unsafe {
132                        copy(buffer.as_ptr().add(e), buffer.as_mut_ptr(), r);
133                    }
134
135                    l = r;
136                },
137                Err(error) if error.kind() == ErrorKind::Interrupted => {},
138                Err(error) => return Err(MagicCryptError::IOError(error)),
139            }
140        }
141
142        let raw_block = &mut buffer[..BLOCK_SIZE];
143
144        Pkcs7::raw_pad(raw_block, l);
145        cipher.encrypt_blocks_mut(to_blocks(raw_block));
146
147        writer.write_all(raw_block)?;
148
149        Ok(writer.flush()?)
150    }
151
152    #[inline]
153    fn decrypt_bytes_to_bytes<T: ?Sized + AsRef<[u8]>>(
154        &self,
155        bytes: &T,
156    ) -> Result<Vec<u8>, MagicCryptError> {
157        let bytes = bytes.as_ref();
158
159        let cipher = Des64CbcDec::new(&self.key, &self.iv);
160
161        let final_result = cipher.decrypt_padded_vec_mut::<Pkcs7>(bytes)?;
162
163        Ok(final_result)
164    }
165
166    #[cfg(feature = "std")]
167    fn decrypt_reader_to_bytes(&self, reader: &mut dyn Read) -> Result<Vec<u8>, MagicCryptError> {
168        let mut final_result = Vec::new();
169
170        reader.read_to_end(&mut final_result)?;
171
172        let cipher = Des64CbcDec::new(&self.key, &self.iv);
173
174        let data_length = cipher.decrypt_padded_mut::<Pkcs7>(&mut final_result)?.len();
175
176        final_result.truncate(data_length);
177
178        Ok(final_result)
179    }
180
181    #[cfg(feature = "std")]
182    #[allow(clippy::many_single_char_names)]
183    fn decrypt_reader_to_writer2<
184        N: ArrayLength<u8> + PartialDiv<U16> + IsGreaterOrEqual<U16, Output = True> + Add<B1>,
185    >(
186        &self,
187        reader: &mut dyn Read,
188        writer: &mut dyn Write,
189    ) -> Result<(), MagicCryptError>
190    where
191        <N as Add<B1>>::Output: ArrayLength<u8>, {
192        let mut buffer: GenericArray<u8, N> = GenericArray::default();
193
194        let mut cipher = Des64CbcDec::new(&self.key, &self.iv);
195        let mut l = 0;
196
197        loop {
198            match reader.read(&mut buffer[l..]) {
199                Ok(c) => {
200                    if c == 0 {
201                        break;
202                    }
203
204                    l += c;
205
206                    if l < BLOCK_SIZE {
207                        continue;
208                    }
209
210                    let r = l % BLOCK_SIZE;
211                    let e = if r > 0 { l + BLOCK_SIZE - r } else { l };
212
213                    // fill the last block
214                    reader.read_exact(&mut buffer[l..e])?;
215
216                    match reader.read_exact(&mut buffer[e..(e + 1)]) {
217                        Ok(()) => {
218                            cipher.decrypt_blocks_mut(to_blocks(&mut buffer[..e]));
219
220                            writer.write_all(&buffer[..e])?;
221
222                            buffer[0] = buffer[e];
223
224                            l = 1;
225                        },
226                        Err(error) if error.kind() == ErrorKind::UnexpectedEof => {
227                            cipher.decrypt_blocks_mut(to_blocks(&mut buffer[..e]));
228
229                            writer.write_all(Pkcs7::raw_unpad(&buffer[..e])?)?;
230
231                            break;
232                        },
233                        Err(error) => return Err(MagicCryptError::IOError(error)),
234                    }
235                },
236                Err(error) if error.kind() == ErrorKind::Interrupted => {},
237                Err(error) => return Err(MagicCryptError::IOError(error)),
238            }
239        }
240
241        Ok(writer.flush()?)
242    }
243}