1use des::{
38 Des,
39 cipher::{BlockDecrypt, BlockEncrypt, KeyInit},
40};
41
42use crate::{Result, ZusError};
43
44pub const DES_BLOCK_SIZE: usize = 8;
46
47pub const DES_KEY_SIZE: usize = 8;
49
50#[derive(Clone)]
54pub struct DesEncryptor {
55 cipher: Des,
56}
57
58impl DesEncryptor {
59 pub fn new(key: &[u8]) -> Self {
67 assert_eq!(key.len(), DES_KEY_SIZE, "DES key must be exactly 8 bytes");
68 let cipher = Des::new_from_slice(key).expect("Invalid key length");
69 Self { cipher }
70 }
71
72 pub fn try_new(key: &[u8]) -> Result<Self> {
81 if key.len() != DES_KEY_SIZE {
82 return Err(ZusError::Encryption(format!(
83 "DES key must be exactly 8 bytes, got {}",
84 key.len()
85 )));
86 }
87 let cipher = Des::new_from_slice(key).map_err(|e| ZusError::Encryption(e.to_string()))?;
88 Ok(Self { cipher })
89 }
90
91 pub fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
101 let padded_len = if data.is_empty() {
103 DES_BLOCK_SIZE
104 } else {
105 data.len().div_ceil(DES_BLOCK_SIZE) * DES_BLOCK_SIZE
106 };
107
108 let mut buffer = vec![0u8; padded_len];
110 buffer[..data.len()].copy_from_slice(data);
111
112 for chunk in buffer.chunks_exact_mut(DES_BLOCK_SIZE) {
114 let block: &mut [u8; 8] = chunk.try_into().unwrap();
115 self.cipher.encrypt_block(block.into());
116 }
117
118 Ok(buffer)
119 }
120
121 pub fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
132 if !data.len().is_multiple_of(DES_BLOCK_SIZE) {
133 return Err(ZusError::Encryption(format!(
134 "Encrypted data length must be multiple of 8, got {}",
135 data.len()
136 )));
137 }
138
139 let mut buffer = data.to_vec();
140
141 for chunk in buffer.chunks_exact_mut(DES_BLOCK_SIZE) {
143 let block: &mut [u8; 8] = chunk.try_into().unwrap();
144 self.cipher.decrypt_block(block.into());
145 }
146
147 Ok(buffer)
148 }
149
150 pub fn encrypt_in_place(&self, data: &mut Vec<u8>, offset: usize) -> Result<()> {
158 if offset >= data.len() {
159 return Ok(());
160 }
161
162 let len = data.len() - offset;
163 let padded_len = len.div_ceil(DES_BLOCK_SIZE) * DES_BLOCK_SIZE;
164
165 if offset + padded_len > data.len() {
167 data.resize(offset + padded_len, 0);
168 }
169
170 let slice = &mut data[offset..];
172 for chunk in slice.chunks_exact_mut(DES_BLOCK_SIZE) {
173 let block: &mut [u8; 8] = chunk.try_into().unwrap();
174 self.cipher.encrypt_block(block.into());
175 }
176
177 Ok(())
178 }
179
180 pub fn decrypt_in_place(&self, data: &mut [u8], offset: usize) -> Result<()> {
188 if offset >= data.len() {
189 return Ok(());
190 }
191
192 let slice = &mut data[offset..];
193 if !slice.len().is_multiple_of(DES_BLOCK_SIZE) {
194 return Err(ZusError::Encryption(format!(
195 "Data length from offset must be multiple of 8, got {}",
196 slice.len()
197 )));
198 }
199
200 for chunk in slice.chunks_exact_mut(DES_BLOCK_SIZE) {
202 let block: &mut [u8; 8] = chunk.try_into().unwrap();
203 self.cipher.decrypt_block(block.into());
204 }
205
206 Ok(())
207 }
208}
209
210impl std::fmt::Debug for DesEncryptor {
211 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212 f.debug_struct("DesEncryptor").field("cipher", &"[...]").finish()
213 }
214}
215
216pub fn encrypt_des(data: &[u8], key: &[u8]) -> Result<Vec<u8>> {
225 let encryptor = DesEncryptor::try_new(key)?;
226 encryptor.encrypt(data)
227}
228
229pub fn decrypt_des(data: &[u8], key: &[u8]) -> Result<Vec<u8>> {
238 let encryptor = DesEncryptor::try_new(key)?;
239 encryptor.decrypt(data)
240}
241
242#[cfg(test)]
243mod tests {
244 use super::*;
245
246 #[test]
247 fn test_encrypt_decrypt_roundtrip() {
248 let key = b"12345678";
249 let plaintext = b"Hello, World!";
250
251 let encrypted = encrypt_des(plaintext, key).unwrap();
252 assert_eq!(encrypted.len(), 16); let decrypted = decrypt_des(&encrypted, key).unwrap();
255 assert_eq!(&decrypted[..plaintext.len()], plaintext);
256 }
257
258 #[test]
259 fn test_encrypt_exact_block_size() {
260 let key = b"12345678";
261 let plaintext = b"12345678"; let encrypted = encrypt_des(plaintext, key).unwrap();
264 assert_eq!(encrypted.len(), 8);
265
266 let decrypted = decrypt_des(&encrypted, key).unwrap();
267 assert_eq!(&decrypted[..], plaintext);
268 }
269
270 #[test]
271 fn test_encrypt_multiple_blocks() {
272 let key = b"testkey!";
273 let plaintext = b"This is a longer message that spans multiple DES blocks.";
274
275 let encrypted = encrypt_des(plaintext, key).unwrap();
276 assert_eq!(encrypted.len() % 8, 0);
277
278 let decrypted = decrypt_des(&encrypted, key).unwrap();
279 assert_eq!(&decrypted[..plaintext.len()], plaintext);
280 }
281
282 #[test]
283 fn test_encrypt_empty() {
284 let key = b"12345678";
285 let plaintext = b"";
286
287 let encrypted = encrypt_des(plaintext, key).unwrap();
288 assert_eq!(encrypted.len(), 8); let decrypted = decrypt_des(&encrypted, key).unwrap();
291 assert!(decrypted.iter().all(|&b| b == 0));
293 }
294
295 #[test]
296 fn test_invalid_key_length() {
297 let key = b"short";
298 let result = encrypt_des(b"test", key);
299 assert!(result.is_err());
300 }
301
302 #[test]
303 fn test_invalid_decrypt_length() {
304 let key = b"12345678";
305 let invalid_data = vec![1, 2, 3, 4, 5]; let result = decrypt_des(&invalid_data, key);
307 assert!(result.is_err());
308 }
309
310 #[test]
311 fn test_encryptor_reuse() {
312 let key = b"mykey123";
313 let encryptor = DesEncryptor::new(key);
314
315 let data1 = b"First message";
316 let data2 = b"Second message";
317
318 let enc1 = encryptor.encrypt(data1).unwrap();
319 let enc2 = encryptor.encrypt(data2).unwrap();
320
321 let dec1 = encryptor.decrypt(&enc1).unwrap();
322 let dec2 = encryptor.decrypt(&enc2).unwrap();
323
324 assert_eq!(&dec1[..data1.len()], data1);
325 assert_eq!(&dec2[..data2.len()], data2);
326 }
327
328 #[test]
329 fn test_in_place_encryption() {
330 let key = b"12345678";
331 let encryptor = DesEncryptor::new(key);
332
333 let mut data = b"Hello, World!".to_vec();
334 let original_len = data.len();
335
336 encryptor.encrypt_in_place(&mut data, 0).unwrap();
337 assert_eq!(data.len() % 8, 0);
338
339 encryptor.decrypt_in_place(&mut data, 0).unwrap();
340 assert_eq!(&data[..original_len], b"Hello, World!");
341 }
342
343 #[test]
344 fn test_in_place_with_offset() {
345 let key = b"12345678";
346 let encryptor = DesEncryptor::new(key);
347
348 let mut data = vec![0x01, 0x02, 0x03, 0x04]; data.extend_from_slice(b"Body data here"); let header = data[..4].to_vec();
353
354 encryptor.encrypt_in_place(&mut data, 4).unwrap();
355 assert_eq!(&data[..4], &header[..]); encryptor.decrypt_in_place(&mut data, 4).unwrap();
358 assert_eq!(&data[4..4 + 14], b"Body data here");
359 }
360}