vnc-rs 0.5.3

An async implementation of VNC client side protocol
Documentation
/*
 * Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#![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;

/// Do a circular left shift on a width of HALF_KEY_SIZE.
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)
}

/// Create the 16 subkeys.
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();
        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()
}

/// Swap bits using the E table.
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)
}

/// Decrypt `message` using the `key`.
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)
}

/// Encrypt `message` using `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
}

/// Encrypt `message` using the `key`.
pub fn encrypt(message: &[u8], key: &Key) -> Vec<u8> {
    let key = key_to_u64(key);
    let subkeys = compute_subkeys(key);
    des(message, subkeys)
}

/// Feistel function.
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)
}

/// Swap bits using the IP table.
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)
}

/// Convert a `Key` to a 64-bits integer.
fn key_to_u64(key: &Key) -> u64 {
    let mut result = 0;
    for &part in key {
        result <<= 8;
        result += part as u64;
    }
    result
}

/// Convert a message to a vector of 64-bits integer.
fn message_to_u64s(message: &[u8]) -> Vec<u64> {
    message.chunks(8).map(|m| key_to_u64(&to_key(m))).collect()
}

/// Swap bits using the P table.
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)
}

/// Swap bits using the PC-1 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)
}

/// Swap bits using the PC-2 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)
}

/// Swap bits using the reverse FP 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)
}

/// Produce 4-bits using an S box.
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]
}

/// Swap bits using a table.
fn swap_bits(key: u64, table: &[u64]) -> u64 {
    let mut result = 0;

    for (pos, index) in table.iter().enumerate() {
        let bit = (key << (index - 1)) & FIRST_BIT;
        result |= bit >> pos;
    }

    result
}

/// Convert a slice to a `Key`.
fn to_key(slice: &[u8]) -> Key {
    let mut vec: Vec<u8> = slice.to_vec();
    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
}

/// Convert a `u64` to a `Vec<u8>`.
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);
    }
}