|
|
|
@ -4,6 +4,7 @@ use crate::crypto::{Keys, PublicKey};
|
|
|
|
|
use crate::res::IFResult; |
|
|
|
|
use crate::tunnel::TunnelPublic; |
|
|
|
|
use serde::{Serialize, Deserialize}; |
|
|
|
|
use sha2::Digest; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// A serialized message
|
|
|
|
@ -28,7 +29,7 @@ pub enum Signature {
|
|
|
|
|
|
|
|
|
|
/// Network name and version
|
|
|
|
|
#[derive(Serialize, Deserialize, Clone)] |
|
|
|
|
struct NetworkInfo { |
|
|
|
|
pub struct NetworkInfo { |
|
|
|
|
network_name: String, |
|
|
|
|
version: String, |
|
|
|
|
} |
|
|
|
@ -46,6 +47,16 @@ pub enum MessageType {
|
|
|
|
|
Service(ServiceMessageType), |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl MessageType { |
|
|
|
|
fn hash(&self) -> Vec<u8> { |
|
|
|
|
match self { |
|
|
|
|
MessageType::SingleCast => Vec::from([0]), |
|
|
|
|
MessageType::Broadcast => Vec::from([1]), |
|
|
|
|
MessageType::Service(ServiceMessageType::TunnelBuilding(tunnel)) => [2, 0].iter().chain(tunnel.hash().iter()).copied().collect() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Clone)] |
|
|
|
|
pub enum ServiceMessageType { |
|
|
|
|
TunnelBuilding(TunnelPublic) |
|
|
|
@ -61,6 +72,22 @@ pub enum MessageContent {
|
|
|
|
|
None, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl MessageContent { |
|
|
|
|
pub fn hash(&self) -> Vec<u8> { |
|
|
|
|
match self { |
|
|
|
|
MessageContent::Plain(v) => sha2::Sha512::new() |
|
|
|
|
.chain(&[0u8; 1]) |
|
|
|
|
.chain(v.as_slice()) |
|
|
|
|
.result().to_vec(), |
|
|
|
|
MessageContent::Encrypted(v) => sha2::Sha512::new() |
|
|
|
|
.chain(&[1; 1]) |
|
|
|
|
.chain(v.as_slice()) |
|
|
|
|
.result().to_vec(), |
|
|
|
|
MessageContent::None => Vec::new() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The struct for messages that are sent in the network
|
|
|
|
|
#[derive(Serialize, Deserialize, Clone)] |
|
|
|
|
pub struct Message { |
|
|
|
@ -100,8 +127,14 @@ impl Message {
|
|
|
|
|
todo!() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn calculate_hash(_content: &MessageContent, _message_type: MessageType, _sender_or_encrypted_sender: Option<Vec<u8>>) -> Vec<u8> { |
|
|
|
|
todo!() |
|
|
|
|
pub fn calculate_hash(content: &MessageContent, message_type: MessageType, sender_or_encrypted_sender: Option<Vec<u8>>, network_info: &NetworkInfo) -> Vec<u8> { |
|
|
|
|
sha2::Sha512::new() |
|
|
|
|
.chain(content.hash().as_slice()) |
|
|
|
|
.chain(message_type.hash().as_slice()) |
|
|
|
|
.chain(sender_or_encrypted_sender.unwrap_or_default().as_slice()) |
|
|
|
|
.chain(network_info.network_name.as_bytes()) |
|
|
|
|
.chain(network_info.version.as_bytes()) |
|
|
|
|
.result().to_vec() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Encrypt hash of the message for the recipient
|
|
|
|
@ -171,6 +204,7 @@ impl MessageBuilder {
|
|
|
|
|
let sender_encrypted = if let (Some(sender_keys), Some(recipient)) = (self.sender.as_ref(), self.recipient.as_ref()) { |
|
|
|
|
Some(recipient.encrypt_data(&sender_keys.get_public().to_vec()?)?) |
|
|
|
|
} else { None }; |
|
|
|
|
let network_info = NetworkInfo::default(); |
|
|
|
|
let hash = Message::calculate_hash( |
|
|
|
|
&self.content, |
|
|
|
|
self.message_type.clone().unwrap(), |
|
|
|
@ -179,6 +213,7 @@ impl MessageBuilder {
|
|
|
|
|
|| self.sender.as_ref() |
|
|
|
|
.map(|sender_keys| sender_keys.get_public().to_vec().unwrap()) |
|
|
|
|
), |
|
|
|
|
&network_info |
|
|
|
|
); |
|
|
|
|
let recipient_verification = self.recipient.as_ref().map(|rec| rec.encrypt_data(&hash).unwrap()); |
|
|
|
|
let signature = match (self.sender, self.recipient) { |
|
|
|
@ -197,7 +232,31 @@ impl MessageBuilder {
|
|
|
|
|
hash, |
|
|
|
|
recipient_verification, |
|
|
|
|
tunnel_id: self.tunnel_id, |
|
|
|
|
network_info: Default::default(), |
|
|
|
|
network_info, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(test)] |
|
|
|
|
use alloc::vec; |
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
|
fn test_hashing_message_type() { |
|
|
|
|
let msg_type_1 = MessageType::Broadcast; |
|
|
|
|
let msg_type_2 = MessageType::Service(ServiceMessageType::TunnelBuilding(TunnelPublic::new_for_test())); |
|
|
|
|
assert_eq!(msg_type_1.hash(), msg_type_1.hash()); |
|
|
|
|
assert_eq!(msg_type_2.hash(), msg_type_2.hash()); |
|
|
|
|
assert_ne!(msg_type_1.hash(), msg_type_2.hash()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
|
fn test_hash_message_content() { |
|
|
|
|
let content_1 = MessageContent::Plain(vec![1, 2, 4, 5]); |
|
|
|
|
let content_2 = MessageContent::Encrypted(vec![1, 2, 4, 5]); |
|
|
|
|
let content_3 = MessageContent::Plain(vec![1, 3, 4, 5]); |
|
|
|
|
assert_eq!(content_1.hash(), content_1.hash()); |
|
|
|
|
assert_ne!(content_1.hash(), MessageContent::None.hash()); |
|
|
|
|
assert_ne!(content_1.hash(), content_2.hash()); |
|
|
|
|
assert_ne!(content_1.hash(), content_3.hash()); |
|
|
|
|
assert_ne!(content_3.hash(), content_2.hash()); |
|
|
|
|
} |
|
|
|
|