Browse Source

Hashing of everything

master
Lev 3 years ago
parent
commit
eede8b9c23
  1. 17
      src/crypto.rs
  2. 67
      src/message.rs
  3. 34
      src/tunnel.rs

17
src/crypto.rs

@ -27,7 +27,17 @@ impl PublicKey {
}
pub fn to_vec(&self) -> serde_cbor::Result<Vec<u8>> {
serde_cbor::to_vec(&self)
serde_cbor::to_vec(&self.key)
}
pub fn from_vec(data: Vec<u8>) -> serde_cbor::Result<Self> {
serde_cbor::from_slice(data.as_slice())
}
}
impl PublicKey {
fn hash(&self) -> Vec<u8> {
self.to_vec().unwrap()
}
}
@ -103,3 +113,8 @@ fn test_invalid_signing() {
let keys_2 = Keys::generate();
assert!(!keys_2.get_public().verify_sign(&data, &keys_1.sign(&data).unwrap()));
}
#[test]
fn test_pkey_caching() {
assert_ne!(Keys::generate().get_public().hash(), Keys::generate().get_public().hash())
}

67
src/message.rs

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

34
src/tunnel.rs

@ -1,6 +1,7 @@
use alloc::vec::Vec;
use crate::crypto::PublicKey;
use serde::{Serialize, Deserialize};
use sha2::Digest;
/// A tunnel that is used for communication
#[derive(Serialize, Clone, Deserialize)]
@ -34,3 +35,36 @@ pub struct TunnelPublic {
/// Public keys of nodes in the tunnel
nodes_in_tunnel: Option<Vec<PublicKey>>,
}
impl TunnelPublic {
pub fn hash(&self) -> Vec<u8> {
sha2::Sha224::new()
.chain(serde_cbor::to_vec(self).unwrap().as_slice())
.result().to_vec()
}
#[cfg(test)]
pub fn new_for_test() -> Self {
TunnelPublic {
id: Some(56),
local_ids: vec![5, 500, 120],
ttd: 56,
nodes_in_tunnel: Some(vec![crate::crypto::Keys::generate().get_public()])
}
}
}
#[cfg(test)]
use alloc::vec;
#[test]
fn test_tunnel_hashing() {
let tun = TunnelPublic::new_for_test();
assert_eq!(tun.hash(), tun.hash());
assert_ne!(tun.hash(), TunnelPublic {
id: Some(56),
local_ids: vec![5, 500, 120],
ttd: 56,
nodes_in_tunnel: Some(vec![crate::crypto::Keys::generate().get_public()])
}.hash());
}

Loading…
Cancel
Save