use serde::{Deserialize, Serialize};
use crate::{clock::Hlc, conversation::ConversationId, device::DeviceId, WIRE_VERSION};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[repr(u8)]
pub enum MessageKind {
Application = 1,
Commit = 2,
Welcome = 3,
Proposal = 4,
KeyPackage = 5,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageEnvelope {
pub v: u8,
pub conversation_id: ConversationId,
pub epoch: u64,
pub kind: MessageKind,
pub sender_device: DeviceId,
pub seq: u64,
pub hlc: Hlc,
#[serde(with = "serde_bytes")]
pub payload: Vec<u8>,
pub content_hash: [u8; 32],
}
impl MessageEnvelope {
pub fn new(
conversation_id: ConversationId,
epoch: u64,
kind: MessageKind,
sender_device: DeviceId,
seq: u64,
hlc: Hlc,
payload: Vec<u8>,
) -> Self {
debug_assert!(
!matches!(kind, MessageKind::Application),
"use MessageEnvelope::new_application for Application kind (CR-6 hashes plaintext)"
);
let content_hash = hash_handshake(kind, &payload);
Self {
v: WIRE_VERSION,
conversation_id,
epoch,
kind,
sender_device,
seq,
hlc,
payload,
content_hash,
}
}
pub fn new_application(
conversation_id: ConversationId,
epoch: u64,
sender_device: DeviceId,
seq: u64,
hlc: Hlc,
payload: Vec<u8>,
plaintext: &[u8],
) -> Self {
let content_hash = hash_application_plaintext(plaintext);
Self {
v: WIRE_VERSION,
conversation_id,
epoch,
kind: MessageKind::Application,
sender_device,
seq,
hlc,
payload,
content_hash,
}
}
}
pub fn hash_handshake(kind: MessageKind, payload: &[u8]) -> [u8; 32] {
use sha2::{Digest, Sha256};
let mut h = Sha256::new();
h.update([kind as u8]);
h.update(payload);
h.finalize().into()
}
pub fn hash_application_plaintext(plaintext: &[u8]) -> [u8; 32] {
use sha2::{Digest, Sha256};
let mut h = Sha256::new();
h.update(plaintext);
h.finalize().into()
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IncomingMessage {
pub conversation_id: ConversationId,
pub sender_device: DeviceId,
pub epoch: u64,
pub hlc: Hlc,
#[serde(with = "serde_bytes")]
pub plaintext: Vec<u8>,
pub content_hash: [u8; 32],
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OutgoingMessage {
#[serde(with = "serde_bytes")]
pub plaintext: Vec<u8>,
}