1 Commits

Author SHA1 Message Date
Tiago Batista Cardoso
82cc134626 thing 2026-01-11 22:00:10 +01:00
11 changed files with 62 additions and 465 deletions

BIN
README.md

Binary file not shown.

View File

@@ -301,7 +301,7 @@ impl eframe::App for P2PClientApp {
ui.label("No connection.."); ui.label("No connection..");
} }
ServerStatus::ConnectedHandshake => { ServerStatus::ConnectedHandshake => {
let str = format!("📡"); let str = format!("📡 {}", self.active_server);
ui.label(str); ui.label(str);
} }
} }
@@ -343,18 +343,11 @@ impl eframe::App for P2PClientApp {
} else { } else {
for peer in &self.known_peers { for peer in &self.known_peers {
let is_active = let is_active =
self.active_peer.as_ref().map_or(false, |id| id == &peer.0); // if peer.id == self.active_peer_id self.active_peer.as_ref().map_or(false, |id| id == peer); // if peer.id == self.active_peer_id
let selectable = ui.selectable_label(is_active, format!("{}", peer));
let selectable;
if &self.active_server == &peer.0 {
selectable =
ui.selectable_label(is_active, format!("{} 📡 🌀", peer.0))
} else {
selectable = ui.selectable_label(is_active, format!("{}", peer.0));
}
if selectable.clicked() { if selectable.clicked() {
// switch to displaying this peer's tree // switch to displaying this peer's tree
self.active_peer = Some(peer.0.clone()); self.active_peer = Some(peer.clone());
// Request root content if not loaded // Request root content if not loaded
if !self if !self
.loaded_fs .loaded_fs
@@ -375,10 +368,10 @@ impl eframe::App for P2PClientApp {
.button("Utiliser le peer en tant que serveur") .button("Utiliser le peer en tant que serveur")
.clicked() .clicked()
{ {
self.active_server = peer.0.to_string(); self.active_server = peer.to_string();
let res = self.network_cmd_tx.send( let res = self.network_cmd_tx.send(
NetworkCommand::ServerHandshake( NetworkCommand::ServerHandshake(
peer.0.to_string(), peer.to_string(),
self.connected_address.clone(), self.connected_address.clone(),
), ),
); );

View File

@@ -1,5 +1,6 @@
use std::io::Read; use std::io::Read;
use crate::messages_structure::HandshakeMessage;
use bytes::Bytes; use bytes::Bytes;
use p256::EncodedPoint; use p256::EncodedPoint;
use p256::ecdsa::{ use p256::ecdsa::{
@@ -108,10 +109,11 @@ pub fn sign_message(crypto_pair: &CryptographicSignature, message: &Vec<u8>) ->
let digest = Sha256::digest(&message[..7 + msg_length as usize]); let digest = Sha256::digest(&message[..7 + msg_length as usize]);
let signature = crypto_pair.priv_key.sign_prehash_recoverable(&digest); let signature = crypto_pair.priv_key.sign_prehash_recoverable(&digest);
let message_length = 7 + msg_length as usize + 64; let message_length = 12 + msg_length as usize + 32;
let mut signed_message = Vec::with_capacity(message_length); let mut signed_message = Vec::with_capacity(message_length);
println!("{}", message_length); println!("{}", message_length);
signed_message.extend_from_slice(&message[..7 + msg_length as usize]); signed_message.extend_from_slice(&message[..8 + msg_length as usize]);
signed_message.pop();
println!("signed_tmp:{:?}", signed_message); println!("signed_tmp:{:?}", signed_message);
match signature { match signature {
Ok(signature) => { Ok(signature) => {
@@ -122,7 +124,7 @@ pub fn sign_message(crypto_pair: &CryptographicSignature, message: &Vec<u8>) ->
let s_bytes = s.to_bytes(); let s_bytes = s.to_bytes();
signed_message.extend_from_slice(&r_bytes[..32]); signed_message.extend_from_slice(&r_bytes[..32]);
signed_message.extend_from_slice(&s_bytes[..32]); signed_message.extend_from_slice(&s_bytes[..32]);
println!("signed:{:?}, len: {}", signed_message, signed_message.len()); println!("signed:{:?}", signed_message);
signed_message signed_message
} }
Err(e) => { Err(e) => {
@@ -146,7 +148,10 @@ mod tests {
println!("pubkey : {}", formatted_pubkey); println!("pubkey : {}", formatted_pubkey);
} }
/*#[test] ///
/// signs a message
///
#[test]
fn signing_message() { fn signing_message() {
let username = String::from("gamixtreize"); let username = String::from("gamixtreize");
let crypto_pair = CryptographicSignature::new(username.clone()); let crypto_pair = CryptographicSignature::new(username.clone());
@@ -155,5 +160,5 @@ mod tests {
let signed_message = sign_message(&crypto_pair, &ser); let signed_message = sign_message(&crypto_pair, &ser);
println!("unsigned_message: {:?}", ser); println!("unsigned_message: {:?}", ser);
println!("signed_message: {:?}", signed_message); println!("signed_message: {:?}", signed_message);
}*/ }
} }

View File

@@ -1 +0,0 @@
fn parse_received_datum(recevied_datum: Vec<u8>) {}

View File

@@ -1,10 +1,8 @@
mod cryptographic_signature; mod cryptographic_signature;
mod data; mod data;
mod datum_parsing;
mod message_handling; mod message_handling;
mod messages_channels; mod messages_channels;
mod messages_structure; mod messages_structure;
mod peers_refresh;
mod registration; mod registration;
mod server_communication; mod server_communication;
@@ -187,7 +185,6 @@ pub fn start_p2p_executor(
start_receving_thread( start_receving_thread(
sd, sd,
*first, // copie le SocketAddr (implémente Copy pour SocketAddr) *first, // copie le SocketAddr (implémente Copy pour SocketAddr)
event_tx.clone(), //
); );
register_ip_addresses( register_ip_addresses(
sd.cryptopair_ref(), sd.cryptopair_ref(),
@@ -299,7 +296,7 @@ pub fn start_p2p_executor(
let mut current = String::new(); let mut current = String::new();
for i in peers_list.chars() { for i in peers_list.chars() {
if i == '\n' { if i == '\n' {
peers.push((current.clone(), false)); peers.push(current.clone());
current.clear(); current.clear();
} else { } else {
current.push(i); current.push(i);

View File

@@ -4,14 +4,11 @@ use crate::{
CryptographicSignature, get_peer_key, sign_message, verify_signature, CryptographicSignature, get_peer_key, sign_message, verify_signature,
}, },
messages_channels::MultipleSenders, messages_channels::MultipleSenders,
messages_structure::construct_message, messages_structure::HandshakeMessage,
registration, registration,
}; };
use std::sync::{Arc, Mutex};
use std::{collections::HashMap, net::SocketAddr}; use std::{collections::HashMap, net::SocketAddr};
use std::{
net::IpAddr,
sync::{Arc, Mutex},
};
pub enum EventType { pub enum EventType {
ServerHelloReply, ServerHelloReply,
@@ -19,24 +16,29 @@ pub enum EventType {
PeerHello, PeerHello,
} }
const ID: usize = 4; /*pub fn handle_recevied_message(
const TYPE: usize = 5; messages_list: &mut HashMap<i32, EventType>,
const LENGTH: usize = 7; recevied_message: &Vec<u8>,
const EXTENSIONS: usize = 4; crypto_pair: &CryptographicSignature,
const SIGNATURE: usize = 64; socket_addr: &SocketAddr,
senders: &MultipleSenders,
const PING: u8 = 0; ) {
const OK: u8 = 128; let message_id: [u8; 4] = recevied_message[0..4].try_into().expect("size error");
const ERROR: u8 = 129; let id = i32::from_be_bytes(message_id);
const HELLO: u8 = 1; let eventtype = messages_list.get(&id);
const HELLOREPLY: u8 = 130; match eventtype {
const ROOTREQUEST: u8 = 2; Some(EventType::ServerHelloReply) => {
const ROOTREPLY: u8 = 131; registration::register_ip_addresses(
const DATUMREQUEST: u8 = 3; &crypto_pair,
const NODATUM: u8 = 133; socket_addr.ip().to_string(),
const DATUM: u8 = 132; &senders,
const NATTRAVERSALREQUEST: u8 = 4; messages_list,
const NATTRAVERSALREQUEST2: u8 = 5; );
}
Some(_) => print!("Not implemented"),
None => print!("Message not found"),
}
}*/
pub fn handle_recevied_message( pub fn handle_recevied_message(
messages_list: &Arc<Mutex<HashMap<i32, EventType>>>, messages_list: &Arc<Mutex<HashMap<i32, EventType>>>,
@@ -45,8 +47,6 @@ pub fn handle_recevied_message(
socket_addr: &SocketAddr, socket_addr: &SocketAddr,
senders: &MultipleSenders, senders: &MultipleSenders,
server_name: &String, server_name: &String,
cmd_tx: crossbeam_channel::Sender<NetworkEvent>,
ip: SocketAddr,
) { ) {
if recevied_message.len() < 4 { if recevied_message.len() < 4 {
return; return;
@@ -55,33 +55,8 @@ pub fn handle_recevied_message(
let message_id: [u8; 4] = recevied_message[0..4].try_into().expect("size error"); let message_id: [u8; 4] = recevied_message[0..4].try_into().expect("size error");
let id = i32::from_be_bytes(message_id); let id = i32::from_be_bytes(message_id);
let mut is_resp_to_server_handshake = false;
if recevied_message[4] == HELLO {
let length_bytes: [u8; 2] = recevied_message[TYPE..LENGTH]
.try_into()
.expect("Taille incorrecte");
let msg_length = u16::from_be_bytes(length_bytes) as usize;
let ilength = u16::from_be_bytes(length_bytes);
let received_name = &recevied_message[LENGTH + EXTENSIONS..LENGTH + ilength as usize];
let name = String::from_utf8(received_name.to_vec()).expect("wrong name");
if name.clone() == server_name.clone() {
is_resp_to_server_handshake = true;
}
}
let resp = parse_message(recevied_message.to_vec(), id, crypto_pair, cmd_tx, ip);
match resp {
None => {}
Some(resp_msg) => {
println!("msg_sent:{:?}", resp_msg);
senders.send_via(0, resp_msg, ip.to_string(), is_resp_to_server_handshake);
}
}
// Lock the mutex to access the HashMap // Lock the mutex to access the HashMap
/*let list = messages_list.lock().unwrap(); let list = messages_list.lock().unwrap();
let eventtype = list.get(&id); // Clone the enum so we can release the lock if needed let eventtype = list.get(&id); // Clone the enum so we can release the lock if needed
match eventtype { match eventtype {
@@ -143,191 +118,5 @@ pub fn handle_recevied_message(
} }
print!("Message not found for ID: {}", id) print!("Message not found for ID: {}", id)
} }
}*/
}
pub fn parse_message(
received_message: Vec<u8>,
id: i32,
crypto_pair: &CryptographicSignature,
cmd_tx: crossbeam_channel::Sender<NetworkEvent>,
ip: SocketAddr,
) -> Option<Vec<u8>> {
let cmd_tx_clone = cmd_tx.clone();
let id_bytes: [u8; 4] = received_message[0..ID]
.try_into()
.expect("Taille incorrecte");
let msgtype = received_message[ID];
let length_bytes: [u8; 2] = received_message[TYPE..LENGTH]
.try_into()
.expect("Taille incorrecte");
let msg_length = u16::from_be_bytes(length_bytes) as usize;
// verify signature
match msgtype {
HELLO | HELLOREPLY | ROOTREPLY | NODATUM | NATTRAVERSALREQUEST | NATTRAVERSALREQUEST2 => {
let ilength = u16::from_be_bytes(length_bytes);
println!("name received length: {}", ilength);
let received_name = &received_message[LENGTH + EXTENSIONS..LENGTH + ilength as usize];
let received_username = String::from_utf8(received_name.to_vec());
match received_username {
Ok(username) => {
let peer_pubkey = tokio::runtime::Runtime::new()
.unwrap()
.block_on(get_peer_key(&username))
.expect("failed to retrieve public key");
let signature: [u8; SIGNATURE] = received_message
[LENGTH + msg_length..LENGTH + msg_length + SIGNATURE]
.try_into()
.expect("Taille incorrecte");
if !verify_signature(peer_pubkey, &received_message) {
println!(
"incorrect signature from given peer: {}, ignoring message of type {} with id {}",
&username, received_message[ID], id
);
return None;
}
}
Err(e) => {
println!("incorrect name: {}", e);
return None;
}
}
}
_ => {}
} }
// Message handling
let mut constructed_message: Option<Vec<u8>> = None;
match msgtype {
// PING
//
// envoie un OK
PING => {
constructed_message = construct_message(OK, Vec::new(), id, crypto_pair);
}
//
// OK
//
// rien ?
// si NATTRAVERSALREQUEST alors
//
// ERROR
//
// affiche un msg d'erreur
ERROR => {
if let Ok(err_received) =
String::from_utf8(received_message[LENGTH..(msg_length + LENGTH)].to_vec())
{
let err_msg = format!("Error received from peer {} : {}", ip, err_received);
let _ = cmd_tx_clone.send(NetworkEvent::Error(err_msg));
} else {
let err_msg = format!("Error received from peer {} : N/A", ip,);
let _ = cmd_tx_clone.send(NetworkEvent::Error(err_msg));
}
}
// HELLO
//
// envoie une hello reply
//
HELLO => {
let mut payload = Vec::new();
payload.extend_from_slice(&0u32.to_be_bytes());
payload.extend_from_slice(&crypto_pair.username.clone().as_bytes());
let helloreply = construct_message(HELLOREPLY, payload, id, crypto_pair);
return helloreply;
}
// HELLOREPLY
//
//
// ajoute a la liste des peers handshake
HELLOREPLY => {}
//
// ROOTREQUEST
//
// envoie un root reply
//
// ROOTREPLY
//
// envoie un datum request
//
// DATUMREQUEST
//
// envoie le datum
//
// NODATUM
//
// affiche un msg d'erreur
//
// DATUM
//
// parcourt le directory recu ou le big directory et renvoie une DATUMREQUEST pour chaque
// directory ou big directory lu
//
// NATTRAVERSALREQUEST
//
// repond OK et envoie un NATTRAVERSALREQUEST2 au pair B
//
// NATTRAVERSALREQUEST2
//
// envoie OK à S puis envoie un ping à S
// PING
//
// envoie un OK
//
// OK
//
// si NATTRAVERSALREQUEST alors
//
// ERROR
//
// affiche un msg d'erreur
//
// HELLO
//
// envoie une hello reply
//
// HELLOREPLY
//
// envoie un root request
//
// ROOTREQUEST
//
// envoie un root reply
//
// ROOTREPLY
//
// envoie un datum request
//
// DATUMREQUEST
//
// envoie le datum
//
// NODATUM
//
// affiche un msg d'erreur
//
// DATUM
//
// parcourt le directory recu ou le big directory et renvoie une DATUMREQUEST pour chaque
// directory ou big directory lu
//
// NATTRAVERSALREQUEST
//
// repond OK et envoie un NATTRAVERSALREQUEST2 au pair B
//
// NATTRAVERSALREQUEST2
//
// envoie OK à S puis envoie un ping à S
_ => return None,
}
constructed_message
} }

View File

@@ -253,11 +253,7 @@ impl MultipleSenders {
}); });
}*/ }*/
pub fn start_receving_thread( pub fn start_receving_thread(shared_data: &P2PSharedData, socket_addr: SocketAddr) {
shared_data: &P2PSharedData,
socket_addr: SocketAddr,
cmd_tx: crossbeam_channel::Sender<NetworkEvent>,
) {
let sock_clone = shared_data.socket(); let sock_clone = shared_data.socket();
let cryptopair_clone = shared_data.cryptopair(); let cryptopair_clone = shared_data.cryptopair();
let senders_clone = shared_data.senders(); let senders_clone = shared_data.senders();
@@ -278,8 +274,6 @@ pub fn start_receving_thread(
&socket_addr, &socket_addr,
&senders_clone, &senders_clone,
&servername_clone, &servername_clone,
cmd_tx.clone(),
src,
); );
} }
Err(e) => eprintln!("Erreur de réception: {}", e), Err(e) => eprintln!("Erreur de réception: {}", e),

View File

@@ -1,73 +1,3 @@
use crate::{
cryptographic_signature::{CryptographicSignature, sign_message},
server_communication::generate_id,
};
const ID: usize = 4;
const TYPE: usize = 5;
const LENGTH: usize = 7;
const EXTENSIONS: usize = 4;
const SIGNATURE: usize = 64;
const PING: u8 = 0;
const OK: u8 = 128;
const ERROR: u8 = 129;
const HELLO: u8 = 1;
const HELLOREPLY: u8 = 130;
const ROOTREQUEST: u8 = 2;
const ROOTREPLY: u8 = 131;
const DATUMREQUEST: u8 = 3;
const NODATUM: u8 = 133;
const DATUM: u8 = 132;
const NATTRAVERSALREQUEST: u8 = 4;
const NATTRAVERSALREQUEST2: u8 = 5;
pub fn construct_message(
msgtype: u8,
payload: Vec<u8>,
id: i32,
crypto_pair: &CryptographicSignature,
) -> Option<Vec<u8>> {
let mut message = Vec::new();
// ID
// type
message.extend_from_slice(&id.to_be_bytes());
message.push(msgtype);
match msgtype {
HELLO | HELLOREPLY => {
// length
let a = payload.len() as u16;
println!("payload size:{}", a);
message.extend_from_slice(&a.to_be_bytes());
message.extend_from_slice(&payload);
let signature = sign_message(crypto_pair, &message);
return Some(signature);
}
PING | OK => {
message.extend_from_slice(&0u16.to_be_bytes());
return Some(message);
}
ERROR | ROOTREQUEST | DATUMREQUEST => {
message.extend_from_slice(&payload.len().to_be_bytes());
message.extend_from_slice(&payload);
return Some(message);
}
ROOTREPLY | NODATUM | DATUM | NATTRAVERSALREQUEST => {
message.extend_from_slice(&payload.len().to_be_bytes());
message.extend_from_slice(&payload);
let signature = sign_message(crypto_pair, &message);
message.extend_from_slice(&signature);
return Some(message);
}
_ => {}
}
None
}
pub struct UDPMessage { pub struct UDPMessage {
id: u32, id: u32,
msg_type: u8, msg_type: u8,

View File

@@ -1,83 +0,0 @@
// this class consists of a thread that will re send pings every time the first element
// of the stack is at the correct unix time
use std::{
collections::{HashMap, VecDeque},
net::{AddrParseError, SocketAddr},
ops::Add,
process::Command,
sync::{Arc, Mutex},
thread,
time::{self, Duration, SystemTime},
};
pub struct PeerInfo {
username: String,
ip: SocketAddr,
}
pub struct HandshakeHistory {
time_k_ip_v: HashMap<u64, u64>,
ip_k_peerinfo_v: HashMap<u64, PeerInfo>,
}
impl HandshakeHistory {
pub fn new() -> HandshakeHistory {
HandshakeHistory {
time_k_ip_v: HashMap::new(),
ip_k_peerinfo_v: HashMap::new(),
}
}
pub fn update_handshake(&mut self) {
thread::spawn(move || {
let mut times_to_check = VecDeque::new();
let current_time: u64 = SystemTime::now()
.duration_since(time::UNIX_EPOCH)
.expect("system time before UNIX EPOCH")
.add(Duration::from_secs(10))
.as_secs();
// adds 10 seconds in the queue every 10 seconds
loop {
let mut child = Command::new("sleep").arg("9").spawn().unwrap();
let _result = child.wait().unwrap();
for n in 0..9 {
// push 9 successive seconds
times_to_check.push_back(current_time + n);
// gestion d'erreur si verrou mort
}
}
});
}
pub fn add_new_handshake(&mut self, hash: u64, username: String, ip: SocketAddr) {
let current_time: u64 = SystemTime::now()
.duration_since(time::UNIX_EPOCH)
.expect("system time before UNIX EPOCH")
.as_secs();
println!("time:{}", current_time);
/*self.time_k_hash_v.insert(current_time, hash);
self.hash_k_peerinfo_v
.insert(hash, PeerInfo { username, ip });*/
}
}
#[cfg(test)]
mod tests {
use std::net::{IpAddr, Ipv4Addr};
use super::*;
///
/// creates a cryptographic signature
///
#[test]
fn creating_cryptographic_signature() {
let mut hh = HandshakeHistory::new();
hh.add_new_handshake(
20,
"putain".to_string(),
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 1),
);
}
}

View File

@@ -4,7 +4,7 @@ use getrandom::Error;
use crate::cryptographic_signature::{CryptographicSignature, formatPubKey, sign_message}; use crate::cryptographic_signature::{CryptographicSignature, formatPubKey, sign_message};
use crate::message_handling::EventType; use crate::message_handling::EventType;
use crate::messages_channels::{Message, MultipleSenders}; use crate::messages_channels::{Message, MultipleSenders};
use crate::messages_structure::construct_message; use crate::messages_structure::{HandshakeMessage, UDPMessage};
use std::collections::HashMap; use std::collections::HashMap;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::net::UdpSocket; use std::net::UdpSocket;
@@ -73,17 +73,17 @@ pub fn register_ip_addresses(
messages_list: &Mutex<HashMap<i32, EventType>>, messages_list: &Mutex<HashMap<i32, EventType>>,
id: i32, id: i32,
) { ) {
let mut payload = Vec::new(); let username_size = crypto_pair.username.len();
payload.extend_from_slice(&0u32.to_be_bytes()); let hello_handshake = HandshakeMessage::hello(
payload.extend_from_slice(&crypto_pair.username.clone().as_bytes()); id as u32,
let hello_handshake = construct_message(1, payload, id, crypto_pair); username_size as u16 + 4,
match hello_handshake { crypto_pair.username.clone(),
Some(handshake_message) => { );
senders.send_via(0, handshake_message, server_uri, false); //HandshakeMessage::display(&hello_handshake);
} let hello_handshake_serialized = hello_handshake.serialize();
None => {} let message_signed = sign_message(crypto_pair, &hello_handshake_serialized);
} senders.send_via(0, message_signed, server_uri, false);
/*let mut list = messages_list.lock().expect("Failed to lock messages_list"); let mut list = messages_list.lock().expect("Failed to lock messages_list");
match list.get(&id) { match list.get(&id) {
Some(_) => { Some(_) => {
list.remove(&id); list.remove(&id);
@@ -92,13 +92,12 @@ pub fn register_ip_addresses(
list.insert(id, EventType::ServerHelloReply); list.insert(id, EventType::ServerHelloReply);
} }
} }
println!("message sent: {}", &id);*/ println!("message sent: {}", &id);
// 3. Perform the insertion // 3. Perform the insertion
/*let mut buf = [0u8; 1024]; /*let mut buf = [0u8; 1024];
socket.recv_from(&mut buf).expect("receive failed"); socket.recv_from(&mut buf).expect("receive failed");
let hello_handshake_received = UDPMessage::parse(buf.to_vec()); let hello_handshake_received = UDPMessage::parse(buf.to_vec());
hello_handshake_received.display();*/ hello_handshake_received.display();*/
//TODO
} }
#[cfg(test)] #[cfg(test)]

36
todo.md
View File

@@ -2,12 +2,6 @@
## peer discovery ## peer discovery
## handshake
# Todo
## peer discovery
- get rsquest to the uri /peers/ - get rsquest to the uri /peers/
## registration with the server ## registration with the server
@@ -21,7 +15,6 @@
## handshake ## handshake
- handshake structure OK - handshake structure OK
- 5min timeout after handshake - 5min timeout after handshake
- matain connection every 4 min - matain connection every 4 min
@@ -34,8 +27,6 @@
- setting in gui to act as a relay - setting in gui to act as a relay
- chunk, directory, big, bigdirectory structures - chunk, directory, big, bigdirectory structures
## fonctionnalités application
## nat traversal ## nat traversal
- make hello and helloreply messages set the first extension bit to announce that peer is available for nat traversal - make hello and helloreply messages set the first extension bit to announce that peer is available for nat traversal
@@ -45,29 +36,12 @@
fonctionnalités : fonctionnalités :
s'enregistrer avec le serveur OK
rechercher un pair
generer une clé publique OK
rechercher les fichiers d'un pair rechercher les fichiers d'un pair
telechargement des fichiers telechargement des fichiers
choisir un dossier à partager choisir un dossier à partager
choisir le nombre de canaux se deconnecter du réseau
handshake server DOING 2 channels -> un pour envoyer et un pour recevoir OK
se deconnecter du réseau DOING
## autre
socket ipv6
# FAIT
- choisir un pseudo OK
- get rsquest to the uri /peers/ OK
- generation of the cryptographic key OK
- put request to the uri (check if the peer is already connected) OK
- get request to the uri /peers/key to get the public key of a peer OK
- get request to the uri /peers/key/addresses OK
- udp handshakes OK
- handshake structure OK
- s'enregistrer avec le serveur OK
- generer une clé publique OK
- verifier signature OK
- 2 channels -> un pour envoyer et un pour recevoir OK