#![allow(dead_code)]
pub type Key = [u8; 8];
const FIRST_BIT: u64 = 1 << 63;
const HALF_KEY_SIZE: i64 = KEY_SIZE / 2;
const KEY_SIZE: i64 = 56;
fn circular_left_shift(n1: u64, n2: u64, shift_count: i64) -> (u64, u64) {
let mut new_value1 = n1;
let mut new_value2 = n2;
for _ in 0 .. shift_count {
let first_bit = new_value1 & FIRST_BIT;
new_value1 = (new_value1 << 1) | (first_bit >> (HALF_KEY_SIZE - 1));
let first_bit = new_value2 & FIRST_BIT;
new_value2 = (new_value2 << 1) | (first_bit >> (HALF_KEY_SIZE - 1));
}
(new_value1, new_value2)
}
fn compute_subkeys(key: u64) -> Vec<u64> {
let table = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
let k0 = pc1(key);
let mut subkeys = vec![k0];
for shift_count in &table {
let last_key = subkeys.last().unwrap().clone();
let last_ci = last_key & 0xFFFFFFF000000000;
let last_di = last_key << HALF_KEY_SIZE;
let (ci, di) = circular_left_shift(last_ci, last_di, *shift_count);
let current_key = ci | (di >> HALF_KEY_SIZE);
subkeys.push(current_key);
}
subkeys.remove(0);
subkeys.iter().map(|&n| { pc2(n) }).collect()
}
fn e(block: u64) -> u64 {
let table =
[ 32, 1, 2, 3, 4, 5
, 4, 5, 6, 7, 8, 9
, 8, 9, 10, 11, 12, 13
, 12, 13, 14, 15, 16, 17
, 16, 17, 18, 19, 20, 21
, 20, 21, 22, 23, 24, 25
, 24, 25, 26, 27, 28, 29
, 28, 29, 30, 31, 32, 1
];
swap_bits(block, &table)
}
pub fn decrypt(cipher: &[u8], key: &Key) -> Vec<u8> {
let key = key_to_u64(key);
let mut subkeys = compute_subkeys(key);
subkeys.reverse();
des(cipher, subkeys)
}
fn des(message: &[u8], subkeys: Vec<u64>) -> Vec<u8> {
let blocks = message_to_u64s(message);
let mut cipher = vec![];
for block in blocks {
let permuted = ip(block);
let mut li = permuted & 0xFFFFFFFF00000000;
let mut ri = permuted << 32;
for subkey in &subkeys {
let last_li = li;
li = ri;
ri = last_li ^ feistel(ri, *subkey);
}
let r16l16 = ri | (li >> 32);
cipher.append(&mut to_u8_vec(fp(r16l16)));
}
cipher
}
pub fn encrypt(message: &[u8], key: &Key) -> Vec<u8> {
let key = key_to_u64(key);
let subkeys = compute_subkeys(key);
des(message, subkeys)
}
fn feistel(half_block: u64, subkey: u64) -> u64 {
let expanded = e(half_block);
let mut intermediate = expanded ^ subkey;
let mut result = 0;
for i in 0 .. 8 {
let block = (intermediate & 0xFC00000000000000) >> 58;
intermediate <<= 6;
result <<= 4;
result |= s(i, block);
}
p(result << 32)
}
fn ip(message: u64) -> u64 {
let table =
[ 58, 50, 42, 34, 26, 18, 10, 2
, 60, 52, 44, 36, 28, 20, 12, 4
, 62, 54, 46, 38, 30, 22, 14, 6
, 64, 56, 48, 40, 32, 24, 16, 8
, 57, 49, 41, 33, 25, 17, 9, 1
, 59, 51, 43, 35, 27, 19, 11, 3
, 61, 53, 45, 37, 29, 21, 13, 5
, 63, 55, 47, 39, 31, 23, 15, 7
];
swap_bits(message, &table)
}
fn key_to_u64(key: &Key) -> u64 {
let mut result = 0;
for &part in key {
result <<= 8;
result += part as u64;
}
result
}
fn message_to_u64s(message: &[u8]) -> Vec<u64> {
message.chunks(8)
.map(|m| key_to_u64(&to_key(m)))
.collect()
}
fn p(block: u64) -> u64 {
let table =
[ 16, 7, 20, 21
, 29, 12, 28, 17
, 1, 15, 23, 26
, 5, 18, 31, 10
, 2, 8, 24, 14
, 32, 27, 3, 9
, 19, 13, 30, 6
, 22, 11, 4, 25
];
swap_bits(block, &table)
}
fn pc1(key: u64) -> u64 {
let table =
[ 57, 49, 41, 33, 25, 17, 9
, 1, 58, 50, 42, 34, 26, 18
, 10, 2, 59, 51, 43, 35, 27
, 19, 11, 3, 60, 52, 44, 36
, 63, 55, 47, 39, 31, 23, 15
, 7, 62, 54, 46, 38, 30, 22
, 14, 6, 61, 53, 45, 37, 29
, 21, 13, 5, 28, 20, 12, 4
];
swap_bits(key, &table)
}
fn pc2(key: u64) -> u64 {
let table =
[ 14, 17, 11, 24, 1, 5
, 3, 28, 15, 6, 21, 10
, 23, 19, 12, 4, 26, 8
, 16, 7, 27, 20, 13, 2
, 41, 52, 31, 37, 47, 55
, 30, 40, 51, 45, 33, 48
, 44, 49, 39, 56, 34, 53
, 46, 42, 50, 36, 29, 32
];
swap_bits(key, &table)
}
fn fp(message: u64) -> u64 {
let table =
[ 40, 8, 48, 16, 56, 24, 64, 32
, 39, 7, 47, 15, 55, 23, 63, 31
, 38, 6, 46, 14, 54, 22, 62, 30
, 37, 5, 45, 13, 53, 21, 61, 29
, 36, 4, 44, 12, 52, 20, 60, 28
, 35, 3, 43, 11, 51, 19, 59, 27
, 34, 2, 42, 10, 50, 18, 58, 26
, 33, 1, 41, 9, 49, 17, 57, 25
];
swap_bits(message, &table)
}
fn s(box_id: usize, block: u64) -> u64 {
let tables =
[[[ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7]
, [ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8]
, [ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0]
, [ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]
],
[ [ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10]
, [ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5]
, [ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15]
, [ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9]
],
[ [ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8]
, [ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1]
, [ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7]
, [ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12]
],
[ [ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15]
, [ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9]
, [ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4]
, [ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14]
],
[ [ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9]
, [ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6]
, [ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14]
, [ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3]
],
[ [ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11]
, [ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8]
, [ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6]
, [ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13]
],
[ [ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1]
, [ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6]
, [ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2]
, [ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12]
],
[ [ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7]
, [ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2]
, [ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8]
, [ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11]
]];
let i = ((block & 0x20) >> 4 | (block & 1)) as usize;
let j = ((block & 0x1E) >> 1) as usize;
tables[box_id][i][j]
}
fn swap_bits(key: u64, table: &[u64]) -> u64 {
let mut result = 0;
let mut pos = 0;
for index in table.iter() {
let bit = (key << (index - 1)) & FIRST_BIT;
result |= bit >> pos;
pos += 1;
}
result
}
fn to_key(slice: &[u8]) -> Key {
let mut vec: Vec<u8> = slice.iter().cloned().collect();
let mut key = [0; 8];
let diff = key.len() - vec.len();
if diff > 0 {
vec.append(&mut vec![0; diff]);
}
key.clone_from_slice(&vec);
key
}
fn to_u8_vec(num: u64) -> Vec<u8> {
vec!
[ ((num & 0xFF00000000000000) >> 56) as u8
, ((num & 0x00FF000000000000) >> 48) as u8
, ((num & 0x0000FF0000000000) >> 40) as u8
, ((num & 0x000000FF00000000) >> 32) as u8
, ((num & 0x00000000FF000000) >> 24) as u8
, ((num & 0x0000000000FF0000) >> 16) as u8
, ((num & 0x000000000000FF00) >> 8) as u8
, (num & 0x00000000000000FF) as u8
]
}
#[cfg(test)]
mod tests {
use super::{decrypt, encrypt};
#[test]
fn test_encrypt_decrypt() {
let key = [0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1];
let message = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF];
let expected_cipher = vec![0x85, 0xE8, 0x13, 0x54, 0x0F, 0x0A, 0xB4, 0x05];
let cipher = encrypt(&message, &key);
assert_eq!(cipher, expected_cipher);
let cipher = expected_cipher;
let expected_message = message;
let message = decrypt(&cipher, &key);
assert_eq!(message, expected_message);
let message = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF];
let expected_cipher = vec![0x85, 0xE8, 0x13, 0x54, 0x0F, 0x0A, 0xB4, 0x05, 0x85, 0xE8, 0x13, 0x54, 0x0F, 0x0A, 0xB4, 0x05];
let cipher = encrypt(&message, &key);
assert_eq!(cipher, expected_cipher);
let cipher = expected_cipher;
let expected_message = message;
let message = decrypt(&cipher, &key);
assert_eq!(message, expected_message);
}
}