Files
featherChat/warzone/crates/warzone-protocol/src/message.rs
Siavash Sameni 86da52acc4 v0.0.13: Sender Keys for efficient group encryption
Protocol (sender_keys.rs):
- SenderKey: symmetric key with chain ratchet (forward secrecy per chain)
- generate(), rotate(), encrypt(), decrypt()
- SenderKeyDistribution: share key via 1:1 encrypted channel
- SenderKeyMessage: encrypted group message (O(1) instead of O(N))
- Chain key ratchets forward on each message (HKDF)
- Generation counter for key rotation tracking
- 4 tests: basic, multi-message, rotation, old-key rejection

WireMessage:
- GroupSenderKey variant: encrypted group message
- SenderKeyDistribution variant: key sharing

Server: dedup handles new variants.
CLI TUI + recv: stub handlers for new message types.
23/23 protocol tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:23:10 +04:00

105 lines
3.0 KiB
Rust

use serde::{Deserialize, Serialize};
use crate::ratchet::RatchetHeader;
use crate::types::{Fingerprint, MessageId, SessionId};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum MessageType {
Text,
File,
KeyExchange,
Receipt,
}
/// An encrypted message on the wire.
#[derive(Clone, Serialize, Deserialize)]
pub struct WarzoneMessage {
pub version: u8,
pub id: MessageId,
pub from: Fingerprint,
pub to: Fingerprint,
pub timestamp: i64,
pub msg_type: MessageType,
pub session_id: SessionId,
pub ratchet_header: RatchetHeader,
pub ciphertext: Vec<u8>,
pub signature: Vec<u8>,
}
/// Plaintext message content (inside the encrypted envelope).
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum MessageContent {
Text { body: String },
File { filename: String, data: Vec<u8> },
Receipt { message_id: MessageId },
}
/// Receipt type: delivered (received + decrypted) or read (user viewed).
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum ReceiptType {
Delivered,
Read,
}
/// Wire message format for transport between clients.
/// Used by both CLI and WASM — MUST be identical for interop.
#[derive(Clone, Serialize, Deserialize)]
pub enum WireMessage {
/// First message to a peer: X3DH key exchange + first ratchet message.
KeyExchange {
id: String,
sender_fingerprint: String,
sender_identity_encryption_key: [u8; 32],
ephemeral_public: [u8; 32],
used_one_time_pre_key_id: Option<u32>,
ratchet_message: crate::ratchet::RatchetMessage,
},
/// Subsequent messages: ratchet-encrypted.
Message {
id: String,
sender_fingerprint: String,
ratchet_message: crate::ratchet::RatchetMessage,
},
/// Delivery / read receipt (plaintext, not encrypted).
Receipt {
sender_fingerprint: String,
message_id: String,
receipt_type: ReceiptType,
},
/// File transfer header: announces an incoming chunked file.
FileHeader {
id: String,
sender_fingerprint: String,
filename: String,
file_size: u64,
total_chunks: u32,
sha256: String,
},
/// A single chunk of a file transfer (data is ratchet-encrypted).
FileChunk {
id: String,
sender_fingerprint: String,
filename: String,
chunk_index: u32,
total_chunks: u32,
data: Vec<u8>,
},
/// Group message encrypted with sender key (O(1) instead of O(N)).
GroupSenderKey {
id: String,
sender_fingerprint: String,
group_name: String,
generation: u32,
counter: u32,
ciphertext: Vec<u8>,
},
/// Sender key distribution: share your sender key with a group member.
/// This is sent via 1:1 encrypted channel (wrapped in KeyExchange/Message).
SenderKeyDistribution {
sender_fingerprint: String,
group_name: String,
chain_key: [u8; 32],
generation: u32,
},
}