Skip to main content

fast_des/
lib.rs

1use bitsliced_op::{ALL_ONES, transpose_64x64};
2use wide::u64x8;
3
4use crate::{
5    des::{compute_pc1, create_subkeys, encrypt},
6    des_optimized::{compute_pc1_optimized, create_subkeys_optimized, encrypt_optimized},
7};
8
9pub mod benchmark;
10mod constants;
11pub mod des;
12pub mod des_optimized;
13pub mod sbox_optimized;
14mod utils;
15
16pub const ZERO: u64x8 = u64x8::ZERO;
17
18pub fn des(plaintext: u64, key: u64) -> u64 {
19    let (c0, d0) = compute_pc1(key);
20    let subkeys = create_subkeys(c0, d0);
21    let encrypted = encrypt(plaintext, subkeys);
22    encrypted
23}
24
25pub fn bitsliced_des_simd(plaintext: u64, keys: &[[u64; 64]; 8]) -> [[u64; 64]; 8] {
26    let mut k_slice = transpose(keys);
27    let (mut c0, mut d0) = compute_pc1_optimized(&mut k_slice);
28    let subkeys = create_subkeys_optimized(&mut c0, &mut d0);
29
30    encrypt_optimized(plaintext, subkeys, &mut k_slice);
31    let ciphertext = transpose_back(&k_slice);
32    ciphertext
33}
34
35//inline expects keys that are already transposed
36pub fn bitsliced_des_inline_simd(plaintext: u64, keys: &mut [u64x8; 64]) {
37    let (mut c0, mut d0) = compute_pc1_optimized(keys);
38    let subkeys = create_subkeys_optimized(&mut c0, &mut d0);
39
40    encrypt_optimized(plaintext, subkeys, keys);
41}
42
43//expects plaintexts of 56bits, 8 MSB of all u64's are ignored
44pub fn bitsliced_netntlmv1_simd(plaintext: u64, keys: &[[u64; 64]; 8]) -> [[u64; 64]; 8] {
45    let transposed = transpose(keys);
46    let mut keys = convert_to_key(&transposed);
47    bitsliced_des_inline_simd(plaintext, &mut keys);
48    let ciphertext = transpose_back(&keys);
49    ciphertext
50}
51
52//expects plaintexts of 56bits, 8 MSB of all u64's are ignored
53pub fn bitsliced_netntlmv1_inline_simd(plaintext: u64, keys: &mut [u64x8; 64]) {
54    convert_to_key_inline(keys);
55    bitsliced_des_inline_simd(plaintext, keys);
56}
57
58const DES_KEY_PERM: [i8; 64] = [
59    0, 1, 2, 3, 4, 5, 6, -1, 7, 8, 9, 10, 11, 12, 13, -1, 14, 15, 16, 17, 18, 19, 20, -1, 21, 22,
60    23, 24, 25, 26, 27, -1, 28, 29, 30, 31, 32, 33, 34, -1, 35, 36, 37, 38, 39, 40, 41, -1, 42, 43,
61    44, 45, 46, 47, 48, -1, 49, 50, 51, 52, 53, 54, 55, -1,
62];
63
64fn convert_to_key(plaintexts: &[u64x8; 64]) -> [u64x8; 64] {
65    let mut out = [ZERO; 64];
66    for i in 0..64 {
67        let src = DES_KEY_PERM[i];
68        if src >= 0 {
69            out[i] = plaintexts[(src as usize) + 8];
70        } else {
71            out[i] = ALL_ONES;
72        }
73    }
74    out
75}
76
77fn convert_to_key_inline(plaintexts: &mut [u64x8; 64]) {
78    let mut tmp = [ZERO; 56];
79    for i in 8..64 {
80        tmp[i - 8] = plaintexts[i];
81    }
82    for i in 0..64 {
83        let src = DES_KEY_PERM[i];
84        if src >= 0 {
85            plaintexts[i] = tmp[src as usize];
86        } else {
87            plaintexts[i] = ALL_ONES;
88        }
89    }
90}
91
92fn transpose(input: &[[u64; 64]; 8]) -> [u64x8; 64] {
93    let mut out: [u64x8; 64] = [u64x8::ZERO; 64];
94    for k in 0..8 {
95        let tmp = input[k];
96        let tmp = transpose_64x64(&tmp);
97
98        for r in 0..64 {
99            out[r].as_mut_array()[k] = tmp[r];
100        }
101    }
102    out
103}
104
105fn transpose_back(input: &[u64x8; 64]) -> [[u64; 64]; 8] {
106    let mut out = [[0u64; 64]; 8];
107
108    for j in 0..64 {
109        let tmp = input[j].as_array();
110        out[0][j] = tmp[0];
111        out[1][j] = tmp[1];
112        out[2][j] = tmp[2];
113        out[3][j] = tmp[3];
114        out[4][j] = tmp[4];
115        out[5][j] = tmp[5];
116        out[6][j] = tmp[6];
117        out[7][j] = tmp[7];
118    }
119    for k in 0..8 {
120        let tmp = out[k];
121        out[k] = transpose_64x64(&tmp);
122    }
123
124    out
125}
126
127#[cfg(test)]
128mod tests {
129    // Note this useful idiom: importing names from outer (for mod tests) scope.
130    use super::*;
131
132    #[test]
133    fn test_encrypt_works_correctly() {
134        //test data taken from https://page.math.tu-berlin.de/~kant/teaching/hess/krypto-ws2006/des.htm
135        let ciphertext = des(0x0123456789ABCDEF, 0x133457799BBCDFF1);
136        assert_eq!(ciphertext, 0x85E813540F0AB405);
137    }
138
139    #[test]
140    fn test_encrypt_optimized_works_correctly() {
141        //test data taken from https://page.math.tu-berlin.de/~kant/teaching/hess/krypto-ws2006/des.htm
142        let k = 0x133457799BBCDFF1u64;
143        let mut keys = [[k; 64]; 8];
144        let ciphertexts = bitsliced_des_simd(0x0123456789ABCDEF, &mut keys);
145        assert_eq!(ciphertexts[0][0], 0x85E813540F0AB405);
146        assert_eq!(ciphertexts[0][63], 0x85E813540F0AB405);
147    }
148
149    #[test]
150    fn test_encrypt_optimized_inline_works_correctly() {
151        //test data taken from https://page.math.tu-berlin.de/~kant/teaching/hess/krypto-ws2006/des.htm
152        let k = 0x133457799BBCDFF1u64;
153        let mut keys = [[k; 64]; 8];
154        let mut transposed = transpose(&keys);
155        bitsliced_des_inline_simd(0x0123456789ABCDEF, &mut transposed);
156        let ciphertexts = transpose_back(&transposed);
157        assert_eq!(ciphertexts[0][0], 0x85E813540F0AB405);
158        assert_eq!(ciphertexts[0][63], 0x85E813540F0AB405);
159    }
160
161    #[test]
162    fn test_netntlmv1_encrypt_works_correctly() {
163        let k = 0x8846F7EAEE8FB1u64;
164        let keys = [[k; 64]; 8];
165        let ciphertexts = bitsliced_netntlmv1_simd(0x1122334455667788, &keys);
166        assert_eq!(ciphertexts[0][0], 0x727B4E35F947129E);
167        assert_eq!(ciphertexts[0][63], 0x727B4E35F947129E);
168    }
169
170    #[test]
171    fn test_netntlmv1_inline_encrypt_works_correctly() {
172        let k = 0x8846F7EAEE8FB1u64;
173        let keys = [[k; 64]; 8];
174        let mut transposed = transpose(&keys);
175        bitsliced_netntlmv1_inline_simd(0x1122334455667788, &mut transposed);
176        let ciphertexts = transpose_back(&transposed);
177        assert_eq!(ciphertexts[0][0], 0x727B4E35F947129E);
178        assert_eq!(ciphertexts[0][63], 0x727B4E35F947129E);
179    }
180}