Browse Source

MessageBuilder

interface-2
Lev 3 years ago
parent
commit
63ab79c6b2
  1. 17
      Cargo.lock
  2. 1
      Cargo.toml
  3. 4
      src/crypto.rs
  4. 5
      src/ironforce.rs
  5. 104
      src/message.rs
  6. 24
      src/res.rs

17
Cargo.lock generated

@ -210,6 +210,12 @@ dependencies = [
"wasi 0.10.2+wasi-snapshot-preview1", "wasi 0.10.2+wasi-snapshot-preview1",
] ]
[[package]]
name = "half"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.19" version = "0.1.19"
@ -229,6 +235,7 @@ dependencies = [
"rayon", "rayon",
"rsa", "rsa",
"serde", "serde",
"serde_cbor",
"sha2", "sha2",
] ]
@ -505,6 +512,16 @@ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]]
name = "serde_cbor"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
dependencies = [
"half",
"serde",
]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.130" version = "1.0.130"

1
Cargo.toml

@ -19,6 +19,7 @@ rsa = { version = "0.5", features = ["serde"] }
serde = { version = "1.0", features = ["derive", "alloc"], default-features = false } serde = { version = "1.0", features = ["derive", "alloc"], default-features = false }
rayon = { version = "1.5.1", optional = true } rayon = { version = "1.5.1", optional = true }
core-error = "0.0.1-rc4" core-error = "0.0.1-rc4"
serde_cbor = "0.11.2"
[profile.dev.package.num-bigint-dig] [profile.dev.package.num-bigint-dig]
opt-level = 3 opt-level = 3

4
src/crypto.rs

@ -25,6 +25,10 @@ impl PublicKey {
pub fn encrypt_data(&self, data: &[u8]) -> RsaRes<Vec<u8>> { pub fn encrypt_data(&self, data: &[u8]) -> RsaRes<Vec<u8>> {
self.key.encrypt(&mut OsRng {}, PaddingScheme::PKCS1v15Encrypt, data) self.key.encrypt(&mut OsRng {}, PaddingScheme::PKCS1v15Encrypt, data)
} }
pub fn to_vec(&self) -> serde_cbor::Result<Vec<u8>> {
serde_cbor::to_vec(&self)
}
} }
/// Key pair (public and secret) for a node, should be stored locally /// Key pair (public and secret) for a node, should be stored locally

5
src/ironforce.rs

@ -37,6 +37,11 @@ impl IronForce {
todo!() todo!()
} }
/// Send a multicast or broadcast message
fn send_to_all(&mut self, _message: Message) -> IFResult<()> {
todo!()
}
/// 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!()

104
src/message.rs

@ -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(),
})
}
} }

24
src/res.rs

@ -9,13 +9,29 @@ pub enum IFError {
General(String), General(String),
/// A tunnel satisfying some conditions has not been found /// A tunnel satisfying some conditions has not been found
TunnelNotFound, TunnelNotFound,
/// Error during serialization
SerializationError(String),
/// Error in rsa
CryptoError(String),
} }
impl<T: Debug + core_error::Error> From<T> for IFError { // impl<T: Debug + core_error::Error> From<T> for IFError {
/// Convert from other error // /// Convert from other error
fn from(e: T) -> Self { // fn from(e: T) -> Self {
Self::General(format!("{:?}", e)) // Self::General(format!("{:?}", e))
// }
// }
impl From<serde_cbor::Error> for IFError {
fn from(e: serde_cbor::Error) -> Self {
Self::SerializationError(format!("{:?}", e))
}
}
impl From<rsa::errors::Error> for IFError {
fn from(e: rsa::errors::Error) -> Self {
Self::CryptoError(format!("{:?}", e))
} }
} }

Loading…
Cancel
Save