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}