1use crate::BlockCipher;
27
28const IP: [u8; 64] = [
34 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32,
35 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47,
36 39, 31, 23, 15, 7,
37];
38
39const FP: [u8; 64] = [
41 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21,
42 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9,
43 49, 17, 57, 25,
44];
45
46const E_PERM: [u8; 48] = [
48 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20, 21,
49 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1,
50];
51
52const P_PERM: [u8; 32] = [
54 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4,
55 25,
56];
57
58const PC1: [u8; 56] = [
60 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 63, 55,
61 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4,
62];
63
64const PC2: [u8; 48] = [
66 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30,
67 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32,
68];
69
70const KEY_SHIFTS: [u8; 16] = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
72
73const SBOXES: [[u8; 64]; 8] = [
75 [
77 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 4,
78 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
79 ],
80 [
82 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 0,
83 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
84 ],
85 [
87 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 13,
88 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
89 ],
90 [
92 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 10,
93 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
94 ],
95 [
97 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 4,
98 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
99 ],
100 [
102 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 9,
103 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
104 ],
105 [
107 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 1,
108 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
109 ],
110 [
112 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 7,
113 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,
114 ],
115];
116
117#[inline]
123fn bytes_to_u64(b: &[u8]) -> u64 {
124 ((b[0] as u64) << 56)
125 | ((b[1] as u64) << 48)
126 | ((b[2] as u64) << 40)
127 | ((b[3] as u64) << 32)
128 | ((b[4] as u64) << 24)
129 | ((b[5] as u64) << 16)
130 | ((b[6] as u64) << 8)
131 | (b[7] as u64)
132}
133
134#[inline]
136fn u64_to_bytes(v: u64) -> [u8; 8] {
137 v.to_be_bytes()
138}
139
140#[inline]
142fn get_bit64(val: u64, pos: u8) -> u64 {
143 (val >> (64 - pos as u32)) & 1
144}
145
146fn permute64(input: u64, table: &[u8]) -> u64 {
151 let mut output: u64 = 0;
152 for (i, &pos) in table.iter().enumerate() {
153 let bit = get_bit64(input, pos);
154 output |= bit << (63 - i as u32);
155 }
156 output
157}
158
159pub struct Des {
165 subkeys: [u64; 16],
168}
169
170impl Des {
171 fn generate_subkeys(key: u64) -> [u64; 16] {
173 let pc1 = permute64(key, &PC1);
175
176 let mut c: u32 = (pc1 >> 36) as u32; let mut d: u32 = ((pc1 >> 8) as u32) & 0x0FFFFFFF; let mut subkeys = [0u64; 16];
181
182 for round in 0..16 {
183 let shift = KEY_SHIFTS[round] as u32;
184 c = ((c << shift) | (c >> (28 - shift))) & 0x0FFFFFFF;
186 d = ((d << shift) | (d >> (28 - shift))) & 0x0FFFFFFF;
187
188 let cd: u64 = ((c as u64) << 36) | ((d as u64) << 8);
190
191 subkeys[round] = permute64(cd, &PC2);
193 }
194
195 subkeys
196 }
197
198 fn feistel(r: u32, subkey: u64) -> u32 {
203 let r64 = (r as u64) << 32;
206 let expanded = permute64(r64, &E_PERM); let xored = expanded ^ subkey;
210
211 let mut sbox_result: u32 = 0;
213 for i in 0..8 {
214 let shift = 58 - (i * 6); let six_bits = ((xored >> shift) & 0x3F) as u8;
218
219 let row = ((six_bits & 0x20) >> 4) | (six_bits & 0x01); let col = (six_bits >> 1) & 0x0F;
222 let val = SBOXES[i as usize][(row as usize) * 16 + (col as usize)];
223
224 sbox_result |= (val as u32) << (28 - i * 4);
226 }
227
228 let sbox64 = (sbox_result as u64) << 32;
230 let p_out = permute64(sbox64, &P_PERM);
231 (p_out >> 32) as u32
232 }
233
234 fn des_cipher(&self, input: u64, decrypt: bool) -> u64 {
236 let permuted = permute64(input, &IP);
238
239 let mut l: u32 = (permuted >> 32) as u32;
240 let mut r: u32 = permuted as u32;
241
242 for round in 0..16 {
244 let subkey_idx = if decrypt { 15 - round } else { round };
245 let f_out = Self::feistel(r, self.subkeys[subkey_idx]);
246
247 let new_r = l ^ f_out;
248 l = r;
249 r = new_r;
250 }
251
252 let pre_fp: u64 = ((r as u64) << 32) | (l as u64);
254 permute64(pre_fp, &FP)
255 }
256}
257
258impl BlockCipher for Des {
259 const BLOCK_LEN: usize = 8;
260 const KEY_LENS: &'static [usize] = &[8]; fn new(key: &[u8]) -> Self {
263 assert_eq!(key.len(), 8, "DES requires an 8-byte key");
264 Des {
265 subkeys: Self::generate_subkeys(bytes_to_u64(key)),
266 }
267 }
268
269 fn encrypt_block(&self, block: &mut [u8]) {
270 assert!(block.len() >= 8, "DES: block must be at least 8 bytes");
271 let input = bytes_to_u64(&block[..8]);
272 let output = self.des_cipher(input, false);
273 block[..8].copy_from_slice(&u64_to_bytes(output));
274 }
275
276 fn decrypt_block(&self, block: &mut [u8]) {
277 assert!(block.len() >= 8, "DES: block must be at least 8 bytes");
278 let input = bytes_to_u64(&block[..8]);
279 let output = self.des_cipher(input, true);
280 block[..8].copy_from_slice(&u64_to_bytes(output));
281 }
282}
283
284pub struct TripleDes {
293 k1: Des,
294 k2: Des,
295 k3: Des,
296}
297
298impl BlockCipher for TripleDes {
299 const BLOCK_LEN: usize = 8;
300 const KEY_LENS: &'static [usize] = &[24]; fn new(key: &[u8]) -> Self {
303 assert_eq!(key.len(), 24, "3DES requires a 24-byte key (3 x 8)");
304 TripleDes {
305 k1: Des::new(&key[0..8]),
306 k2: Des::new(&key[8..16]),
307 k3: Des::new(&key[16..24]),
308 }
309 }
310
311 fn encrypt_block(&self, block: &mut [u8]) {
312 self.k1.encrypt_block(block);
313 self.k2.decrypt_block(block);
314 self.k3.encrypt_block(block);
315 }
316
317 fn decrypt_block(&self, block: &mut [u8]) {
318 self.k3.decrypt_block(block);
319 self.k2.encrypt_block(block);
320 self.k1.decrypt_block(block);
321 }
322}
323
324#[cfg(test)]
329mod tests {
330 use super::*;
331
332 fn hex_to_bytes(s: &str) -> Vec<u8> {
333 (0..s.len())
334 .step_by(2)
335 .map(|i| u8::from_str_radix(&s[i..i + 2], 16).unwrap())
336 .collect()
337 }
338
339 #[test]
341 fn des_known_answer_tests() {
342 let k1 = Des::new(&hex_to_bytes("133457799BBCDFF1"));
344 let mut b1 = hex_to_bytes("0123456789ABCDEF");
345 k1.encrypt_block(&mut b1);
346 assert_eq!(b1, hex_to_bytes("85E813540F0AB405").as_slice());
347 k1.decrypt_block(&mut b1);
348 assert_eq!(b1, hex_to_bytes("0123456789ABCDEF").as_slice());
349
350 let k2 = Des::new(&hex_to_bytes("FEDCBA9876543210"));
352 let mut b2 = hex_to_bytes("0123456789ABCDEF");
353 k2.encrypt_block(&mut b2);
354 assert_eq!(b2, hex_to_bytes("ED39D950FA74BCC4").as_slice());
355 k2.decrypt_block(&mut b2);
356 assert_eq!(b2, hex_to_bytes("0123456789ABCDEF").as_slice());
357
358 let k3 = Des::new(&hex_to_bytes("0123456789ABCDEF"));
360 let mut b3 = [0u8; 8];
361 k3.encrypt_block(&mut b3);
362 assert_eq!(b3.to_vec(), hex_to_bytes("D5D44FF720683D0D"));
363
364 let mut b4 = hex_to_bytes("0123456789ABCDEF");
366 k3.encrypt_block(&mut b4);
367 assert_eq!(b4, hex_to_bytes("56CC09E7CFDC4CEF").as_slice());
368 }
369
370 #[test]
372 fn des_round_trip() {
373 let cipher = Des::new(&hex_to_bytes("0123456789ABCDEF"));
374 for pt_hex in &[
375 "0000000000000000",
376 "FFFFFFFFFFFFFFFF",
377 "4E6F772069732074",
378 "0123456789ABCDEF",
379 ] {
380 let pt = hex_to_bytes(pt_hex);
381 let mut block = pt.clone();
382 cipher.encrypt_block(&mut block);
383 assert_ne!(block, pt.as_slice(), "CT should differ from PT for {}", pt_hex);
384 cipher.decrypt_block(&mut block);
385 assert_eq!(block, pt.as_slice(), "round-trip failed for PT={}", pt_hex);
386 }
387 }
388
389 #[test]
391 fn triple_des_round_trip() {
392 let key = hex_to_bytes("0123456789ABCDEF23456789ABCDEF01456789ABCDEF0123");
393 let plaintext = hex_to_bytes("4E6F772069732074");
394
395 let cipher = TripleDes::new(&key);
396
397 let mut block = plaintext.clone();
398 cipher.encrypt_block(&mut block);
399 assert_ne!(block, plaintext.as_slice());
400
401 cipher.decrypt_block(&mut block);
402 assert_eq!(block, plaintext.as_slice());
403 }
404
405 #[test]
407 fn triple_des_ede_consistency() {
408 let key = hex_to_bytes("0123456789ABCDEF23456789ABCDEF01456789ABCDEF0123");
409 let plaintext = hex_to_bytes("4E6F772069732074");
410 let cipher = TripleDes::new(&key);
411
412 let mut block = plaintext.clone();
413 cipher.encrypt_block(&mut block);
414
415 let k1 = Des::new(&hex_to_bytes("0123456789ABCDEF"));
417 let k2 = Des::new(&hex_to_bytes("23456789ABCDEF01"));
418 let k3 = Des::new(&hex_to_bytes("456789ABCDEF0123"));
419
420 let mut manual = plaintext.clone();
421 k1.encrypt_block(&mut manual);
422 k2.decrypt_block(&mut manual);
423 k3.encrypt_block(&mut manual);
424
425 assert_eq!(block, manual.as_slice(), "3DES EDE mismatch");
426 }
427}