1use bytes::Bytes;
2use std::io;
3
4pub mod bytes;
5
6#[derive(Clone, Debug)]
8struct XteaKey(Vec<u32>);
9
10impl std::ops::Index<usize> for XteaKey {
11 type Output = u32;
12
13 fn index(&self, index: usize) -> &Self::Output {
14 &self.0[index]
15 }
16}
17
18#[derive(Debug)]
22pub struct Xtea {
23 key: XteaKey,
24 rounds: u32,
25}
26
27impl Xtea {
28 const DEFAULT_ROUNDS: u32 = 32;
30
31 const DELTA: u32 = 0x9E3779B9;
32
33 pub fn using_key(key: [u32; 4]) -> Self {
35 assert!(key.len() == 4);
36 Self {
37 key: XteaKey(key.to_vec()),
38 rounds: Self::DEFAULT_ROUNDS,
39 }
40 }
41
42 pub fn with_rounds(mut self, rounds: u32) -> Self {
45 self.rounds = rounds;
46 self
47 }
48
49 pub fn encipher(&self, mut input: &mut [u8], mut output: &mut [u8]) -> io::Result<()> {
51 self.do_block_cipher(&mut input, &mut output, false)
52 }
53
54 pub fn decipher(&self, input: &mut [u8], output: &mut [u8]) -> io::Result<()> {
56 self.do_block_cipher(input, output, true)
57 }
58
59 fn encipher_block(&self, input: &[u32; 2], output: &mut [u32; 2]) {
60 let mut v0 = input[0];
61 let mut v1 = input[1];
62 let mut sum = 0u32;
63
64
65 for _ in 0..self.rounds {
66 v0 = v0.wrapping_add(((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1))
67 ^ (sum.wrapping_add(self.key[(sum & 3) as usize]));
68 sum = sum.wrapping_add(Self::DELTA);
69 v1 = v1.wrapping_add(
70 (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0))
71 ^ (sum.wrapping_add(self.key[((sum >> 11) & 3) as usize])),
72 );
73 }
74
75 output[0] = v0;
76 output[1] = v1;
77 }
78
79 fn decipher_block(&self, input: &[u32; 2], output: &mut [u32; 2]) {
80 let mut v0 = input[0];
81 let mut v1 = input[1];
82 let mut sum = Self::DELTA.wrapping_mul(self.rounds);
83
84 for _ in 0..self.rounds {
85 v1 = v1.wrapping_sub(
86 (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0))
87 ^ (sum.wrapping_add(self.key[((sum >> 11) & 3) as usize])),
88 );
89 sum = sum.wrapping_sub(Self::DELTA);
90 v0 = v0.wrapping_sub(
91 (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1))
92 ^ (sum.wrapping_add(self.key[(sum & 3) as usize])),
93 );
94 }
95
96 output[0] = v0;
97 output[1] = v1;
98 }
99
100 fn do_block_cipher(&self, input: &mut [u8], output: &mut [u8], decrypt: bool) -> io::Result<()> {
101 let mut input_buffer = Bytes::new(input.to_vec());
102 let mut output_buffer = Bytes::new(output.to_vec());
103 let mut input_slice = [0_u32; 2];
104 let mut output_slice = [0_u32; 2];
105 let iterations = input_buffer.readable() / 8;
106
107 for _ in 0..iterations {
108 input_slice[0] = input_buffer.get_u32()?;
109 input_slice[1] = input_buffer.get_u32()?;
110
111 if decrypt {
112 self.decipher_block(&input_slice, &mut output_slice);
113 } else {
114 self.encipher_block(&input_slice, &mut output_slice);
115 }
116
117 output_buffer.put_u32(output_slice[0]);
118 output_buffer.put_u32(output_slice[1]);
119 }
120 Ok(())
121 }
122}