1use anyhow::{Result, bail, ensure};
6use std::convert::TryInto;
7
8pub struct Present {
13 round_keys: Vec<u64>,
14}
15
16impl Present {
17 pub fn try_new_rounds(key: Vec<u8>, rounds: usize) -> Result<Present> {
18 ensure!(
19 (1..=254).contains(&rounds),
20 "unsupported number of rounds {}",
21 rounds
22 );
23
24 let round_keys = match key.len() {
25 10 => generate_round_keys_80(key, rounds),
26 16 => generate_round_keys_128(key, rounds),
27 _ => bail!("key length must be 80 or 128 bits"),
28 };
29
30 Ok(Present { round_keys })
31 }
32
33 pub fn try_new(key: Vec<u8>) -> Result<Present> {
37 Self::try_new_rounds(key, 32)
38 }
39
40 pub fn new_128(key: &[u8; 16]) -> Present {
42 Self::try_new(key.to_vec()).unwrap()
43 }
44
45 pub fn new_80(key: &[u8; 10]) -> Present {
47 Self::try_new(key.to_vec()).unwrap()
48 }
49
50 pub fn encrypt_block(&self, block: u64) -> u64 {
52 let mut state = block;
53 state ^= self.round_keys[0];
54 for round_key in &self.round_keys[1..] {
55 state = s_box_layer(state);
56 state = p_box_layer(state);
57 state ^= round_key;
58 }
59 state
60 }
61
62 pub fn decrypt_block(&self, block: u64) -> u64 {
64 let mut state = block;
65 for round_key in self.round_keys[1..].iter().rev() {
66 state ^= round_key;
67 state = p_box_layer_dec(state);
68 state = s_box_layer_dec(state);
69 }
70 state ^ self.round_keys[0]
71 }
72}
73
74const S_BOX: [u8; 16] = [
75 0x0c, 0x05, 0x06, 0x0b, 0x09, 0x00, 0x0a, 0x0d, 0x03, 0x0e, 0x0f, 0x08, 0x04, 0x07, 0x01, 0x02,
76];
77
78const S_BOX_INV: [u8; 16] = [
79 0x05, 0x0e, 0x0f, 0x08, 0x0c, 0x01, 0x02, 0x0d, 0x0b, 0x04, 0x06, 0x03, 0x00, 0x07, 0x09, 0x0a,
80];
81
82const P_BOX: [u8; 64] = [
83 0x00, 0x10, 0x20, 0x30, 0x01, 0x11, 0x21, 0x31, 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33,
84 0x04, 0x14, 0x24, 0x34, 0x05, 0x15, 0x25, 0x35, 0x06, 0x16, 0x26, 0x36, 0x07, 0x17, 0x27, 0x37,
85 0x08, 0x18, 0x28, 0x38, 0x09, 0x19, 0x29, 0x39, 0x0a, 0x1a, 0x2a, 0x3a, 0x0b, 0x1b, 0x2b, 0x3b,
86 0x0c, 0x1c, 0x2c, 0x3c, 0x0d, 0x1d, 0x2d, 0x3d, 0x0e, 0x1e, 0x2e, 0x3e, 0x0f, 0x1f, 0x2f, 0x3f,
87];
88
89const P_BOX_INV: [u8; 64] = [
90 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c,
91 0x01, 0x05, 0x09, 0x0d, 0x11, 0x15, 0x19, 0x1d, 0x21, 0x25, 0x29, 0x2d, 0x31, 0x35, 0x39, 0x3d,
92 0x02, 0x06, 0x0a, 0x0e, 0x12, 0x16, 0x1a, 0x1e, 0x22, 0x26, 0x2a, 0x2e, 0x32, 0x36, 0x3a, 0x3e,
93 0x03, 0x07, 0x0b, 0x0f, 0x13, 0x17, 0x1b, 0x1f, 0x23, 0x27, 0x2b, 0x2f, 0x33, 0x37, 0x3b, 0x3f,
94];
95
96fn generate_round_keys_80(key: Vec<u8>, rounds: usize) -> Vec<u64> {
98 let mut orig_key = key;
100 let mut key = vec![0u8; 6];
101 key.append(&mut orig_key);
102
103 let key: &[u8; 16] = key.as_slice().try_into().unwrap();
105 let mut key = u128::from_le_bytes(*key);
106
107 let mut round_keys = Vec::new();
108 for i in 1..rounds + 1 {
109 let round_key = (key >> 16) as u64;
111
112 key = (key & 0x7ffff) << 61 | key >> 19;
115
116 key = (S_BOX[(key >> 76) as usize] as u128) << 76 | (key & !0u128 >> (128 - 76));
119
120 key ^= (i as u128) << 15;
123
124 round_keys.push(round_key);
125 }
126
127 round_keys
128}
129
130fn generate_round_keys_128(key: Vec<u8>, rounds: usize) -> Vec<u64> {
132 let mut round_keys = Vec::new();
133
134 let key: &[u8; 16] = key.as_slice().try_into().unwrap();
136 let mut key = u128::from_le_bytes(*key);
137 for i in 1..rounds + 1 {
138 let round_key = (key >> 64) as u64;
140
141 key = key.rotate_left(61);
143
144 key = (S_BOX[(key >> 124) as usize] as u128) << 124
146 | (S_BOX[((key >> 120) & 0xF) as usize] as u128) << 120
147 | (key & (!0u128 >> 8));
148
149 key ^= (i as u128) << 62;
152
153 round_keys.push(round_key);
154 }
155
156 round_keys
157}
158
159fn s_box_layer(state: u64) -> u64 {
161 let mut output: u64 = 0;
162 for i in (0..64).step_by(4) {
163 output |= (S_BOX[((state >> i) & 0x0f) as usize] as u64) << i;
164 }
165 output
166}
167
168fn s_box_layer_dec(state: u64) -> u64 {
170 let mut output: u64 = 0;
171 for i in (0..64).step_by(4) {
172 output |= (S_BOX_INV[((state >> i) & 0x0f) as usize] as u64) << i;
173 }
174 output
175}
176
177fn p_box_layer(state: u64) -> u64 {
179 let mut output: u64 = 0;
180 for (i, v) in P_BOX.iter().enumerate() {
181 output |= ((state >> i) & 0x01) << v;
182 }
183 output
184}
185
186fn p_box_layer_dec(state: u64) -> u64 {
188 let mut output: u64 = 0;
189 for (i, v) in P_BOX_INV.iter().enumerate() {
190 output |= ((state >> i) & 0x01) << v;
191 }
192 output
193}
194
195#[cfg(test)]
196mod test {
197 use super::*;
198
199 #[rustfmt::skip]
200 const ROUND_KEYS_80: [u64; 32] = [
201 0x0000000000000000, 0xc000000000000000, 0x5000180000000001, 0x60000a0003000001,
202 0xb0000c0001400062, 0x900016000180002a, 0x0001920002c00033, 0xa000a0003240005b,
203 0xd000d4001400064c, 0x30017a001a800284, 0xe01926002f400355, 0xf00a1c0324c005ed,
204 0x800d5e014380649e, 0x4017b001abc02876, 0x71926802f600357f, 0x10a1ce324d005ec7,
205 0x20d5e21439c649a8, 0xc17b041abc428730, 0xc926b82f60835781, 0x6a1cd924d705ec19,
206 0xbd5e0d439b249aea, 0x07b077abc1a8736e, 0x426ba0f60ef5783e, 0x41cda84d741ec1d5,
207 0xf5e0e839b509ae8f, 0x2b075ebc1d0736ad, 0x86ba2560ebd783ad, 0x8cdab0d744ac1d77,
208 0x1e0eb19b561ae89b, 0xd075c3c1d6336acd, 0x8ba27a0eb8783ac9, 0x6dab31744f41d700,
209 ];
210
211 #[rustfmt::skip]
212 const ROUND_KEYS_128: [u64; 32] = [
213 0x0000000000000000, 0xcc00000000000000, 0xc300000000000000, 0x5b30000000000000,
214 0x580c000000000001, 0x656cc00000000001, 0x6e60300000000001, 0xb595b30000000001,
215 0xbeb980c000000002, 0x96d656cc00000002, 0x9ffae60300000002, 0x065b595b30000002,
216 0x0f7feb980c000003, 0xac196d656cc00003, 0xa33dffae60300003, 0xd6b065b595b30003,
217 0xdf8cf7feb980c004, 0x3b5ac196d656cc04, 0x387e33dffae60304, 0xeced6b065b595b34,
218 0xe3e1f8cf7feb9809, 0x6bb3b5ac196d6569, 0xbb8f87e33dffae65, 0x80aeced6b065b590,
219 0xc1ee3e1f8cf7febf, 0x2602bb3b5ac196d0, 0xcb07b8f87e33dffc, 0x34980aeced6b065d,
220 0x8b2c1ee3e1f8cf78, 0x54d2602bb3b5ac1e, 0x4a2cb07b8f87e33a, 0x97534980aeced6b7,
221 ];
222
223 #[test]
224 fn test_generate_80() {
225 let key = vec![0u8; 10];
226 let round_keys = generate_round_keys_80(key, 32);
227 assert_eq!(round_keys, ROUND_KEYS_80);
228 }
229
230 #[test]
231 fn test_generate_128() {
232 let key = vec![0u8; 16];
233 let round_keys = generate_round_keys_128(key, 32);
234 assert_eq!(round_keys, ROUND_KEYS_128);
235 }
236
237 #[test]
238 fn test_enc_80() -> Result<()> {
239 let cipher = Present::try_new(vec![0; 10])?;
240 assert_eq!(cipher.encrypt_block(0), 0x5579c1387b228445);
241 Ok(())
242 }
243
244 #[test]
245 fn test_dec_80() -> Result<()> {
246 let cipher = Present::try_new(vec![0; 10])?;
247 assert_eq!(cipher.decrypt_block(0x5579c1387b228445), 0);
248 Ok(())
249 }
250
251 #[test]
252 fn test_enc_128() -> Result<()> {
253 let cipher = Present::try_new(vec![0; 16])?;
254 assert_eq!(cipher.encrypt_block(0), 0x96db702a2e6900af);
255 assert_eq!(cipher.encrypt_block(!0), 0x3c6019e5e5edd563);
256 let cipher = Present::try_new(vec![0xff; 16])?;
257 assert_eq!(cipher.encrypt_block(0), 0x13238c710272a5d8);
258 assert_eq!(cipher.encrypt_block(!0), 0x628d9fbd4218e5b4);
259 Ok(())
260 }
261
262 #[test]
263 fn test_dec_128() -> Result<()> {
264 let cipher = Present::try_new(vec![0; 16])?;
265 assert_eq!(cipher.decrypt_block(0x96db702a2e6900af), 0);
266 assert_eq!(cipher.decrypt_block(0x3c6019e5e5edd563), !0);
267 let cipher = Present::try_new(vec![0xff; 16])?;
268 assert_eq!(cipher.decrypt_block(0x13238c710272a5d8), 0);
269 assert_eq!(cipher.decrypt_block(0x628d9fbd4218e5b4), !0);
270 Ok(())
271 }
272}