rust-nex/src/kerberos/mod.rs

111 lines
3 KiB
Rust
Raw Normal View History

use std::io::{Read, Write};
use bytemuck::{bytes_of, Pod, Zeroable};
use chrono::{Datelike, Timelike};
use hmac::Hmac;
use md5::{Digest, Md5};
use rc4::{Rc4, Rc4Core, StreamCipher};
use rc4::cipher::StreamCipherCoreWrapper;
use rc4::consts::U16;
use hmac::Mac;
use rc4::KeyInit;
use crate::rmc::structures::RmcSerialize;
type Md5Hmac = Hmac<md5::Md5>;
pub fn derive_key(pid: u32, password: [u8; 16]) -> [u8; 16]{
let iteration_count = 65000 + pid%1024;
let mut key = password;
for _ in 0..iteration_count {
let mut md5 = Md5::new();
md5.update(key);
key = md5.finalize().try_into().unwrap();
}
key
}
#[derive(Pod, Zeroable, Copy, Clone)]
#[repr(transparent)]
pub struct KerberosDateTime(u64);
impl KerberosDateTime{
pub fn new(second: u64, minute: u64, hour: u64, day: u64, month: u64, year:u64 ) -> Self {
Self(second | (minute << 6) | (hour << 12) | (day << 17) | (month << 22) | (year << 26))
}
pub fn now() -> Self{
let now = chrono::Utc::now();
Self::new(
now.second() as u64,
now.minute() as u64,
now.hour() as u64,
now.day() as u64,
now.month() as u64,
now.year() as u64,
)
}
}
#[derive(Pod, Zeroable, Copy, Clone)]
#[repr(C, packed)]
pub struct TicketInternalData{
issued_time: KerberosDateTime,
pub pid: u32,
pub session_key: [u8; 32],
}
impl TicketInternalData{
pub(crate) fn new(pid: u32) -> Self{
Self{
issued_time: KerberosDateTime::now(),
pid,
session_key: rand::random()
}
}
pub(crate) fn encrypt(&self, key: [u8; 16]) -> Box<[u8]>{
let mut data = bytes_of(self).to_vec();
let mut rc4: StreamCipherCoreWrapper<Rc4Core<U16>> = Rc4::new_from_slice(&key).unwrap();
rc4.apply_keystream(&mut data);
let mut hmac = <Md5Hmac as KeyInit>::new_from_slice(&key).unwrap();
hmac.write_all(&data[..]).expect("failed to write data to hmac");
let hmac_result = &hmac.finalize().into_bytes()[..];
data.write_all(&hmac_result).expect("failed to write data to vec");
data.into_boxed_slice()
}
}
#[derive(Pod, Zeroable, Copy, Clone)]
#[repr(C, packed)]
pub struct Ticket{
pub session_key: [u8; 32],
pub pid: u32,
}
impl Ticket{
pub(crate) fn encrypt(&self, key: [u8; 16], internal_data: &[u8]) -> Box<[u8]>{
let mut data = bytes_of(self).to_vec();
internal_data.serialize(&mut data).expect("unable to write to vec");
let mut rc4: StreamCipherCoreWrapper<Rc4Core<U16>> = Rc4::new_from_slice(&key).unwrap();
rc4.apply_keystream(&mut data);
let mut hmac = <Md5Hmac as KeyInit>::new_from_slice(&key).unwrap();
hmac.write_all(&data[..]).expect("failed to write data to hmac");
let hmac_result = &hmac.finalize().into_bytes()[..];
data.write_all(&hmac_result).expect("failed to write data to vec");
data.into_boxed_slice()
}
}