1use crate::word::Word;
67
68pub fn rotl<W: Word>(x: W, y: W) -> W {
69 let w = W::BYTES * 8;
70 let a = y & W::from_usize(w - 1);
71 if a == W::ZERO {
72 x
73 } else {
74 (x << a) | (x >> (W::from_usize(w) - a))
75 }
76}
77
78pub fn rotr<W: Word>(x: W, y: W) -> W {
79 let w = W::BYTES * 8;
80 let a = y & W::from_usize(w - 1);
81 if a == W::ZERO {
82 x
83 } else {
84 (x >> a) | (x << (W::from_usize(w) - a))
85 }
86}
87
88pub fn encrypt<W: Word>(pt: [W; 2], key: &Vec<u8>, rounds: usize) -> [W; 2] {
107 let key_exp = expand_key::<W>(key, rounds);
108 let mut a = pt[0].wrapping_add(&key_exp[0]);
109 let mut b = pt[1].wrapping_add(&key_exp[1]);
110 for i in 1..=rounds {
111 a = rotl(a ^ b, b).wrapping_add(&key_exp[2 * i]);
112 b = rotl(b ^ a, a).wrapping_add(&key_exp[2 * i + 1]);
113 }
114 [a, b]
115}
116
117#[allow(arithmetic_overflow)]
136pub fn decrypt<W: Word>(ct: [W; 2], key: &Vec<u8>, rounds: usize) -> [W; 2] {
137 let key_exp = expand_key::<W>(key, rounds);
138 let mut a = ct[0];
139 let mut b = ct[1];
140 for i in (1..=rounds).rev() {
141 b = rotr(b.wrapping_sub(&key_exp[2 * i + 1]), a) ^ a;
142 a = rotr(a.wrapping_sub(&key_exp[2 * i]), b) ^ b;
143 }
144 [a.wrapping_sub(&key_exp[0]), b.wrapping_sub(&key_exp[1])]
145}
146
147#[allow(arithmetic_overflow)]
170pub fn expand_key<W: Word>(key: &Vec<u8>, rounds: usize) -> Vec<W> {
171 let t = 2 * (rounds + 1);
172 let b = key.len();
173 let w = W::BYTES * 8;
174
175 let c = std::cmp::max(1, (8 * b + w - 1) / w);
177
178 let mut key_l: Vec<W> = vec![W::ZERO; c];
180 let u = W::BYTES;
181 for i in (0..b).rev() {
182 let ix = i / u;
183 key_l[ix] = (key_l[ix].wrapping_shl(8u32)).wrapping_add(&W::from_u8(key[i]));
184 }
185
186 let mut key_s = vec![W::ZERO; t];
188 key_s[0] = W::P;
189 for i in 1..t {
190 key_s[i] = key_s[i - 1].wrapping_add(&W::Q);
191 }
192
193 let mut i = 0;
195 let mut j = 0;
196 let mut a = W::ZERO;
197 let mut b = W::ZERO;
198 for _k in 0..3 * std::cmp::max(c, t) {
199 key_s[i] = rotl(key_s[i].wrapping_add(&a.wrapping_add(&b)), W::from_usize(3));
200 a = key_s[i];
201 key_l[j] = rotl(
202 key_l[j].wrapping_add(&a.wrapping_add(&b)),
203 a.wrapping_add(&b),
204 );
205 b = key_l[j];
206 i = (i + 1) % t;
207 j = (j + 1) % c;
208 }
209 key_s
210}
211
212#[cfg(test)]
213mod tests {
214 use super::*;
215
216 #[test]
217 fn test_left_right_shift() {
218 let a = 0x77u8; assert_eq!(rotl(a, 1u8), 0xeeu8);
221 assert_eq!(rotl(a, 7u8), 0xbbu8); assert_eq!(rotl(a, 8u8), a);
223 assert_eq!(rotl(a, 2 * 8u8), a);
224 assert_eq!(rotl(a, 5 * 8u8), a);
225 assert_eq!(rotl(a, 1u8), 0xeeu8); assert_eq!(rotl(a, 7u8), 0xbbu8); assert_eq!(rotr(a, 8u8), a);
228
229 assert_eq!(rotr(a, 1u8), 0xbbu8); assert_eq!(rotr(a, 2u8), 0xddu8); assert_eq!(rotr(a, 7u8), 0xeeu8); assert_eq!(rotr(a, 8u8), a);
233 assert_eq!(rotr(a, 8u8 + 1u8), 0xbbu8);
234 assert_eq!(rotr(a, 8u8 + 2u8), 0xddu8);
235 assert_eq!(rotr(a, 8u8 + 7u8), 0xeeu8);
236 assert_eq!(rotr(a, 2 * 8u8), a);
237 assert_eq!(rotr(a, 5 * 8u8), a);
238 }
239
240 #[test]
241 fn test_rivest_1() {
242 let key = vec![
243 0x00u8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x00, 0x00,
245 ];
246 let pt = [0x00000000u32, 0x00000000];
247 let rounds = 12;
248
249 let ct = encrypt(pt, &key, rounds);
250 assert_eq!(ct, [0xEEDBA521u32, 0x6D8F4B15]);
251
252 let pt = decrypt(ct, &key, rounds);
253 assert_eq!(pt, [0x00000000u32, 0x00000000]);
254 }
255
256 #[test]
257 fn test_rivest_2() {
258 let key = vec![
259 0x91, 0x5F, 0x46, 0x19, 0xBE, 0x41, 0xB2, 0x51, 0x63, 0x55, 0xA5, 0x01, 0x10, 0xA9,
260 0xCE, 0x91,
261 ];
262 let pt = [0xEEDBA521u32, 0x6D8F4B15];
263 let rounds = 12;
264
265 let ct = encrypt(pt, &key, rounds);
266 assert_eq!(ct, [0xAC13C0F7u32, 0x52892B5B]);
267
268 let pt = decrypt(ct, &key, rounds);
269 assert_eq!(pt, [0xEEDBA521u32, 0x6D8F4B15]);
270 }
271
272 #[test]
273 fn test_rivest_3() {
274 let key = vec![
275 0x78, 0x33, 0x48, 0xE7, 0x5A, 0xEB, 0x0F, 0x2F, 0xD7, 0xB1, 0x69, 0xBB, 0x8D, 0xC1,
276 0x67, 0x87,
277 ];
278 let pt = [0xAC13C0F7u32, 0x52892B5B];
279 let rounds = 12;
280
281 let ct = encrypt(pt, &key, rounds);
282 assert_eq!(ct, [0xB7B3422Fu32, 0x92FC6903]);
283
284 let pt = decrypt(ct, &key, rounds);
285 assert_eq!(pt, [0xAC13C0F7u32, 0x52892B5B]);
286 }
287
288 #[test]
289 fn test_rivest_4() {
290 let key = vec![
291 0xDC, 0x49, 0xDB, 0x13, 0x75, 0xA5, 0x58, 0x4F, 0x64, 0x85, 0xB4, 0x13, 0xB5, 0xF1,
292 0x2B, 0xAF,
293 ];
294 let pt = [0xB7B3422Fu32, 0x92FC6903];
295 let rounds = 12;
296
297 let ct = encrypt(pt, &key, rounds);
298 assert_eq!(ct, [0xB278C165u32, 0xCC97D184]);
299
300 let pt = decrypt(ct, &key, rounds);
301 assert_eq!(pt, [0xB7B3422Fu32, 0x92FC6903]);
302 }
303
304 #[test]
305 fn test_rivest_5() {
306 let key = vec![
307 0x52, 0x69, 0xF1, 0x49, 0xD4, 0x1B, 0xA0, 0x15, 0x24, 0x97, 0x57, 0x4D, 0x7F, 0x15,
308 0x31, 0x25,
309 ];
310 let pt = [0xB278C165u32, 0xCC97D184];
311 let rounds = 12;
312
313 let ct = encrypt(pt, &key, rounds);
314 assert_eq!(ct, [0x15E444EBu32, 0x249831DA]);
315
316 let pt = decrypt(ct, &key, rounds);
317 assert_eq!(pt, [0xB278C165u32, 0xCC97D184]);
318 }
319
320 #[test]
321 fn encrypt_decrypt_a() {
322 let rounds = 12;
323 let key = vec![
324 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
325 0x0E, 0x0F,
326 ];
327 let pt = [0x33221100u32, 0x77665544];
328
329 let ct = encrypt(pt, &key, rounds);
330
331 assert_eq!(ct, [0x9B14DC2Du32, 0x9E8B08CF]);
332
333 let pt = decrypt(ct, &key, rounds);
334
335 assert_eq!(pt, [0x33221100u32, 0x77665544]);
336 }
337
338 #[test]
339 fn encrypt_decrypt_b() {
340 let rounds = 12;
341 let key = vec![
342 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81,
343 0xFF, 0x48,
344 ];
345 let pt = [0x144702EAu32, 0x844D5CAD];
346
347 let ct = encrypt(pt, &key, rounds);
348
349 assert_eq!(ct, [0x863BE411u32, 0x64EA31D2]);
350
351 let pt = decrypt(ct, &key, rounds);
352
353 assert_eq!(pt, [0x144702EAu32, 0x844D5CAD]);
354 }
355
356 #[test]
359 fn encrypt_decrypt_8_12_4() {
360 let rounds = 12;
361 let key = vec![0x00, 0x01, 0x02, 0x03];
362
363 let pt = [0x00u8, 0x01];
364
365 let ct = encrypt(pt, &key, rounds);
366
367 assert_eq!(ct, [0x21u8, 0x2A]);
368
369 let pt = decrypt(ct, &key, rounds);
370
371 assert_eq!(pt, [0x00u8, 0x01]);
372 }
373
374 #[test]
375 fn encrypt_16_16_8() {
376 let rounds = 16;
377 let key = vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
378
379 let pt = [0x0100u16, 0x0302];
380
381 let ct = encrypt(pt, &key, rounds);
382
383 assert_eq!(ct, [0xA823, 0x2ED7]);
384
385 let pt = decrypt(ct, &key, rounds);
386
387 assert_eq!(pt, [0x0100u16, 0x0302]);
388 }
389
390 #[test]
391 fn encrypt_decrypt_32_20_16() {
392 let rounds = 20;
393 let key = vec![
394 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
395 0x0E, 0x0F,
396 ];
397 let pt = [0x03020100u32, 0x07060504];
398
399 let ct = encrypt(pt, &key, rounds);
400
401 assert_eq!(ct, [0x0EDC0E2Au32, 0x73FF3194]);
402
403 let pt = decrypt(ct, &key, rounds);
404
405 assert_eq!(pt, [0x03020100u32, 0x07060504]);
406 }
407
408 #[test]
409 fn encrypt_64_24_24() {
410 let rounds = 24;
411 let key = vec![
412 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
413 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
414 ];
415 let pt = [0x0706050403020100u64, 0x0F0E0D0C0B0A0908];
416
417 let ct = encrypt(pt, &key, rounds);
418
419 assert_eq!(ct, [0x02CEDB0E827267A4u64, 0xDA7871AE32EAAB35]);
420
421 let pt = decrypt(ct, &key, rounds);
422
423 assert_eq!(pt, [0x0706050403020100u64, 0x0F0E0D0C0B0A0908]);
424 }
425
426 #[test]
427 fn encrypt_kernel_128_28_32() {
428 let rounds = 28;
429 let key = vec![
430 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
431 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
432 0x1C, 0x1D, 0x1E, 0x1F,
433 ];
434 let pt = [
435 0x0F0E0D0C0B0A09080706050403020100u128,
436 0x1F1E1D1C1B1A19181716151413121110,
437 ];
438
439 let ct = encrypt(pt, &key, rounds);
440
441 assert_eq!(
442 ct,
443 [
444 0xBAFCA120ADD77ADDCFF4A4210991A5ECu128,
445 0x40B480E17F4B91FE682D75CDA7C78E06
446 ]
447 );
448
449 let pt = decrypt(ct, &key, rounds);
450
451 assert_eq!(
452 pt,
453 [
454 0x0F0E0D0C0B0A09080706050403020100u128,
455 0x1F1E1D1C1B1A19181716151413121110,
456 ]
457 );
458 }
459}