|
|
@ -57,11 +57,16 @@ pub enum MessageContent { |
|
|
|
Plain(Vec<u8>), |
|
|
|
Plain(Vec<u8>), |
|
|
|
/// Message content bytes encrypted for the recipient
|
|
|
|
/// Message content bytes encrypted for the recipient
|
|
|
|
Encrypted(Vec<u8>), |
|
|
|
Encrypted(Vec<u8>), |
|
|
|
|
|
|
|
/// There is no content
|
|
|
|
|
|
|
|
None, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// The struct for messages that are sent in the network
|
|
|
|
#[derive(Serialize, Deserialize, Clone)] |
|
|
|
#[derive(Serialize, Deserialize, Clone)] |
|
|
|
pub struct Message { |
|
|
|
pub struct Message { |
|
|
|
/// Content of the message (not to be confused with the bytes that we are sending through interfaces)
|
|
|
|
/// Content of the message (not to be confused with the bytes that we are sending through interfaces)
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// AKA useful payload
|
|
|
|
pub content: MessageContent, |
|
|
|
pub content: MessageContent, |
|
|
|
/// The type of this message
|
|
|
|
/// The type of this message
|
|
|
|
pub message_type: MessageType, |
|
|
|
pub message_type: MessageType, |
|
|
@ -95,7 +100,104 @@ impl Message { |
|
|
|
todo!() |
|
|
|
todo!() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn calculate_hash(_content: MessageContent, _message_type: MessageType, _sender: Option<PublicKey>) -> Vec<u8> { |
|
|
|
pub fn calculate_hash(_content: &MessageContent, _message_type: MessageType, _sender_or_encrypted_sender: Option<Vec<u8>>) -> Vec<u8> { |
|
|
|
todo!() |
|
|
|
todo!() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Encrypt hash of the message for the recipient
|
|
|
|
|
|
|
|
pub fn generate_recipient_verification(hash: Vec<u8>, recipient: PublicKey) -> rsa::errors::Result<Vec<u8>> { |
|
|
|
|
|
|
|
recipient.encrypt_data(&hash) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Message builder to create a new message step-by-step, like `Message::build().message_type(...).sign(...)`
|
|
|
|
|
|
|
|
pub struct MessageBuilder { |
|
|
|
|
|
|
|
content: MessageContent, |
|
|
|
|
|
|
|
/// The type of the message to be built
|
|
|
|
|
|
|
|
message_type: Option<MessageType>, |
|
|
|
|
|
|
|
/// Sender's keys
|
|
|
|
|
|
|
|
sender: Option<Keys>, |
|
|
|
|
|
|
|
/// Recipient's public key (if present, the content will be encrypted and recipient verification field will be set)
|
|
|
|
|
|
|
|
recipient: Option<PublicKey>, |
|
|
|
|
|
|
|
/// ID of the tunnel that is used
|
|
|
|
|
|
|
|
tunnel_id: u64, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl MessageBuilder { |
|
|
|
|
|
|
|
/// Create a new `MessageBuilder` with default parameters
|
|
|
|
|
|
|
|
pub fn new() -> Self { |
|
|
|
|
|
|
|
Self { |
|
|
|
|
|
|
|
content: MessageContent::None, |
|
|
|
|
|
|
|
message_type: None, |
|
|
|
|
|
|
|
sender: None, |
|
|
|
|
|
|
|
recipient: None, |
|
|
|
|
|
|
|
tunnel_id: 0, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn content(mut self, cont: Vec<u8>) -> Self { |
|
|
|
|
|
|
|
self.content = MessageContent::Plain(cont); |
|
|
|
|
|
|
|
self |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Sign the message
|
|
|
|
|
|
|
|
pub fn sign(mut self, keys: &Keys) -> Self { |
|
|
|
|
|
|
|
self.sender = Some(keys.clone()); |
|
|
|
|
|
|
|
self |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Set message's recipient (and therefore set recipient verification and encrypt the content)
|
|
|
|
|
|
|
|
pub fn recipient(mut self, recipient: PublicKey) -> Self { |
|
|
|
|
|
|
|
self.recipient = Some(recipient); |
|
|
|
|
|
|
|
self |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Set tunnel id
|
|
|
|
|
|
|
|
pub fn tunnel(mut self, tunnel_id: u64) -> Self { |
|
|
|
|
|
|
|
self.tunnel_id = tunnel_id; |
|
|
|
|
|
|
|
self |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Set message's type
|
|
|
|
|
|
|
|
pub fn message_type(mut self, message_type: MessageType) -> Self { |
|
|
|
|
|
|
|
self.message_type = Some(message_type); |
|
|
|
|
|
|
|
self |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Get the resulting message
|
|
|
|
|
|
|
|
pub fn build(self) -> IFResult<Message> { |
|
|
|
|
|
|
|
let salt = rand::random(); |
|
|
|
|
|
|
|
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 hash = Message::calculate_hash( |
|
|
|
|
|
|
|
&self.content, |
|
|
|
|
|
|
|
self.message_type.clone().unwrap(), |
|
|
|
|
|
|
|
sender_encrypted.clone() |
|
|
|
|
|
|
|
.or_else( |
|
|
|
|
|
|
|
|| self.sender.as_ref() |
|
|
|
|
|
|
|
.map(|sender_keys| sender_keys.get_public().to_vec().unwrap()) |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
let recipient_verification = self.recipient.as_ref().map(|rec| rec.encrypt_data(&hash).unwrap()); |
|
|
|
|
|
|
|
let signature = match (self.sender, self.recipient) { |
|
|
|
|
|
|
|
(Some(sender_keys), Some(recipient_key)) => Signature::SignedPrivately { |
|
|
|
|
|
|
|
sender_encrypted: sender_encrypted.unwrap(), |
|
|
|
|
|
|
|
signature: recipient_key.encrypt_data(&sender_keys.sign(&hash)?)?, |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
(Some(sender_keys), None) => Signature::Signed { sender: sender_keys.get_public(), signature: sender_keys.sign(&hash)? }, |
|
|
|
|
|
|
|
(None, _) => Signature::NotSigned, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
Ok(Message { |
|
|
|
|
|
|
|
content: self.content, |
|
|
|
|
|
|
|
message_type: self.message_type.unwrap(), |
|
|
|
|
|
|
|
signature, |
|
|
|
|
|
|
|
salt, |
|
|
|
|
|
|
|
hash, |
|
|
|
|
|
|
|
recipient_verification, |
|
|
|
|
|
|
|
tunnel_id: self.tunnel_id, |
|
|
|
|
|
|
|
network_info: Default::default(), |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|