diff --git a/Cargo.toml b/Cargo.toml index af68115..c0b6cc4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,3 +27,6 @@ readonly = "0.2.13" sha2 = "0.10.9" smol = "2.0.2" tappers = "0.4.2" + +[features] +no-timeout = [] diff --git a/src/client/main.rs b/src/client/main.rs index 00e57eb..390be7e 100644 --- a/src/client/main.rs +++ b/src/client/main.rs @@ -52,6 +52,7 @@ fn main() -> std::io::Result<()> { })() .expect("Failed to bind to any available port"); + #[cfg(not(feature = "no-timeout"))] socket.set_read_timeout(Some(Duration::new(10, 0)))?; // set timeout to 10 seconds let server_port: u16 = (|| -> u16 { @@ -82,6 +83,14 @@ fn main() -> std::io::Result<()> { rng.fill_bytes(&mut salt); rng.fill_bytes(&mut iv); let enc_key_tmp = shared::crypto::derive_key_from_password(p.as_bytes(), &salt); + #[cfg(debug_assertions)] + eprintln!( + "key: {}", + enc_key_tmp + .iter() + .map(|x| format!("{:02X} ", x)) + .collect::() + ); ( shared::crypto::encrypt(&enc_key_tmp, &iv, public_sock_addr_raw.as_bytes()) .unwrap() diff --git a/src/client/net.rs b/src/client/net.rs index f050fa8..4b8eaf3 100644 --- a/src/client/net.rs +++ b/src/client/net.rs @@ -116,6 +116,22 @@ pub fn register_request( + public_sock_addr.len() ] .into_boxed_slice(); + + #[cfg(debug_assertions)] + eprintln!( + "registering network:\niv: {}\nSockAddr: {}\nsalt: {}", + iv.iter().map(|x| format!("{:02X} ", x)).collect::(), + public_sock_addr + .iter() + .map(|x| format!("{:02X} ", x)) + .collect::(), + network + .salt + .iter() + .map(|x| format!("{:02X} ", x)) + .collect::(), + ); + send_buf[0] = ServerMethods::REGISTER as u8; // set metod identification byte send_buf[RegisterRequestDataPositions::ENCRYPTED as usize] = network.encrypted as u8; @@ -184,7 +200,7 @@ pub fn get_request( false }; - let num_of_clients: u8 = buf[GetResponseDataPositions::NUM_OF_CLIENTS as usize]; + let mut num_of_clients: u8 = buf[GetResponseDataPositions::NUM_OF_CLIENTS as usize]; let salt: [u8; SALT_AND_IV_SIZE as usize] = buf[GetResponseDataPositions::SALT as usize ..GetResponseDataPositions::SALT as usize + SALT_AND_IV_SIZE as usize] @@ -198,6 +214,13 @@ pub fn get_request( Some(p) => shared::crypto::derive_key_from_password(p.as_bytes(), &salt), None => [0; 32], }; + #[cfg(debug_assertions)] + eprintln!( + "key: {}", + key.iter() + .map(|x| format!("{:02X} ", x)) + .collect::() + ); while num_of_clients != 0 { let sock_addr_len: u8 = buf[GetResponseDataPositions::CLIENTS as usize + offset]; @@ -211,6 +234,14 @@ pub fn get_request( + sock_addr_len as usize] .to_vec() .into_boxed_slice(); + #[cfg(debug_assertions)] + eprintln!( + "sock_addr_raw: {}", + sock_addr_raw + .iter() + .map(|x| format!("{:02X} ", x)) + .collect::() + ); loop { // loop used to easily skip peer let peer: SocketAddr = if encrypted { @@ -267,6 +298,7 @@ pub fn get_request( break; } offset += SALT_AND_IV_SIZE as usize + sock_addr_len as usize; + num_of_clients -= 1; } return Ok(types::Network::new( @@ -291,6 +323,7 @@ pub fn send_heartbeat( HeartBeatRequestDataPositions::IV as usize + SALT_AND_IV_SIZE as usize + my_public_sock_addr.len() + + network.net_id.len() ] .into_boxed_slice(); diff --git a/src/lib.rs b/src/lib.rs index 1c0bb59..0456c66 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,7 +92,8 @@ pub enum GetResponseDataPositions { ENCRYPTED = 1, // this feeld should be 0 if not encrypted NUM_OF_CLIENTS = 2, SALT = 3, - CLIENTS = (SALT_AND_IV_SIZE as usize + RegisterRequestDataPositions::SALT as usize) as usize, + CLIENTS = + (SALT_AND_IV_SIZE as usize + RegisterRequestDataPositions::SALT as usize) - 1 as usize, // after this there will be blocks of this sturcture: one byte size of sockaddr than there will be IV that is SALT_AND_IV_SIZE long and after that there will be sockaddr this repeats until the end of packet } diff --git a/src/server/main.rs b/src/server/main.rs index 1d6ae32..cad0d74 100644 --- a/src/server/main.rs +++ b/src/server/main.rs @@ -24,9 +24,10 @@ fn main() -> std::io::Result<()> { let registration_vector: Arc> = Arc::new(orx_concurrent_vec::ConcurrentVec::new()); - let mut buf: [u8; pea_2_pea::BUFFER_SIZE] = [0; pea_2_pea::BUFFER_SIZE]; + let mut buf: [u8; pea_2_pea::BUFFER_SIZE] = [0u8; pea_2_pea::BUFFER_SIZE]; smol::block_on(async { loop { + buf.fill(0); match socket.recv_from(&mut buf) { Ok((data_length, src)) => { smol::spawn(net::handle_request( diff --git a/src/server/net.rs b/src/server/net.rs index 3b50551..06dde53 100644 --- a/src/server/net.rs +++ b/src/server/net.rs @@ -48,7 +48,7 @@ pub async fn handle_request( return; // drop packet if id lenght is biger than posible } - let net_id: String = match std::str::from_utf8(&buf[1..]) { + let net_id: String = match std::str::from_utf8(&buf[1..data_len]) { Ok(s) => s.to_string(), Err(e) => { eprint!("id to utf-8 failed: {}", e); @@ -68,7 +68,7 @@ pub async fn handle_request( eprintln!("send {} bytes", s); } Err(e) => { - eprintln!("Error snding data: {}", e); + eprintln!("Error sending data: {}", e); } }; return; @@ -84,11 +84,13 @@ pub async fn handle_request( // lets start serializing send_vec.push(registration.encrypted as u8); - send_vec.push(registration.net_id.len() as u8); send_vec.push(registration.clients.len() as u8); // todo!("make sure it allows only 255 client per network max"); send_vec.extend_from_slice(®istration.salt); + #[cfg(debug_assertions)] + eprintln!("Found {} clients", registration.clients.len()); + registration.clients.iter().for_each(|client| { let sock_addr_len: u8 = client.client_sock_addr.len() as u8; @@ -131,7 +133,7 @@ pub async fn handle_request( //read lenght of sockaddr // rustc be like RUST HAS NO TERNARY OPERATON USE if-else - let len_id: u8 = if buf[RegisterRequestDataPositions::ID_LEN as usize] != 0 { + let id_len: u8 = if buf[RegisterRequestDataPositions::ID_LEN as usize] != 0 { buf[RegisterRequestDataPositions::ID_LEN as usize] } else { return; @@ -146,7 +148,7 @@ pub async fn handle_request( let net_id: String = match std::str::from_utf8( &buf[(RegisterRequestDataPositions::DATA as usize) - ..(len_id as usize) + (RegisterRequestDataPositions::DATA as usize)], + ..(id_len as usize) + (RegisterRequestDataPositions::DATA as usize)], ) { Ok(s) => s.to_string(), Err(e) => { @@ -197,12 +199,33 @@ pub async fn handle_request( salt = None; iv = None; } + let client_sock_addr: Vec = buf[RegisterRequestDataPositions::DATA as usize + + id_len as usize + ..RegisterRequestDataPositions::DATA as usize + + id_len as usize + + (sock_addr_len as usize)] + .to_vec(); + + #[cfg(debug_assertions)] + eprintln!( + "first client registerd:\n iv: {}\nSockAddr: {}\nsalt: {}", + iv.iter() + .flatten() + .map(|x| format!("{:02X} ", x)) + .collect::(), + client_sock_addr + .iter() + .map(|x| format!("{:02X} ", x)) + .collect::(), + salt.iter() + .flatten() + .map(|x| format!("{:02X} ", x)) + .collect::(), + ); registration_vector.push(types::Registration::new( net_id, - buf[(RegisterRequestDataPositions::DATA as usize) - ..(RegisterRequestDataPositions::DATA as usize) + (sock_addr_len as usize)] - .to_vec(), + client_sock_addr, encrypted, chrono::Utc::now().timestamp(), salt, diff --git a/src/shared/crypto.rs b/src/shared/crypto.rs index e305ba6..b36aa5b 100644 --- a/src/shared/crypto.rs +++ b/src/shared/crypto.rs @@ -30,5 +30,70 @@ pub fn decrypt( ciphertext: &[u8], ) -> Result, Box> { let cipher = Aes256CbcDec::new_from_slices(key, iv)?; - Ok(cipher.decrypt_padded_vec_mut::(ciphertext).unwrap()) + match cipher.decrypt_padded_vec_mut::(ciphertext) { + Ok(v) => Ok(v), + Err(e) => Err(format!("Decryption unpad error: {:?}", e).into()), + } +} + +pub fn test_all_crypto_functions() { + // Test data + let password = b"test_password_123"; + let salt = b"random_salt_data"; + let iv = b"1234567890123456"; // 16 bytes for AES-256-CBC + let test_data = b"Hello, this is secret data to encrypt and decrypt!"; + + println!("Testing crypto functions..."); + + // Test 1: Key derivation + println!("1. Testing key derivation..."); + let key = derive_key_from_password(password, salt); + println!(" ✓ Key derived successfully: {} bytes", key.len()); + + // Test 2: Encryption + println!("2. Testing encryption..."); + match encrypt(&key, iv, test_data) { + Ok(ciphertext) => { + println!(" ✓ Encryption successful"); + println!(" Original data length: {} bytes", test_data.len()); + println!(" Encrypted data length: {} bytes", ciphertext.len()); + + // Test 3: Decryption + println!("3. Testing decryption..."); + match decrypt(&key, iv, &ciphertext) { + Ok(decrypted) => { + println!(" ✓ Decryption successful"); + + // Test 4: Verify data integrity + println!("4. Verifying data integrity..."); + if decrypted == test_data { + println!( + " ✓ Data integrity verified - original and decrypted data match!" + ); + } else { + println!(" ✗ Data integrity failed - data doesn't match!"); + } + } + Err(e) => { + println!(" ✗ Decryption failed: {:?}", e); + } + } + } + Err(e) => { + println!(" ✗ Encryption failed: {:?}", e); + } + } + + // Test 5: Test with different key (should fail to decrypt properly) + println!("5. Testing with wrong key (should fail)..."); + let wrong_key = derive_key_from_password(b"wrong_password", salt); + match encrypt(&key, iv, test_data) { + Ok(ciphertext) => match decrypt(&wrong_key, iv, &ciphertext) { + Ok(_) => println!(" ⚠ Unexpected success with wrong key"), + Err(_) => println!(" ✓ Correctly failed with wrong key"), + }, + Err(e) => println!(" Error in setup: {:?}", e), + } + + println!("All tests completed!"); }