From 3664d556782c1897d19eb2d3893bae2ae9762f5f Mon Sep 17 00:00:00 2001 From: wikano Date: Wed, 17 Dec 2025 01:40:52 +0100 Subject: [PATCH] cryptographic signature, put registration and messages structure --- client-network/src/cryptographic_signature.rs | 55 +++++++++++++++++++ client-network/src/lib.rs | 3 + client-network/src/messages_structure.rs | 50 +++++++++++++++++ client-network/src/registration.rs | 50 +++++++++++++++++ todo.md | 5 +- 5 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 client-network/src/cryptographic_signature.rs create mode 100644 client-network/src/messages_structure.rs create mode 100644 client-network/src/registration.rs diff --git a/client-network/src/cryptographic_signature.rs b/client-network/src/cryptographic_signature.rs new file mode 100644 index 0000000..7c510b8 --- /dev/null +++ b/client-network/src/cryptographic_signature.rs @@ -0,0 +1,55 @@ +use p256::ecdsa::{ + Signature, SigningKey, VerifyingKey, + signature::{Signer, Verifier}, +}; +use rand_core::OsRng; + +/// +/// contains the ecdsa private key, the ecdsa public key and the username +/// +pub struct CryptographicSignature { + priv_key: SigningKey, + pub pub_key: VerifyingKey, + pub username: String, +} + +impl CryptographicSignature { + /// + /// creates a CryptographicSignature + /// + pub fn new(username: String) -> CryptographicSignature { + // generate a private key + let priv_key = SigningKey::random(&mut OsRng); + // extract the public key from the private key + let pub_key = VerifyingKey::from(&priv_key); + // return the new struct + CryptographicSignature { + priv_key: priv_key, + pub_key: pub_key, + username: username, + } + } +} + +/// +/// returns a string representing the pub_key as a String +/// +pub fn formatPubKey(crypto_pair: CryptographicSignature) -> String { + let encoded_point = crypto_pair.pub_key.to_encoded_point(false); + let pubkey_bytes = encoded_point.as_bytes(); + hex::encode(pubkey_bytes) +} + +#[cfg(test)] +mod tests { + // Note this useful idiom: importing names from outer (for mod tests) scope. + use super::*; + + #[test] + fn creating_cryptographic_signature() { + let username = String::from("quoicoubeh"); + let crypto_pair = CryptographicSignature::new(username); + let formatted_pubkey =formatPubKey(crypto_pair); + println!("pubkey : {}",formatted_pubkey); + } +} diff --git a/client-network/src/lib.rs b/client-network/src/lib.rs index 0b56579..aedf0b8 100644 --- a/client-network/src/lib.rs +++ b/client-network/src/lib.rs @@ -1,5 +1,8 @@ mod data; mod protocol; +mod cryptographic_signature; +mod registration; +mod messages_structure; /// Messages sent to the Network thread by the GUI. pub enum NetworkCommand { diff --git a/client-network/src/messages_structure.rs b/client-network/src/messages_structure.rs new file mode 100644 index 0000000..06b955f --- /dev/null +++ b/client-network/src/messages_structure.rs @@ -0,0 +1,50 @@ +struct UDPMessage { + id: [u8; 4], + msg_type: u8, + length: [u8; 2], + body: [u8; 985], + signature: [u8; 32], +} + +struct HandshakeMessage { + id: [u8; 4], + msg_type: u8, + length: [u8; 2], + extensions: [u8; 4], + name: [u8; 981], + signature: [u8; 32], +} + +impl UDPMessage { + pub fn ping(id: i32) -> UDPMessage { + UDPMessage { id: id.to_ne_bytes(), msg_type: 0, length: [0; 2], body: [0; 985], signature: [0; 32]} + } + + pub fn error(id: i32) -> UDPMessage { + + UDPMessage { id: id.to_ne_bytes(), msg_type: 129, length: [0; 2], body: [0; 985], signature: [0; 32]} + } + + pub fn hello(id: i32, length: i16, username: String) -> HandshakeMessage { + let username_bytes = username.as_bytes(); + + let mut body: [u8; 981] = [0; 981]; + + let length_to_copy = username_bytes.len().min(981); + body[..length_to_copy].copy_from_slice(&username_bytes[..length_to_copy]); + HandshakeMessage {id: id.to_ne_bytes(), msg_type: 1, length: length.to_ne_bytes(), extensions: [0;4], name: body, signature: [0;32]} + + } + + pub fn helloReply(id: i32, length: i16, username: String) -> HandshakeMessage { + let username_bytes = username.as_bytes(); + + let mut body: [u8; 981] = [0; 981]; + + let length_to_copy = username_bytes.len().min(981); + body[..length_to_copy].copy_from_slice(&username_bytes[..length_to_copy]); + HandshakeMessage {id: id.to_ne_bytes(), msg_type: 130, length: length.to_ne_bytes(), extensions: [0;4], name: body, signature: [0;32]} + + } +} + diff --git a/client-network/src/registration.rs b/client-network/src/registration.rs new file mode 100644 index 0000000..576a8f0 --- /dev/null +++ b/client-network/src/registration.rs @@ -0,0 +1,50 @@ +use crate::cryptographic_signature::{CryptographicSignature, formatPubKey}; +use std::net::UdpSocket; +/// +/// Registration with the server happens in two steps: first, the client +/// sends its cryptographic signature to the server using a PUT request over the HTTP API. +async fn register_with_the_server(crypto_pair: CryptographicSignature) -> Result<(), reqwest::Error>{ + let client = reqwest::Client::new(); + let uri = format!("https://jch.irif.fr:8443/peers/{}/key", crypto_pair.username); + let encoded_point = crypto_pair.pub_key.to_encoded_point(false); + let pubkey_bytes = encoded_point.as_ref().to_vec(); + let pubkey_bytes_minus = pubkey_bytes[1..].to_vec(); + // In order to register with the server, a peer ϕ makes a PUT request to the URL /peers/ϕ/key with its 64-byte public key in the body + let res = client.put(uri) + .body(pubkey_bytes_minus) + .send() + .await?; + if res.status().is_success() { + println!("Successfully registered with the server."); + } else { + eprintln!("Failed to register with the server. Status: {}", res.status()); + let str = hex::encode(res.bytes().await?); + eprintln!("erreur : {}", str); + } + Ok(()) +} + +/// It then +/// registers each of its IP addresses by sending a Hello request to the server. +/// After the client sends a Hello request to the server, the server will verify that the client is able +/// to receive requests by sending a Hello request to the client. If the client doesn’t reply to the Hello +/// request with a properly signed message, its address will not be published by the server. +fn register_ip_addresses(crypto_pair: CryptographicSignature) { + let socket = UdpSocket::bind("127.0.0.1:4242"); + //TODO +} + +#[cfg(test)] +mod tests { + // Note this useful idiom: importing names from outer (for mod tests) scope. + use super::*; + + #[tokio::test] + async fn creating_cryptographic_signature() { + let username = String::from("charlie_kirk"); + let crypto_pair = CryptographicSignature::new(username); + if let Err(e) = register_with_the_server(crypto_pair).await { + eprintln!("Error during registration: {}", e); + } + } +} diff --git a/todo.md b/todo.md index 09e5375..e6932fe 100644 --- a/todo.md +++ b/todo.md @@ -3,8 +3,9 @@ - get rsquest to the uri /peers/ ## registration with the server -- generation of the cryptographic key +- generation of the cryptographic key OK - put request to the uri (check if the peer is already connected) OK +- udp handshakes - get request to the uri /peers/key to get the public key of a peer - get request to the uri /peers/key/addresses @@ -25,7 +26,7 @@ fonctionnalités : s'enregistrer avec le serveur OK rechercher un pair -generer une clé publique +generer une clé publique OK rechercher les fichiers d'un pair telechargement des fichiers choisir un dossier à partager