leekoq/lib.rs
1//!
2//!
3
4#![no_std]
5
6pub struct LeeKoq;
7
8impl LeeKoq {
9 // 1-bit lookup table for the NLF
10 pub const LUT: u32 = 0x3A5C742E;
11
12 /// Encrypts a 32-bit block of plaintext using the KeeLoq algorithm.
13 ///
14 /// # Arguments
15 ///
16 /// * `block` - 32-bit plaintext block
17 /// * `key` - 64-bit key
18 /// * `return` - 32-bit cipher-text block
19 ///
20 /// # Example
21 ///
22 /// ```rust,run
23 /// use leekoq::LeeKoq;
24 ///
25 /// let plain: u32 = 0x12345678;
26 /// let key: u64 = 0xCAFED00D;
27 /// assert_eq!(LeeKoq::encrypt(plain, key), 0xD0FB287C);
28 /// ```
29 ///
30 pub fn encrypt(mut block: u32, mut key: u64) -> u32 {
31 for _ in 0..528 {
32 // Calculate LUT key
33 let lutkey = (block >> 1) & 1 | (block >> 8) & 2 | (block >> 18) & 4 | (block >> 23) & 8 | (block >> 27) & 16;
34
35 // Calculate next bit to feed
36 let msb = (block >> 16 & 1) ^ (block & 1) ^ (Self::LUT >> lutkey & 1) ^ ((key & 1) as u32);
37
38 // Feed it
39 block = msb << 31 | block >> 1;
40
41 // Rotate key right
42 key = (key & 1) << 63 | key >> 1;
43 }
44
45 block
46 }
47
48 /// Decrypts a 32-bit block of ciphertext using the KeeLoq algorithm.
49 ///
50 /// # Arguments
51 ///
52 /// * `block` - 32-bit plaintext block
53 /// * `key` - 64-bit key
54 /// * `return` - 32-bit cipher-text block
55 ///
56 /// # Example
57 ///
58 /// ```rust,run
59 /// use leekoq::LeeKoq;
60 ///
61 /// let cipher: u32 = 0xD0FB287C;
62 /// let key: u64 = 0xCAFED00D;
63 /// assert_eq!(LeeKoq::decrypt(cipher, key), 0x12345678);
64 /// ```
65 ///
66 pub fn decrypt(mut block: u32, mut key: u64) -> u32 {
67 for _ in 0..528 {
68 // Calculate LUT key
69 let lutkey = (block >> 0) & 1 | (block >> 7) & 2 | (block >> 17) & 4 | (block >> 22) & 8 | (block >> 26) & 16;
70
71 // Calculate next bit to feed
72 let lsb = (block >> 31) ^ (block >> 15 & 1) ^ (Self::LUT >> lutkey & 1) ^ ((key >> 15 & 1) as u32);
73
74 // Feed it
75 block = (block & 0x7FFFFFFF) << 1 | lsb;
76
77 // Rotate key left
78 key = (key & 0x7FFFFFFFFFFFFFFF) << 1 | key >> 63;
79 }
80
81 block
82 }
83
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn encrypt() {
92 assert_eq!(LeeKoq::encrypt(0xf741e2db, 0x5cec6701b79fd949), 0xe44f4cdf);
93 assert_eq!(LeeKoq::encrypt(0x0ca69b92, 0x5cec6701b79fd949), 0xa6ac0ea2);
94 assert_eq!(LeeKoq::encrypt(0x12345678, 0xCAFED00D), 0xD0FB287C);
95 }
96
97 #[test]
98 fn decrypt() {
99 assert_eq!(LeeKoq::decrypt(0xe44f4cdf, 0x5cec6701b79fd949), 0xf741e2db);
100 assert_eq!(LeeKoq::decrypt(0xa6ac0ea2, 0x5cec6701b79fd949), 0x0ca69b92);
101 assert_eq!(LeeKoq::decrypt(0xD0FB287C, 0xCAFED00D), 0x12345678);
102 }
103}