use std::io::{Read, Write};
pub fn decrypt_hs100(data: &mut [u8]) {
let mut key = 171u8;
for b in data {
if *b != 0 {
*b = *b ^ key;
key = *b ^ key;
}
}
}
pub fn encrypt_hs100(data: &mut [u8]) {
let mut key = 171u8;
for b in data {
if *b != 0 {
*b = *b ^ key;
key = *b;
}
}
}
pub fn read_hs100_str<T: Read + ?Sized>(stream: &mut T) -> std::io::Result<String> {
let mut len = [0; 4];
stream.read(&mut len)?;
let len = ((len[0] as usize) << 24)
+ ((len[1] as usize) << 16)
+ ((len[2] as usize) << 8)
+ (len[3] as usize);
let mut buf: Vec<u8> = vec![0; len];
stream.read_exact(&mut buf)?;
decrypt_hs100(&mut buf);
let mut result = std::str::from_utf8(&buf).unwrap().to_owned();
result.truncate(len);
Ok(result)
}
pub fn write_hs100_str<T: Write + ?Sized>(
stream: &mut T,
mut message: String,
) -> std::io::Result<()> {
let mut len = [0; 4];
len[3] = (message.len() % 0xFF) as u8;
len[2] = ((message.len() >> 8) % 0xFF) as u8;
len[1] = ((message.len() >> 16) % 0xFF) as u8;
len[0] = ((message.len() >> 24) % 0xFF) as u8;
let bytes = unsafe { message.as_bytes_mut() };
encrypt_hs100(bytes);
stream.write(&len)?;
stream.write(bytes)?;
Ok(())
}
#[cfg(test)]
mod tests {
#[test]
fn encrytion() {
let plaintext: &mut [u8] = &mut br#"{"system":{"get_sysinfo":{}}}"#.clone();
let cyphertext = [
208, 242, 129, 248, 139, 255, 154, 247, 213, 239, 148, 182, 209, 180, 192, 159, 236,
149, 230, 143, 225, 135, 232, 202, 240, 139, 246, 139, 246,
];
super::encrypt_hs100(plaintext);
assert_eq!(&plaintext, &cyphertext);
}
#[test]
fn decryption() {
let plaintext = br#"{"system":{"get_sysinfo":{}}}"#;
let cyphertext: &mut [u8] = &mut [
208, 242, 129, 248, 139, 255, 154, 247, 213, 239, 148, 182, 209, 180, 192, 159, 236,
149, 230, 143, 225, 135, 232, 202, 240, 139, 246, 139, 246,
]
.clone();
super::decrypt_hs100(cyphertext);
assert_eq!(&cyphertext, &plaintext);
}
#[test]
fn encrytion_roundtrip() {
let original = br#"{"system":{"get_sysinfo":{}}}"#;
let modified: &mut [u8] = &mut br#"{"system":{"get_sysinfo":{}}}"#.clone();
super::encrypt_hs100(modified);
super::decrypt_hs100(modified);
assert_eq!(&original, &modified);
}
#[test]
fn read() {
let plaintext = r#"{"system":{"get_sysinfo":{}}}"#.to_string();
let cyphertext: &[u8] = &[
0, 0, 0, 29, 208, 242, 129, 248, 139, 255, 154, 247, 213, 239, 148, 182, 209, 180, 192,
159, 236, 149, 230, 143, 225, 135, 232, 202, 240, 139, 246, 139, 246,
];
let result = super::read_hs100_str(&mut cyphertext.as_ref()).unwrap();
assert_eq!(&result, &plaintext);
}
#[test]
fn write() {
let plaintext = r#"{"system":{"get_sysinfo":{}}}"#.to_string();
let cyphertext = [
0, 0, 0, 29, 208, 242, 129, 248, 139, 255, 154, 247, 213, 239, 148, 182, 209, 180, 192,
159, 236, 149, 230, 143, 225, 135, 232, 202, 240, 139, 246, 139, 246,
];
let mut buffer: Vec<u8> = Vec::new();
super::write_hs100_str(&mut buffer, plaintext).unwrap();
assert_eq!(&buffer, &cyphertext);
}
}