2023-09-26 12:37:59 +00:00
|
|
|
use std::sync::atomic::{AtomicU16, Ordering::SeqCst};
|
|
|
|
|
2023-09-22 10:34:35 +00:00
|
|
|
use aes::{
|
2023-09-24 11:16:57 +00:00
|
|
|
cipher::{
|
2023-09-25 09:30:54 +00:00
|
|
|
block_padding::NoPadding, generic_array::GenericArray, BlockDecrypt, BlockDecryptMut,
|
2023-09-24 11:16:57 +00:00
|
|
|
BlockEncryptMut, KeyInit, KeyIvInit,
|
|
|
|
},
|
2023-09-22 10:34:35 +00:00
|
|
|
Aes128,
|
|
|
|
};
|
2023-09-24 11:16:57 +00:00
|
|
|
use anyhow::{bail, Result};
|
2023-09-22 10:34:35 +00:00
|
|
|
use rand::{self, RngCore};
|
2023-09-24 11:16:57 +00:00
|
|
|
use sha2::{Digest, Sha256};
|
2023-09-22 10:34:35 +00:00
|
|
|
|
|
|
|
use crate::hex;
|
|
|
|
|
|
|
|
#[allow(non_camel_case_types)]
|
|
|
|
#[repr(u8)]
|
2023-09-24 11:16:57 +00:00
|
|
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
2023-09-22 10:34:35 +00:00
|
|
|
pub enum MsgType {
|
|
|
|
HANDSHAKE_REQUEST = 0x0,
|
|
|
|
ENCRYPTED_RESPONSE = 0x3,
|
|
|
|
ENCRYPTED_REQUEST = 0x6,
|
|
|
|
}
|
|
|
|
|
2023-09-22 12:14:46 +00:00
|
|
|
#[derive(Debug, Default)]
|
|
|
|
pub struct Security {
|
2023-09-26 12:37:59 +00:00
|
|
|
request_count: AtomicU16,
|
|
|
|
response_count: AtomicU16,
|
2023-09-24 11:16:57 +00:00
|
|
|
|
|
|
|
tcp_key: Option<[u8; 32]>,
|
2023-09-22 12:14:46 +00:00
|
|
|
}
|
2023-09-22 10:34:35 +00:00
|
|
|
|
|
|
|
impl Security {
|
2023-09-22 12:14:46 +00:00
|
|
|
const N: u128 = 141661095494369103254425781617665632877;
|
|
|
|
const KEY: [u8; 16] = Self::N.to_be_bytes();
|
2023-09-24 11:16:57 +00:00
|
|
|
const IV: [u8; 16] = [b'\0'; 16];
|
2023-09-22 10:34:35 +00:00
|
|
|
|
2023-09-26 12:37:59 +00:00
|
|
|
pub fn aes_decrypt(data: &mut [u8]) {
|
2023-09-22 12:14:46 +00:00
|
|
|
let array = GenericArray::from(Self::KEY);
|
2023-09-22 10:34:35 +00:00
|
|
|
let cipher = Aes128::new(&array);
|
|
|
|
|
|
|
|
for chunk in data.chunks_mut(16) {
|
|
|
|
let mut block = GenericArray::from_mut_slice(chunk);
|
|
|
|
cipher.decrypt_block(&mut block);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-25 09:30:54 +00:00
|
|
|
pub fn aes_cbc_encrypt(&self, raw: [u8; 32], key: &[u8; 32]) -> [u8; 32] {
|
2023-09-24 11:16:57 +00:00
|
|
|
type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
|
|
|
|
|
|
|
|
Aes256CbcEnc::new(key.into(), &Self::IV.into())
|
2023-09-25 09:30:54 +00:00
|
|
|
.encrypt_padded_vec_mut::<NoPadding>(&raw)
|
|
|
|
.try_into()
|
|
|
|
.unwrap()
|
2023-09-24 11:16:57 +00:00
|
|
|
}
|
|
|
|
|
2023-09-25 09:30:54 +00:00
|
|
|
pub fn aes_cbc_decrypt(&self, raw: [u8; 32], key: &[u8; 32]) -> [u8; 32] {
|
2023-09-24 11:16:57 +00:00
|
|
|
type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
|
|
|
|
|
|
|
|
Aes256CbcDec::new(key.into(), &Self::IV.into())
|
2023-09-25 09:30:54 +00:00
|
|
|
.decrypt_padded_vec_mut::<NoPadding>(&raw)
|
|
|
|
.unwrap()
|
|
|
|
.try_into()
|
|
|
|
.unwrap()
|
2023-09-24 11:16:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn tcp_key(&mut self, response: &[u8], key: &[u8; 32]) -> Result<()> {
|
|
|
|
if response == b"ERROR" {
|
2023-09-25 09:30:54 +00:00
|
|
|
bail!("authentication failed! (code ERROR)");
|
2023-09-24 11:16:57 +00:00
|
|
|
}
|
|
|
|
|
2023-09-25 09:30:54 +00:00
|
|
|
let payload: [u8; 32] = response[0..32]
|
|
|
|
.iter()
|
|
|
|
.map(|&b| b)
|
|
|
|
.collect::<Vec<u8>>()
|
|
|
|
.try_into()
|
|
|
|
.unwrap();
|
2023-09-24 11:16:57 +00:00
|
|
|
|
2023-09-25 09:30:54 +00:00
|
|
|
let sign = &response[32..];
|
|
|
|
let result = self.aes_cbc_decrypt(payload, &key);
|
2023-09-24 11:16:57 +00:00
|
|
|
|
2023-09-25 09:30:54 +00:00
|
|
|
if Sha256::digest(&result).into_iter().collect::<Vec<u8>>() != sign {
|
2023-09-24 11:16:57 +00:00
|
|
|
bail!("sign does not match");
|
|
|
|
}
|
|
|
|
|
2023-09-25 09:30:54 +00:00
|
|
|
self.tcp_key = Some(Self::xorstr(&result, key).try_into().unwrap());
|
2023-09-26 12:37:59 +00:00
|
|
|
self.request_count.store(0, SeqCst);
|
|
|
|
self.response_count.store(0, SeqCst);
|
2023-09-24 11:16:57 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn xorstr(lhs: &[u8], rhs: &[u8]) -> Vec<u8> {
|
2023-09-25 09:30:54 +00:00
|
|
|
debug_assert_eq!(lhs.len(), rhs.len());
|
2023-09-22 10:34:35 +00:00
|
|
|
|
2023-09-24 11:16:57 +00:00
|
|
|
lhs.iter().zip(rhs.iter()).map(|(&l, &r)| l ^ r).collect()
|
|
|
|
}
|
|
|
|
|
2023-09-26 12:37:59 +00:00
|
|
|
pub fn encode_8370(&self, msg: &[u8], msg_type: MsgType) -> Result<Vec<u8>> {
|
2023-09-24 11:16:57 +00:00
|
|
|
let mut header = hex("8370")?;
|
|
|
|
let mut data: Vec<u8> = msg.to_vec();
|
|
|
|
|
|
|
|
let mut size = data.len() as u16;
|
2023-09-22 10:34:35 +00:00
|
|
|
let mut padding = 0;
|
|
|
|
|
|
|
|
if msg_type == MsgType::ENCRYPTED_RESPONSE || msg_type == MsgType::ENCRYPTED_REQUEST {
|
|
|
|
if (size + 2) % 16 != 0 {
|
|
|
|
padding = 16 - ((size + 2) & 0xf);
|
|
|
|
size += padding + 32;
|
|
|
|
data.extend({
|
2023-09-24 11:16:57 +00:00
|
|
|
let mut d = vec![0; padding as usize];
|
2023-09-22 10:34:35 +00:00
|
|
|
rand::thread_rng().fill_bytes(&mut d);
|
|
|
|
|
|
|
|
d
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-24 11:16:57 +00:00
|
|
|
header.extend(size.to_be_bytes());
|
|
|
|
header.extend([0x20, (padding << 4) as u8 | msg_type as u8]);
|
|
|
|
|
|
|
|
data = {
|
2023-09-26 12:37:59 +00:00
|
|
|
let mut b = self
|
|
|
|
.request_count
|
|
|
|
.fetch_add(1, SeqCst)
|
|
|
|
.to_be_bytes()
|
|
|
|
.to_vec();
|
2023-09-24 11:16:57 +00:00
|
|
|
b.extend(data);
|
|
|
|
b
|
|
|
|
};
|
|
|
|
|
|
|
|
if msg_type == MsgType::ENCRYPTED_RESPONSE || msg_type == MsgType::ENCRYPTED_REQUEST {
|
|
|
|
let sign: Vec<u8> = Sha256::digest(Self::add_bytes(header.clone(), data.clone()))
|
|
|
|
.into_iter()
|
|
|
|
.collect();
|
|
|
|
|
2023-09-25 09:30:54 +00:00
|
|
|
data = self
|
|
|
|
.aes_cbc_encrypt(data.try_into().unwrap(), self.tcp_key.as_ref().unwrap())
|
|
|
|
.to_vec();
|
2023-09-24 11:16:57 +00:00
|
|
|
data.extend(sign);
|
|
|
|
}
|
|
|
|
|
|
|
|
header.extend(data);
|
|
|
|
Ok(header)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn add_bytes(mut lhs: Vec<u8>, rhs: Vec<u8>) -> Vec<u8> {
|
|
|
|
lhs.extend(rhs);
|
|
|
|
lhs
|
2023-09-22 10:34:35 +00:00
|
|
|
}
|
2023-09-26 12:37:59 +00:00
|
|
|
|
|
|
|
pub fn decode_8370(&self, buffer: &[u8], msg: &[u8]) -> Result<(Vec<Vec<u8>>, Vec<u8>)> {
|
|
|
|
todo!()
|
|
|
|
}
|
2023-09-22 10:34:35 +00:00
|
|
|
}
|
2023-09-25 09:30:54 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn aes_cbc_decrypt() {
|
|
|
|
let payload: [u8; 32] =
|
|
|
|
b",\xcbq_T\x81L\x96\xfa\xe7\xe4\xa7\xc5\xabU \r\xf5x\xd6\x08\x94_\\\xce\x8br\x1b\xa5\xbe\xc6\x1a"
|
|
|
|
.iter()
|
|
|
|
.map(|&b| b)
|
|
|
|
.collect::<Vec<u8>>()
|
|
|
|
.try_into()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let key = b"*[R\x00\xc2\xc0ML\x81\x1d\x05P\xe1\xdc[1CT6\xb9[wM*\x88\xd7\xe4ma\xfd\x96i";
|
|
|
|
let plain = b"\x9b\xaa\xdf\xff\x07\x1a\xd2\xe4\xb7TY\xe2\xf9\x8c\xdf\xe7!+\xda\xe4\x86GY\xe6j\x94\xdb\xe7\xb9b\xda\xe6";
|
|
|
|
|
|
|
|
let security = Security::default();
|
|
|
|
|
|
|
|
let result = security.aes_cbc_decrypt(payload, key);
|
|
|
|
|
|
|
|
assert_eq!(&result, plain);
|
|
|
|
}
|
|
|
|
}
|