functional encryption
This commit is contained in:
@@ -0,0 +1,117 @@
|
|||||||
|
use std::{
|
||||||
|
fmt::Display,
|
||||||
|
io::{BufRead, BufReader, Write},
|
||||||
|
net::TcpStream,
|
||||||
|
};
|
||||||
|
|
||||||
|
use openssl::{
|
||||||
|
pkey::Private,
|
||||||
|
rsa::Rsa,
|
||||||
|
symm::{decrypt, encrypt, Cipher},
|
||||||
|
};
|
||||||
|
|
||||||
|
fn aes_encrypt(
|
||||||
|
key: &[u8],
|
||||||
|
// iv: &[u8],
|
||||||
|
plaintext: &[u8],
|
||||||
|
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
|
||||||
|
let cipher = Cipher::aes_256_ecb();
|
||||||
|
let ciphertext = encrypt(cipher, key, None, plaintext)?;
|
||||||
|
Ok(ciphertext)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn aes_decrypt(
|
||||||
|
key: &[u8],
|
||||||
|
// iv: &[u8],
|
||||||
|
ciphertext: &[u8],
|
||||||
|
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
|
||||||
|
let cipher = Cipher::aes_256_ecb();
|
||||||
|
let plaintext = decrypt(cipher, key, None, ciphertext)?;
|
||||||
|
Ok(plaintext)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
pub fn handshake(mut stream: TcpStream, rsa: Rsa<Private>) -> ETcp {
|
||||||
|
let mut reader = BufReader::new(stream.try_clone().unwrap());
|
||||||
|
|
||||||
|
stream.write_all(&rsa.public_key_to_pem().unwrap()).unwrap();
|
||||||
|
|
||||||
|
stream.flush().unwrap();
|
||||||
|
|
||||||
|
let mut aes_encoded = String::new();
|
||||||
|
|
||||||
|
reader.read_line(&mut aes_encoded).unwrap();
|
||||||
|
|
||||||
|
let encrypted_data = base64::decode(aes_encoded.trim()).expect("Failed to decode base64");
|
||||||
|
|
||||||
|
let mut aes_decrypted = vec![0; 256];
|
||||||
|
|
||||||
|
let aes_len = rsa
|
||||||
|
.private_decrypt(
|
||||||
|
&encrypted_data,
|
||||||
|
&mut aes_decrypted,
|
||||||
|
openssl::rsa::Padding::PKCS1,
|
||||||
|
)
|
||||||
|
.expect("Decryption failed");
|
||||||
|
|
||||||
|
println!("len: {}", aes_len);
|
||||||
|
|
||||||
|
aes_decrypted.truncate(aes_len);
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Decrypted AES key ({} bytes): {:?}",
|
||||||
|
aes_decrypted.len(),
|
||||||
|
aes_decrypted
|
||||||
|
);
|
||||||
|
|
||||||
|
ETcp {
|
||||||
|
stream,
|
||||||
|
aes: aes_decrypted,
|
||||||
|
reader,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ETcp {
|
||||||
|
stream: TcpStream,
|
||||||
|
reader: BufReader<TcpStream>,
|
||||||
|
aes: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ETcp {
|
||||||
|
#[allow(deprecated)]
|
||||||
|
pub fn send<T: Display>(&mut self, d: T) {
|
||||||
|
let a = aes_encrypt(&self.aes, d.to_string().as_bytes()).unwrap();
|
||||||
|
|
||||||
|
self.stream
|
||||||
|
.write_all((base64::encode(a) + "\n").as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
self.stream.flush().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
pub fn read(&mut self) -> Option<String> {
|
||||||
|
let mut v_encoded = String::new();
|
||||||
|
|
||||||
|
self.reader.read_line(&mut v_encoded).unwrap();
|
||||||
|
|
||||||
|
let encrypted_data = base64::decode(v_encoded.trim()).expect("Failed to decode base64");
|
||||||
|
|
||||||
|
Some(String::from_utf8(aes_decrypt(&self.aes, &encrypted_data).unwrap()).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close(&self) {
|
||||||
|
self.stream
|
||||||
|
.shutdown(std::net::Shutdown::Both)
|
||||||
|
.expect("shutdown call failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clone(&mut self) -> Self {
|
||||||
|
let stream = self.stream.try_clone().unwrap();
|
||||||
|
ETcp {
|
||||||
|
reader: BufReader::new(stream.try_clone().unwrap()),
|
||||||
|
stream,
|
||||||
|
aes: self.aes.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
-20
@@ -1,5 +1,4 @@
|
|||||||
use std::{
|
use std::{
|
||||||
io::{BufRead, BufReader, Write},
|
|
||||||
net::TcpListener,
|
net::TcpListener,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
@@ -36,6 +35,17 @@ fn main() -> std::io::Result<()> {
|
|||||||
stream.send(res);
|
stream.send(res);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
// Check for inactivity
|
||||||
|
if last_activity.elapsed() > Duration::from_secs(60) {
|
||||||
|
println!(
|
||||||
|
"[MOJANG] {} inactive for too long",
|
||||||
|
session.local_player.name
|
||||||
|
);
|
||||||
|
methods::player::logout(&session).unwrap();
|
||||||
|
println!("[MOJANG] {} went offline", session.local_player.name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
match stream.read() {
|
match stream.read() {
|
||||||
None => {
|
None => {
|
||||||
// Client disconnected
|
// Client disconnected
|
||||||
@@ -54,29 +64,12 @@ fn main() -> std::io::Result<()> {
|
|||||||
Err(e) => format!("!{e}"),
|
Err(e) => format!("!{e}"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Err(e) => {
|
|
||||||
// println!(
|
|
||||||
// "[ERROR] Read error for {}: {}",
|
|
||||||
// session.local_player.name, e
|
|
||||||
// );
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check for inactivity
|
|
||||||
if last_activity.elapsed() > Duration::from_secs(60) {
|
|
||||||
println!(
|
|
||||||
"[MOJANG] {} inactive for too long",
|
|
||||||
session.local_player.name
|
|
||||||
);
|
|
||||||
methods::player::logout(&session).unwrap();
|
|
||||||
println!("[MOJANG] {} went offline", session.local_player.name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// stream.write_all(format!("!{e}").as_bytes()).unwrap();
|
stream.send(format!("!{e}"));
|
||||||
|
println!("Disconnected");
|
||||||
stream.close();
|
stream.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user