use std::time::{SystemTime, UNIX_EPOCH};
use zeroize::ZeroizeOnDrop;
use crate::auth::SessionKeys;
use crate::session::error::SessionError;
use crate::session::message::{ContentType, Message};
#[derive(ZeroizeOnDrop)]
pub struct Conversation {
session_keys: SessionKeys,
next_sequence: u64,
created_at: u64,
}
impl Conversation {
pub fn new(shared_secret: &[u8], address: &str, created_at: u64) -> Self {
let session_keys = SessionKeys::derive(shared_secret, address, created_at);
Self {
session_keys,
next_sequence: 1,
created_at,
}
}
#[cfg(test)]
pub fn from_keys(session_keys: SessionKeys) -> Self {
let created_at = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_secs();
Self {
session_keys,
next_sequence: 1,
created_at,
}
}
pub fn created_at(&self) -> u64 {
self.created_at
}
pub fn create_text_message(&mut self, content: &str) -> Message {
let sequence = self.next_sequence;
let timestamp = Self::current_unix_timestamp();
let plaintext = content.as_bytes();
self.next_sequence += 1;
Message::encrypt(
sequence,
timestamp,
ContentType::Text,
plaintext,
&self.session_keys.encryption_key,
&self.session_keys.signing_key,
)
}
pub fn create_image_message(&mut self, image_data: &[u8]) -> Message {
let sequence = self.next_sequence;
let timestamp = Self::current_unix_timestamp();
self.next_sequence += 1;
Message::encrypt(
sequence,
timestamp,
ContentType::Image,
image_data,
&self.session_keys.encryption_key,
&self.session_keys.signing_key,
)
}
pub fn decrypt_message(&self, message: &Message) -> Result<Vec<u8>, SessionError> {
message.decrypt(
&self.session_keys.encryption_key,
&self.session_keys.signing_key,
)
}
pub fn create_forged_text_message(
&self,
sequence: u64,
timestamp: u32,
fake_content: &str,
) -> Message {
let plaintext = fake_content.as_bytes();
Message::encrypt(
sequence,
timestamp,
ContentType::Text,
plaintext,
&self.session_keys.encryption_key,
&self.session_keys.signing_key,
)
}
pub fn current_sequence(&self) -> u64 {
self.next_sequence
}
fn current_unix_timestamp() -> u32 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_secs() as u32
}
}