ozelot 0.1.0

Handles everything network related to MCMODERN.
Documentation
//! This provides helper functions for various Yggdrasil/Protocol Encryption
//! related things.
use std::fmt::Write;
use std::io;

use openssl::hash::{self, MessageDigest};
use openssl::rand;
use openssl::rsa::{PKCS1_PADDING, Padding, Rsa};

const PADDING: Padding = PKCS1_PADDING;

/// Create a shared secret as used for protocol encryption
///
/// # Panics
///
/// Panics if there's an error generating the random bytes.
pub fn create_shared_secret() -> [u8; 16] {
    let mut ret = [0; 16];
    match rand::rand_bytes(&mut ret) {
        Ok(()) => (),
        Err(_) => {
            panic!("yggdrasil.create_shared_secret encountered an error");
        },
    }
    ret
}

/// Generate an RSA key as used by MC.
///
/// Call rsa_key_binary to convert it to the format used in EncryptionRequest.
pub fn generate_rsa_key() -> Rsa {
    Rsa::generate(1024).expect("Error generating RSA key")
}

/// Convert a given RSA key's public part into the DER format, i.e. the format
/// used in the EncryptionRequest packet.
///
/// # Panics
///
/// Panics if the given key does not have a valid public part.
/// It should never panic if called with a key generated by generate_rsa_key
pub fn rsa_key_binary(key: &Rsa) -> Vec<u8> {
    key.public_key_to_der().expect("Error converting RSA key to DER format")
}

/// Given a public key in DER format (the format you get it in in the
/// EncryptionRequest packet), and some data, RSA encrypt the data
///
/// For use with the EncryptionResponse packet.
///
/// The data must be able to fit within 128 bytes encrypted.
pub fn rsa_encrypt(pubkey: &[u8], data: &[u8]) -> io::Result<Vec<u8>> {
    let key = match Rsa::public_key_from_der(pubkey) {
        Ok(x) => x,
        Err(e) => {
            return io_error!("rsa_encrypt: Got error trying to read public key: {:?}",
                             e)
        },
    };

    let mut ret = vec![0; 128];
    match key.public_encrypt(data, &mut ret, PADDING) {
        Ok(128) => (),
        _ => return io_error!("yggdrasil::rsa_encrypt error encrypting data"),
    }

    Ok(ret)
}

/// Given a RSA key, and some data RSA encrypted with the key, decrypt the data
///
/// The given data to decrypt must be exactly 128 bytes long, and the data
/// decrypted must be able to fit within 128 bytes.
pub fn rsa_decrypt(key: &Rsa, data: &[u8]) -> io::Result<Vec<u8>> {
    if data.len() != 128 {
        return io_error!("yggdrasil::rsa_decrypt passed data was {}, not 16 bytes long",
                         data.len());
    }

    let mut ret = vec![0; 128];

    let len = match key.private_decrypt(data, &mut ret, PADDING) {
        Ok(x) if x <= 128 => x,
        _ => return io_error!("yggdrasil::rsa_decrypt error decrypting data"),
    };
    ret.truncate(len);

    Ok(ret)
}

/// Given the server_id, shared_secret and server's public key, calculate the
/// sha1 that is to be used for posting to Mojang
pub fn post_sha1(server_id: &str,
                 shared_secret: &[u8],
                 server_public_key: &[u8])
                 -> String {

    let mut tmp = server_id.as_bytes().to_vec();
    tmp.extend(shared_secret);
    tmp.extend(server_public_key);
    sha1(&tmp)
}

/// Calculate a Minecraft-style sha1
fn sha1(data: &[u8]) -> String {
    let mut digest =
        hash::hash(MessageDigest::sha1(), data).expect("yggdrasil::sha1 error");

    let mut negative = false;

    if digest[0] >= 128 {
        /* This means we have to calculate the twos complement */
        negative = true;

        for byte in digest.iter_mut() {
            *byte ^= 0xff;
        }

        /* Add 1 to the number */
        for byte in digest.iter_mut().rev() {
            if *byte == 255 {
                *byte = 0;
            } else {
                *byte += 1;
                break;
            }
        }
    }

    let mut ret = String::new();
    if negative {
        write!(&mut ret, "-").expect("yggdrasil.sha1 failed writing to String");
    }

    let mut non_zero = false;
    for byte in &digest {
        if *byte >= 16 {
            non_zero = true;
        } else if non_zero == false && *byte > 0 {
            /* If the value is 0 < n < 16, we write the second (hexa)decimal
             * in it, but the first is 0 so is omitted */
            write!(&mut ret, "{:x}", byte)
                .expect("yggdrasil.sha1 failed writing to String");
            non_zero = true;
            continue;
        }
        if non_zero {
            write!(&mut ret, "{:02x}", byte)
                .expect("yggdrasil.sha1 failed writing to String");
        }
    }
    ret
}

#[cfg(test)]
mod test {

    #[test]
    fn sha1() {
        assert_eq!(super::sha1("Ozelot".as_bytes()),
                   "5cfe44b70ee91ccccdb05b1ab8b328d5d8632cbf");
        assert_eq!(super::sha1("Cactus".as_bytes()),
                   "-43468c66aebd37d40b99237799da0772d04308");
        assert_eq!(super::sha1("Bobcat".as_bytes()),
                   "-da0143edc7918223fcc86951a195a5212c77c3f");
    }

    #[test]
    fn rsa() {
        use openssl::rsa::Rsa;
        /* Don't worry, the data and key here were generated specifically for
         * this test */
        let random_data = [0xd7, 0x0f, 0xe4, 0xdb, 0xbf, 0x8b, 0xca, 0x98,
                           0x03, 0xf1, 0x5a, 0x5e, 0x19, 0x1b, 0x9c, 0xfe];
        let key =
            [48, 130, 2, 93, 2, 1, 0, 2, 129, 129, 0, 165, 142, 222, 16, 232,
             164, 176, 243, 229, 48, 68, 247, 171, 149, 34, 247, 217, 61, 36,
             28, 168, 234, 195, 78, 187, 143, 161, 154, 174, 59, 132, 34, 123,
             186, 68, 66, 218, 181, 131, 20, 240, 218, 116, 19, 236, 144, 131,
             145, 125, 206, 197, 61, 50, 61, 173, 92, 186, 206, 96, 102, 89,
             143, 15, 20, 116, 105, 29, 15, 93, 5, 68, 181, 106, 122, 39, 86,
             166, 174, 113, 21, 95, 195, 103, 236, 31, 67, 51, 74, 17, 91,
             234, 150, 253, 155, 7, 26, 7, 162, 206, 12, 77, 28, 82, 80, 44,
             197, 145, 13, 90, 71, 233, 29, 28, 68, 101, 194, 95, 108, 9, 221,
             160, 158, 120, 32, 234, 81, 57, 185, 2, 3, 1, 0, 1, 2, 129, 129,
             0, 134, 165, 46, 205, 169, 167, 103, 146, 180, 47, 17, 168, 44,
             15, 218, 164, 160, 53, 45, 141, 113, 131, 156, 220, 7, 134, 196,
             243, 188, 8, 3, 106, 216, 29, 161, 46, 142, 25, 89, 70, 74, 172,
             32, 3, 164, 61, 212, 3, 27, 194, 114, 127, 86, 192, 250, 161,
             147, 252, 12, 66, 177, 75, 188, 2, 163, 167, 51, 11, 237, 143,
             223, 246, 227, 248, 244, 35, 11, 252, 193, 223, 43, 142, 102,
             232, 74, 111, 244, 13, 171, 30, 19, 106, 105, 47, 224, 213, 173,
             188, 107, 79, 73, 99, 220, 159, 185, 185, 125, 97, 216, 183, 64,
             146, 240, 231, 85, 197, 41, 81, 164, 158, 33, 170, 54, 17, 69,
             179, 38, 1, 2, 65, 0, 213, 65, 118, 227, 240, 116, 200, 65, 30,
             238, 176, 145, 174, 66, 78, 91, 70, 204, 29, 135, 199, 14, 224,
             225, 236, 148, 235, 81, 28, 35, 44, 138, 146, 246, 216, 123, 214,
             73, 56, 129, 213, 130, 131, 225, 1, 166, 95, 69, 194, 2, 250,
             109, 175, 80, 137, 161, 21, 229, 233, 83, 189, 130, 67, 113, 2,
             65, 0, 198, 189, 243, 108, 224, 96, 21, 114, 7, 68, 28, 42, 99,
             214, 114, 43, 63, 215, 241, 168, 113, 212, 255, 201, 146, 93, 37,
             99, 35, 66, 32, 148, 166, 92, 244, 86, 14, 105, 84, 59, 81, 190,
             3, 57, 127, 17, 167, 77, 73, 184, 231, 180, 251, 157, 201, 150,
             201, 247, 24, 28, 182, 191, 166, 201, 2, 65, 0, 158, 189, 23, 17,
             126, 184, 127, 35, 178, 49, 188, 47, 4, 134, 136, 170, 250, 221,
             15, 18, 53, 131, 6, 180, 69, 21, 104, 192, 60, 112, 150, 68, 36,
             55, 40, 87, 173, 223, 92, 247, 144, 5, 145, 195, 24, 38, 78, 126,
             175, 118, 230, 16, 101, 82, 78, 208, 32, 107, 190, 45, 190, 63,
             203, 145, 2, 64, 67, 160, 6, 224, 153, 72, 152, 131, 128, 109,
             112, 152, 11, 248, 192, 72, 111, 36, 239, 153, 189, 130, 24, 183,
             98, 18, 71, 210, 128, 0, 212, 77, 64, 126, 136, 181, 111, 153,
             239, 139, 111, 185, 20, 39, 208, 81, 21, 120, 123, 9, 107, 238,
             109, 95, 183, 100, 147, 188, 124, 123, 232, 195, 53, 225, 2, 64,
             56, 181, 224, 132, 112, 99, 183, 125, 253, 25, 5, 145, 81, 200,
             103, 12, 131, 16, 199, 182, 63, 7, 54, 35, 71, 240, 64, 15, 153,
             1, 137, 114, 102, 203, 151, 8, 211, 57, 198, 209, 93, 106, 31,
             219, 216, 77, 2, 17, 220, 117, 173, 70, 56, 86, 160, 240, 131,
             39, 20, 122, 81, 79, 140, 104];
        let key = Rsa::private_key_from_der(&key).unwrap();
        let pubkey = super::rsa_key_binary(&key);
        let encrypted = super::rsa_encrypt(&pubkey, &random_data).unwrap();
        let decrypted = super::rsa_decrypt(&key, &encrypted).unwrap();
        assert_eq!(&random_data, &*decrypted);
    }
}