Browse Source

Cryptography in message (signing, checks), new serialization for PublicKey

interface-2
Lev 3 years ago
parent
commit
2b6e2b46ad
  1. 35
      examples/test_ip_connection.rs
  2. 65
      src/crypto.rs
  3. 17
      src/interface.rs
  4. 31
      src/ironforce.rs
  5. 184
      src/message.rs

35
examples/test_ip_connection.rs

@ -1,11 +1,17 @@
use std::net; #[cfg(feature = "std")]
use ironforce::interfaces::ip::IPInterface;
use ironforce::interface::Interface; use ironforce::interface::Interface;
#[cfg(feature = "std")]
use ironforce::interfaces::ip::IPInterface;
#[cfg(feature = "std")]
use std::net;
#[cfg(feature = "std")]
fn main() { fn main() {
let mut listener = match net::TcpListener::bind("0.0.0.0:60000") { let mut listener = match net::TcpListener::bind("0.0.0.0:60000") {
Ok(tmp) => tmp, Ok(tmp) => tmp,
Err(_) => { return; } Err(_) => {
return;
}
}; };
let mut interface1 = IPInterface { let mut interface1 = IPInterface {
id: String::from("IP interface"), id: String::from("IP interface"),
@ -14,9 +20,11 @@ fn main() {
}; };
let option_listener = net::TcpListener::bind("0.0.0.0:50000"); let option_listener = net::TcpListener::bind("0.0.0.0:50000");
let mut listener= match option_listener { let mut listener = match option_listener {
Ok(tmp) => tmp, Ok(tmp) => tmp,
Err(_) => { return; } Err(_) => {
return;
}
}; };
let mut interface2 = IPInterface { let mut interface2 = IPInterface {
id: String::from("IP interface"), id: String::from("IP interface"),
@ -24,17 +32,26 @@ fn main() {
listener, listener,
}; };
let t1 = std::thread::spawn(move || { interface1.send(&[0,0,1,1], Some(String::from("0.0.0.0:50000"))); interface1}); let t1 = std::thread::spawn(move || {
let t2 = std::thread::spawn(move || { interface2.main_loop_iteration(); interface2}); interface1.send(&[0, 0, 1, 1], Some(String::from("0.0.0.0:50000")));
interface1
});
let t2 = std::thread::spawn(move || {
interface2.main_loop_iteration();
interface2
});
let res1 = t1.join(); let res1 = t1.join();
match res1 { match res1 {
Ok(_) => println!("Ok"), Ok(_) => println!("Ok"),
Err(e) => println!("{:?}", e) Err(e) => println!("{:?}", e),
} }
let res2 = t2.join(); let res2 = t2.join();
match res2 { match res2 {
Ok(_) => println!("Ok"), Ok(_) => println!("Ok"),
Err(e) => println!("{:?}", e) Err(e) => println!("{:?}", e),
} }
// res1.unwrap(); // res1.unwrap();
} }
#[cfg(not(feature = "std"))]
fn main() {}

65
src/crypto.rs

@ -1,12 +1,18 @@
/// This module has wrappers for cryptography with RSA algorithms. /// This module has wrappers for cryptography with RSA algorithms.
/// Its main structs - `PublicKey` and `Keys` implement all functions for key generation, signatures and asymmetric encryption /// Its main structs - `PublicKey` and `Keys` implement all functions for key generation, signatures and asymmetric encryption
use alloc::vec::Vec; use alloc::vec::Vec;
use alloc::string::String;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use rsa::{RsaPublicKey, RsaPrivateKey, PaddingScheme, PublicKey as RPK}; use rsa::{RsaPublicKey, RsaPrivateKey, PaddingScheme, PublicKey as RPK, PublicKeyParts, BigUint};
use rsa::errors::Result as RsaRes; use rsa::errors::Result as RsaRes;
use rand::rngs::OsRng; use rand::rngs::OsRng;
use sha2::{Digest, Sha224};
use alloc::vec;
use crate::res::{IFError, IFResult};
static KEY_LENGTH: usize = 2048; static KEY_LENGTH: usize = 2048;
static ENCRYPTION_CHUNK_SIZE: usize = 240;
static ENCRYPTION_OUTPUT_CHUNK_SIZE: usize = 256;
/// Public key of a node /// Public key of a node
@ -18,26 +24,50 @@ pub struct PublicKey {
impl PublicKey { impl PublicKey {
/// Check if the sign is valid for given data and key /// Check if the sign is valid for given data and key
pub fn verify_sign(&self, data: &[u8], sign: &[u8]) -> bool { pub fn verify_sign(&self, data: &[u8], sign: &[u8]) -> bool {
self.key.verify(PaddingScheme::PKCS1v15Sign { hash: None }, data, sign).is_ok() self.key.verify(PaddingScheme::PKCS1v15Sign { hash: None }, &Sha224::new().chain(data).result().to_vec(), sign).is_ok()
} }
/// Encrypt some data for a user with this public key /// Encrypt some data for a user with this public key
pub fn encrypt_data(&self, data: &[u8]) -> RsaRes<Vec<u8>> { pub fn encrypt_data(&self, data: &[u8]) -> RsaRes<Vec<u8>> {
if data.len() <= ENCRYPTION_CHUNK_SIZE {
self.key.encrypt(&mut OsRng {}, PaddingScheme::PKCS1v15Encrypt, data) self.key.encrypt(&mut OsRng {}, PaddingScheme::PKCS1v15Encrypt, data)
} else {
let mut res = self.key.encrypt(&mut OsRng {}, PaddingScheme::PKCS1v15Encrypt, &data[..ENCRYPTION_CHUNK_SIZE])?;
res.extend(self.encrypt_data(&data[ENCRYPTION_CHUNK_SIZE..])?);
Ok(res)
}
} }
pub fn to_vec(&self) -> serde_cbor::Result<Vec<u8>> { pub fn to_vec(&self) -> Vec<u8> {
serde_cbor::to_vec(&self.key) let n_bytes = self.key.n().to_bytes_be();
let e_bytes = self.key.e().to_bytes_be();
let mut res = vec![
(n_bytes.len() / 256) as u8, (n_bytes.len() % 256) as u8,
(e_bytes.len() / 256) as u8, (e_bytes.len() % 256) as u8,
];
res.extend(n_bytes);
res.extend(e_bytes);
res
} }
pub fn from_vec(data: Vec<u8>) -> serde_cbor::Result<Self> { pub fn from_vec(data: Vec<u8>) -> IFResult<Self> {
serde_cbor::from_slice(data.as_slice()) if data.len() < 4 {
return Err(IFError::SerializationError(String::from("Not enough bytes in serialized PublicKey")))
}
let n_len = data[0] as usize * 256 + data[1] as usize;
let e_len = data[2] as usize * 256 + data[3] as usize;
if data.len() != e_len + n_len + 4 {
return Err(IFError::SerializationError(String::from("Not enough bytes in serialized PublicKey")))
}
let n_bytes = &data[4..n_len + 4];
let e_bytes = &data[4 + n_len..e_len + n_len + 4];
Ok(Self { key: RsaPublicKey::new(BigUint::from_bytes_be(n_bytes), BigUint::from_bytes_be(e_bytes))? })
} }
} }
impl PublicKey { impl PublicKey {
fn hash(&self) -> Vec<u8> { fn hash(&self) -> Vec<u8> {
self.to_vec().unwrap() self.to_vec()
} }
} }
@ -64,12 +94,18 @@ impl Keys {
impl Keys { impl Keys {
/// Sign content using these keys /// Sign content using these keys
pub fn sign(&self, content: &[u8]) -> RsaRes<Vec<u8>> { pub fn sign(&self, content: &[u8]) -> RsaRes<Vec<u8>> {
self.private_key.sign(PaddingScheme::PKCS1v15Sign { hash: None }, content) self.private_key.sign(PaddingScheme::PKCS1v15Sign { hash: None }, &Sha224::new().chain(content).result().to_vec())
} }
/// Decrypt data /// Decrypt data
pub fn decrypt_data(&self, data_encrypted: &[u8]) -> RsaRes<Vec<u8>> { pub fn decrypt_data(&self, data_encrypted: &[u8]) -> RsaRes<Vec<u8>> {
if data_encrypted.len() <= ENCRYPTION_OUTPUT_CHUNK_SIZE {
self.private_key.decrypt(PaddingScheme::PKCS1v15Encrypt, data_encrypted) self.private_key.decrypt(PaddingScheme::PKCS1v15Encrypt, data_encrypted)
} else {
let mut res = self.private_key.decrypt(PaddingScheme::PKCS1v15Encrypt, &data_encrypted[..ENCRYPTION_OUTPUT_CHUNK_SIZE])?;
res.extend(self.decrypt_data(&data_encrypted[ENCRYPTION_OUTPUT_CHUNK_SIZE..])?);
Ok(res)
}
} }
/// Get public key /// Get public key
@ -80,17 +116,19 @@ impl Keys {
#[test] #[test]
fn test_encrypt() { fn test_encrypt() {
let data = vec![0, 5, 8, 135, 67]; let data = vec![0, 5, 8, 135, 67, 45, 32, 5];
let keys = Keys::generate(); let keys = Keys::generate();
let data_encrypted = keys.get_public().encrypt_data(&data).unwrap();
assert_eq!( assert_eq!(
keys.decrypt_data(&keys.get_public().encrypt_data(&data).unwrap()).unwrap(), keys.decrypt_data(&data_encrypted).unwrap(),
data data
); );
assert_eq!(
keys.decrypt_data(&keys.get_public().encrypt_data(&data.repeat(300)).unwrap()).unwrap(),
data.repeat(300)
);
} }
#[cfg(test)]
use alloc::vec;
#[test] #[test]
fn test_invalid_encrypt() { fn test_invalid_encrypt() {
let data = vec![0, 5, 8, 135, 67]; let data = vec![0, 5, 8, 135, 67];
@ -104,6 +142,7 @@ fn test_signing() {
let data = vec![0, 5, 8, 135, 67]; let data = vec![0, 5, 8, 135, 67];
let keys = Keys::generate(); let keys = Keys::generate();
assert!(keys.get_public().verify_sign(&data, &keys.sign(&data).unwrap())); assert!(keys.get_public().verify_sign(&data, &keys.sign(&data).unwrap()));
assert!(keys.get_public().verify_sign(&data.repeat(340), &keys.sign(&data.repeat(340)).unwrap()));
} }
#[test] #[test]

17
src/interface.rs

@ -1,7 +1,6 @@
use alloc::string::String;
use crate::message::MessageBytes; use crate::message::MessageBytes;
use crate::res::IFResult; use crate::res::IFResult;
use alloc::string::String;
/// Some data that can be provided to the interface to send the message to a target. /// Some data that can be provided to the interface to send the message to a target.
/// ///
@ -16,7 +15,6 @@ pub trait InterfaceRequirements {}
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub trait InterfaceRequirements: Send + Sync {} pub trait InterfaceRequirements: Send + Sync {}
/// An interface that can be used to /// An interface that can be used to
pub trait Interface: InterfaceRequirements { pub trait Interface: InterfaceRequirements {
/// Run one main loop iteration. /// Run one main loop iteration.
@ -34,7 +32,11 @@ pub trait Interface: InterfaceRequirements {
fn id(&self) -> &str; fn id(&self) -> &str;
/// Send a message. If no `interface_data` is provided, we should consider it to be a broadcast. /// Send a message. If no `interface_data` is provided, we should consider it to be a broadcast.
/// If, on the other hand, `interface_data` is not `None`, it should be used to send the message to the target. /// If, on the other hand, `interface_data` is not `None`, it should be used to send the message to the target.
fn send(&mut self, message: &[u8] /*MessageBytes*/, interface_data: Option<TargetingData>) -> IFResult<()>; fn send(
&mut self,
message: &[u8], /*MessageBytes*/
interface_data: Option<TargetingData>,
) -> IFResult<()>;
/// Receive a message through this interface. Returns a result with an option of (message bytes, target). /// Receive a message through this interface. Returns a result with an option of (message bytes, target).
/// `None` means there is no message available at the time. /// `None` means there is no message available at the time.
/// The implementations of this function shouldn't wait for new messages, but /// The implementations of this function shouldn't wait for new messages, but
@ -65,14 +67,13 @@ pub mod test_interface {
} }
fn send(&mut self, message: &[u8], interface_data: Option<TargetingData>) -> IFResult<()> { fn send(&mut self, message: &[u8], interface_data: Option<TargetingData>) -> IFResult<()> {
self.messages.push((Vec::from(message), interface_data.unwrap_or_default())); self.messages
.push((Vec::from(message), interface_data.unwrap_or_default()));
Ok(()) Ok(())
} }
fn receive(&mut self) -> IFResult<Option<(MessageBytes, TargetingData)>> { fn receive(&mut self) -> IFResult<Option<(MessageBytes, TargetingData)>> {
Ok( Ok(self.messages.pop())
self.messages.pop()
)
} }
} }
} }

31
src/ironforce.rs

@ -1,11 +1,10 @@
use alloc::vec::Vec;
use alloc::vec;
use crate::crypto::PublicKey; use crate::crypto::PublicKey;
use crate::message::{Message, MessageType, ServiceMessageType}; use crate::message::{Message, MessageType, ServiceMessageType};
use crate::res::{IFError, IFResult}; use crate::res::{IFError, IFResult};
use crate::transport::Transport; use crate::transport::Transport;
use crate::tunnel::Tunnel; use crate::tunnel::Tunnel;
use alloc::vec;
use alloc::vec::Vec;
/// Main worker /// Main worker
pub struct IronForce { pub struct IronForce {
@ -43,16 +42,30 @@ impl IronForce {
} }
/// Send a message through tunnel /// Send a message through tunnel
fn send_through_tunnel(&mut self, _tunnel_id: u64, _message: Message, _direction: Option<bool>) -> IFResult<()> { fn send_through_tunnel(
&mut self,
_tunnel_id: u64,
_message: Message,
_direction: Option<bool>,
) -> IFResult<()> {
todo!() todo!()
} }
/// Send a message to another node, /// Send a message to another node,
/// creating a new tunnel if needed /// creating a new tunnel if needed
pub fn send_message(&mut self, message: Message, destination: PublicKey) -> IFResult<()> { pub fn send_message(&mut self, message: Message, destination: PublicKey) -> IFResult<()> {
if let Some(Some(tunnel_id)) = self.tunnels.iter() if let Some(Some(tunnel_id)) = self
.find(|t| t.target_node.as_ref() == Some(&destination) || t.nodes_in_tunnel.as_ref().map(|nodes| nodes.contains(&destination)) == Some(true)) .tunnels
.map(|tunnel| tunnel.id) { .iter()
.find(|t| {
t.target_node.as_ref() == Some(&destination)
|| t.nodes_in_tunnel
.as_ref()
.map(|nodes| nodes.contains(&destination))
== Some(true)
})
.map(|tunnel| tunnel.id)
{
self.send_through_tunnel(tunnel_id, message, None) self.send_through_tunnel(tunnel_id, message, None)
} else { } else {
Err(IFError::TunnelNotFound) Err(IFError::TunnelNotFound)
@ -67,8 +80,8 @@ impl IronForce {
ServiceMessageType::TunnelBuilding(_tunnel) => { ServiceMessageType::TunnelBuilding(_tunnel) => {
todo!() todo!()
} }
} },
MessageType::SingleCast | MessageType::Broadcast => { self.messages.push(message) } MessageType::SingleCast | MessageType::Broadcast => self.messages.push(message),
} }
} }

184
src/message.rs

@ -1,12 +1,11 @@
use alloc::string::String;
use alloc::vec::Vec;
use crate::crypto::{Keys, PublicKey}; use crate::crypto::{Keys, PublicKey};
use crate::res::IFResult; use crate::res::IFResult;
use crate::tunnel::TunnelPublic; use crate::tunnel::TunnelPublic;
use serde::{Serialize, Deserialize}; use alloc::string::String;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
use sha2::Digest; use sha2::Digest;
/// A serialized message /// A serialized message
pub(crate) type MessageBytes = Vec<u8>; pub(crate) type MessageBytes = Vec<u8>;
@ -27,6 +26,19 @@ pub enum Signature {
}, },
} }
impl Signature {
/// Get sender's key or its encrypted version for hashing
pub(crate) fn sender_or_encrypted_sender(&self) -> Option<Vec<u8>> {
match &self {
Signature::NotSigned => None,
Signature::Signed { sender, .. } => Some(sender.to_vec()),
Signature::SignedPrivately {
sender_encrypted, ..
} => Some(sender_encrypted.clone()),
}
}
}
/// Network name and version /// Network name and version
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone)]
pub struct NetworkInfo { pub struct NetworkInfo {
@ -36,7 +48,10 @@ pub struct NetworkInfo {
impl Default for NetworkInfo { impl Default for NetworkInfo {
fn default() -> Self { fn default() -> Self {
Self { version: String::from("0.1.0"), network_name: String::from("test") } Self {
version: String::from("0.1.0"),
network_name: String::from("test"),
}
} }
} }
@ -52,14 +67,16 @@ impl MessageType {
match self { match self {
MessageType::SingleCast => Vec::from([0]), MessageType::SingleCast => Vec::from([0]),
MessageType::Broadcast => Vec::from([1]), MessageType::Broadcast => Vec::from([1]),
MessageType::Service(ServiceMessageType::TunnelBuilding(tunnel)) => [2, 0].iter().chain(tunnel.hash().iter()).copied().collect() MessageType::Service(ServiceMessageType::TunnelBuilding(tunnel)) => {
[2, 0].iter().chain(tunnel.hash().iter()).copied().collect()
}
} }
} }
} }
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone)]
pub enum ServiceMessageType { pub enum ServiceMessageType {
TunnelBuilding(TunnelPublic) TunnelBuilding(TunnelPublic),
} }
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone)]
@ -78,12 +95,14 @@ impl MessageContent {
MessageContent::Plain(v) => sha2::Sha512::new() MessageContent::Plain(v) => sha2::Sha512::new()
.chain(&[0u8; 1]) .chain(&[0u8; 1])
.chain(v.as_slice()) .chain(v.as_slice())
.result().to_vec(), .result()
.to_vec(),
MessageContent::Encrypted(v) => sha2::Sha512::new() MessageContent::Encrypted(v) => sha2::Sha512::new()
.chain(&[1; 1]) .chain(&[1; 1])
.chain(v.as_slice()) .chain(v.as_slice())
.result().to_vec(), .result()
MessageContent::None => Vec::new() .to_vec(),
MessageContent::None => Vec::new(),
} }
} }
} }
@ -113,36 +132,106 @@ pub struct Message {
impl Message { impl Message {
/// Verify message's hash /// Verify message's hash
pub fn verify(&self) -> bool { pub fn verify_hash(&self) -> bool {
todo!() self.hash
== Self::calculate_hash(
&self.content,
self.message_type.clone(),
self.signature.sender_or_encrypted_sender(),
&self.network_info,
)
}
/// Verify sender's signature
pub fn verify_signature(&self, recipient_keys: Keys) -> bool {
match &self.signature {
Signature::NotSigned => true,
Signature::Signed { signature, sender } => {
sender.verify_sign(self.hash.as_slice(), signature.as_slice())
}
Signature::SignedPrivately { signature, .. } => {
if let Some(sender) = self.get_sender(&recipient_keys) {
sender.verify_sign(
self.hash.as_slice(),
&match recipient_keys.decrypt_data(signature.as_slice()) {
Ok(r) => r,
Err(_e) => return false,
},
)
} else {
false
}
}
}
} }
/// Check if this message is for this set of keys /// Check if this message is for this set of keys
pub fn check_recipient(&self, _keys: Keys) -> bool { pub fn check_recipient(&self, keys: Keys) -> bool {
todo!() keys.decrypt_data(&self.recipient_verification.clone().unwrap_or_default())
.is_ok()
} }
/// Get decrypted content of the message /// Get decrypted content of the message
pub fn get_decrypted(&self, _keys: Keys) -> IFResult<Vec<u8>> { pub fn get_decrypted(&self, keys: Keys) -> IFResult<Vec<u8>> {
todo!() Ok(match &self.content {
MessageContent::Plain(c) => c.clone(),
MessageContent::Encrypted(encrypted_content) => {
keys.decrypt_data(encrypted_content.as_slice())?
}
MessageContent::None => Vec::new(),
})
} }
pub fn calculate_hash(content: &MessageContent, message_type: MessageType, sender_or_encrypted_sender: Option<Vec<u8>>, network_info: &NetworkInfo) -> Vec<u8> { pub fn calculate_hash(
content: &MessageContent,
message_type: MessageType,
sender_or_encrypted_sender: Option<Vec<u8>>,
network_info: &NetworkInfo,
) -> Vec<u8> {
sha2::Sha512::new() sha2::Sha512::new()
.chain(content.hash().as_slice()) .chain(content.hash().as_slice())
.chain(message_type.hash().as_slice()) .chain(message_type.hash().as_slice())
.chain(sender_or_encrypted_sender.unwrap_or_default().as_slice()) .chain(sender_or_encrypted_sender.unwrap_or_default().as_slice())
.chain(network_info.network_name.as_bytes()) .chain(network_info.network_name.as_bytes())
.chain(network_info.version.as_bytes()) .chain(network_info.version.as_bytes())
.result().to_vec() .result()
.to_vec()
} }
/// Encrypt hash of the message for the recipient /// Encrypt hash of the message for the recipient
pub fn generate_recipient_verification(hash: Vec<u8>, recipient: PublicKey) -> rsa::errors::Result<Vec<u8>> { pub fn generate_recipient_verification(
hash: Vec<u8>,
recipient: PublicKey,
) -> rsa::errors::Result<Vec<u8>> {
recipient.encrypt_data(&hash) recipient.encrypt_data(&hash)
} }
}
/// Try to get sender from the signature
fn get_sender(&self, keys: &Keys) -> Option<PublicKey> {
match &self.signature {
Signature::NotSigned => None,
Signature::Signed { sender, .. } => Some(sender.clone()),
Signature::SignedPrivately {
sender_encrypted, ..
} => {
if let Some(Some(res)) = keys
.decrypt_data(sender_encrypted.as_slice())
.ok()
.map(|k| PublicKey::from_vec(k).ok())
{
Some(res)
} else {
None
}
}
}
}
/// Create new MessageBuilder
pub fn build() -> MessageBuilder {
MessageBuilder::new()
}
}
/// Message builder to create a new message step-by-step, like `Message::build().message_type(...).sign(...)` /// Message builder to create a new message step-by-step, like `Message::build().message_type(...).sign(...)`
pub struct MessageBuilder { pub struct MessageBuilder {
@ -201,27 +290,37 @@ impl MessageBuilder {
/// Get the resulting message /// Get the resulting message
pub fn build(self) -> IFResult<Message> { pub fn build(self) -> IFResult<Message> {
let salt = rand::random(); let salt = rand::random();
let sender_encrypted = if let (Some(sender_keys), Some(recipient)) = (self.sender.as_ref(), self.recipient.as_ref()) { let sender_encrypted = if let (Some(sender_keys), Some(recipient)) =
Some(recipient.encrypt_data(&sender_keys.get_public().to_vec()?)?) (self.sender.as_ref(), self.recipient.as_ref())
} else { None }; {
Some(recipient.encrypt_data(&sender_keys.get_public().to_vec())?)
} else {
None
};
let network_info = NetworkInfo::default(); let network_info = NetworkInfo::default();
let hash = Message::calculate_hash( let hash = Message::calculate_hash(
&self.content, &self.content,
self.message_type.clone().unwrap(), self.message_type.clone().unwrap(),
sender_encrypted.clone() sender_encrypted.clone().or_else(|| {
.or_else( self.sender
|| self.sender.as_ref() .as_ref()
.map(|sender_keys| sender_keys.get_public().to_vec().unwrap()) .map(|sender_keys| sender_keys.get_public().to_vec())
), }),
&network_info &network_info,
); );
let recipient_verification = self.recipient.as_ref().map(|rec| rec.encrypt_data(&hash).unwrap()); let recipient_verification = self
.recipient
.as_ref()
.map(|rec| rec.encrypt_data(&hash).unwrap());
let signature = match (self.sender, self.recipient) { let signature = match (self.sender, self.recipient) {
(Some(sender_keys), Some(recipient_key)) => Signature::SignedPrivately { (Some(sender_keys), Some(recipient_key)) => Signature::SignedPrivately {
sender_encrypted: sender_encrypted.unwrap(), sender_encrypted: sender_encrypted.unwrap(),
signature: recipient_key.encrypt_data(&sender_keys.sign(&hash)?)?, 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)? }, (Some(sender_keys), None) => Signature::Signed {
sender: sender_keys.get_public(),
signature: sender_keys.sign(&hash)?,
},
(None, _) => Signature::NotSigned, (None, _) => Signature::NotSigned,
}; };
Ok(Message { Ok(Message {
@ -239,11 +338,16 @@ impl MessageBuilder {
#[cfg(test)] #[cfg(test)]
use alloc::vec; use alloc::vec;
#[cfg(feature = "std")]
#[cfg(test)]
use std::println;
#[test] #[test]
fn test_hashing_message_type() { fn test_hashing_message_type() {
let msg_type_1 = MessageType::Broadcast; let msg_type_1 = MessageType::Broadcast;
let msg_type_2 = MessageType::Service(ServiceMessageType::TunnelBuilding(TunnelPublic::new_for_test())); 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_1.hash(), msg_type_1.hash());
assert_eq!(msg_type_2.hash(), msg_type_2.hash()); assert_eq!(msg_type_2.hash(), msg_type_2.hash());
assert_ne!(msg_type_1.hash(), msg_type_2.hash()) assert_ne!(msg_type_1.hash(), msg_type_2.hash())
@ -260,3 +364,19 @@ fn test_hash_message_content() {
assert_ne!(content_1.hash(), content_3.hash()); assert_ne!(content_1.hash(), content_3.hash());
assert_ne!(content_3.hash(), content_2.hash()); assert_ne!(content_3.hash(), content_2.hash());
} }
#[test]
fn test_building_message() -> IFResult<()> {
let keys_1 = Keys::generate();
let keys_2 = Keys::generate();
let msg = Message::build()
.content(b"hello".to_vec())
.sign(&keys_1)
.recipient(keys_2.get_public())
.tunnel(1)
.message_type(MessageType::SingleCast)
.build()?;
assert!(msg.verify_hash());
assert!(msg.verify_signature(keys_2));
Ok(())
}

Loading…
Cancel
Save