2021-05-18 04:58:52 +00:00
|
|
|
use crate::MixMessage::{Forward, Heartbeat};
|
|
|
|
use chrono::{DateTime, Duration, Local, NaiveDateTime};
|
|
|
|
use fuzzytags::{RootSecret, Tag, TaggingKey};
|
|
|
|
use niwl::encrypt::{PrivateKey, TaggedCiphertext};
|
|
|
|
use niwl::Profile;
|
2021-05-18 07:00:39 +00:00
|
|
|
use rand::rngs::OsRng;
|
|
|
|
use rand::Rng;
|
2021-05-18 04:58:52 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use std::fmt::Error;
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
pub enum MixMessage {
|
|
|
|
Heartbeat(Tag<24>, DateTime<Local>),
|
|
|
|
Forward(TaggedCiphertext),
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct RandomEjectionMix {
|
|
|
|
heartbeat_id: Tag<24>,
|
2021-05-18 06:34:36 +00:00
|
|
|
last_heartbeat: DateTime<Local>,
|
2021-05-18 07:00:39 +00:00
|
|
|
store: Vec<TaggedCiphertext>,
|
2021-05-18 04:58:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl RandomEjectionMix {
|
|
|
|
pub fn init(tag: Tag<24>) -> RandomEjectionMix {
|
2021-05-18 07:00:39 +00:00
|
|
|
let mut store = vec![];
|
|
|
|
for i in 0..10 {
|
2021-05-18 22:13:44 +00:00
|
|
|
store.push(RandomEjectionMix::get_random());
|
2021-05-18 07:00:39 +00:00
|
|
|
}
|
|
|
|
|
2021-05-18 06:34:36 +00:00
|
|
|
RandomEjectionMix {
|
|
|
|
heartbeat_id: tag,
|
|
|
|
last_heartbeat: Local::now(),
|
2021-05-18 07:00:39 +00:00
|
|
|
store,
|
2021-05-18 06:34:36 +00:00
|
|
|
}
|
2021-05-18 04:58:52 +00:00
|
|
|
}
|
|
|
|
|
2021-05-18 22:13:44 +00:00
|
|
|
pub fn get_random() -> TaggedCiphertext {
|
|
|
|
let random_tag = RootSecret::<24>::generate().tagging_key().generate_tag();
|
|
|
|
let random_secret = PrivateKey::generate();
|
|
|
|
let random_encryption = random_secret
|
|
|
|
.public_key()
|
|
|
|
.encrypt(&random_tag, &String::new());
|
|
|
|
random_encryption
|
|
|
|
}
|
|
|
|
|
2021-05-18 04:58:52 +00:00
|
|
|
pub fn push(&mut self, tag: &Tag<24>, plaintext: &String) -> Option<MixMessage> {
|
|
|
|
// The plaintext can either be a TaggedCiphertext OR a HeartBeat
|
|
|
|
let message: serde_json::Result<TaggedCiphertext> =
|
|
|
|
serde_json::from_str(plaintext.as_str());
|
|
|
|
match &message {
|
|
|
|
Ok(ciphertext) => return Some(Forward(self.random_ejection_mix(ciphertext))),
|
|
|
|
Err(_) => {
|
|
|
|
// Assume this is a Mix Message
|
|
|
|
let message: serde_json::Result<MixMessage> =
|
|
|
|
serde_json::from_str(plaintext.as_str());
|
|
|
|
match &message {
|
|
|
|
Ok(mixMessage) => match mixMessage {
|
|
|
|
Heartbeat(id, time) => self.process_heartbeat(id, time),
|
|
|
|
_ => None,
|
|
|
|
},
|
|
|
|
Err(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-18 06:34:36 +00:00
|
|
|
fn process_heartbeat(
|
|
|
|
&mut self,
|
|
|
|
tag: &Tag<24>,
|
|
|
|
heartbeat: &DateTime<Local>,
|
|
|
|
) -> Option<MixMessage> {
|
2021-05-18 04:58:52 +00:00
|
|
|
if tag == &self.heartbeat_id {
|
2021-05-18 06:34:36 +00:00
|
|
|
println!("[DEBUG] Received HeartBeat from {}", heartbeat);
|
|
|
|
self.last_heartbeat = heartbeat.clone();
|
|
|
|
let now = Local::now();
|
|
|
|
let new_heartbeat = Heartbeat(self.heartbeat_id.clone(), now.clone());
|
2021-05-18 04:58:52 +00:00
|
|
|
return Some(new_heartbeat);
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2021-05-18 06:34:36 +00:00
|
|
|
pub fn check_heartbeat(&self) -> bool {
|
|
|
|
let time_since_last = Local::now() - self.last_heartbeat;
|
|
|
|
println!(
|
|
|
|
"[DEBUG] Time since last heartbeat: {}s",
|
|
|
|
time_since_last.num_seconds()
|
|
|
|
);
|
|
|
|
if time_since_last > Duration::minutes(2) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-05-18 04:58:52 +00:00
|
|
|
// Actually do the Random Ejection Mixing...
|
|
|
|
fn random_ejection_mix(&mut self, ciphertext: &TaggedCiphertext) -> TaggedCiphertext {
|
2021-05-18 07:00:39 +00:00
|
|
|
let mut rng = OsRng::default();
|
|
|
|
let random_index = rng.gen_range(0..10);
|
|
|
|
println!("[DEBUG] Ejecting {} ", random_index);
|
|
|
|
let ejection = self.store[random_index].clone();
|
|
|
|
self.store[random_index] = ciphertext.clone();
|
|
|
|
ejection
|
2021-05-18 04:58:52 +00:00
|
|
|
}
|
|
|
|
}
|