From 28a965dff4a47d7f768a33873fff97d4df11a902 Mon Sep 17 00:00:00 2001 From: kaichaosun Date: Wed, 28 Jan 2026 16:38:42 +0800 Subject: [PATCH] chore: remove backup codes --- double-ratchets/src/storage/mod.rs.bak | 5 - double-ratchets/src/storage/session.rs.bak | 310 --------------------- double-ratchets/src/storage/types.rs.bak | 81 ------ 3 files changed, 396 deletions(-) delete mode 100644 double-ratchets/src/storage/mod.rs.bak delete mode 100644 double-ratchets/src/storage/session.rs.bak delete mode 100644 double-ratchets/src/storage/types.rs.bak diff --git a/double-ratchets/src/storage/mod.rs.bak b/double-ratchets/src/storage/mod.rs.bak deleted file mode 100644 index e26ec70..0000000 --- a/double-ratchets/src/storage/mod.rs.bak +++ /dev/null @@ -1,5 +0,0 @@ -mod session; -mod sqlite; - -pub use session::{RatchetSession, SessionError}; -pub use sqlite::{SqliteStorage, StorageConfig}; diff --git a/double-ratchets/src/storage/session.rs.bak b/double-ratchets/src/storage/session.rs.bak deleted file mode 100644 index 399af8d..0000000 --- a/double-ratchets/src/storage/session.rs.bak +++ /dev/null @@ -1,310 +0,0 @@ -use x25519_dalek::PublicKey; - -use crate::{ - InstallationKeyPair, - errors::RatchetError, - hkdf::HkdfInfo, - state::{Header, RatchetState}, - types::SharedSecret, -}; - -use super::{SqliteStorage, StorageError}; - -/// A session wrapper that automatically persists ratchet state after operations. -/// Provides rollback semantics - state is only saved if the operation succeeds. -pub struct RatchetSession<'a, D: HkdfInfo + Clone> { - storage: &'a mut SqliteStorage, - conversation_id: String, - state: RatchetState, -} - -#[derive(Debug)] -pub enum SessionError { - Storage(StorageError), - Ratchet(RatchetError), -} - -impl From for SessionError { - fn from(e: StorageError) -> Self { - SessionError::Storage(e) - } -} - -impl From for SessionError { - fn from(e: RatchetError) -> Self { - SessionError::Ratchet(e) - } -} - -impl std::fmt::Display for SessionError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - SessionError::Storage(e) => write!(f, "storage error: {}", e), - SessionError::Ratchet(e) => write!(f, "ratchet error: {}", e), - } - } -} - -impl std::error::Error for SessionError {} - -impl<'a, D: HkdfInfo + Clone> RatchetSession<'a, D> { - /// Opens an existing session from storage. - pub fn open( - storage: &'a mut SqliteStorage, - conversation_id: impl Into, - ) -> Result { - let conversation_id = conversation_id.into(); - let state = storage.load(&conversation_id)?; - Ok(Self { - storage, - conversation_id, - state, - }) - } - - /// Creates a new session and persists the initial state. - pub fn create( - storage: &'a mut SqliteStorage, - conversation_id: impl Into, - state: RatchetState, - ) -> Result { - let conversation_id = conversation_id.into(); - storage.save(&conversation_id, &state)?; - Ok(Self { - storage, - conversation_id, - state, - }) - } - - /// Initializes a new session as a sender and persists the initial state. - pub fn create_sender_session( - storage: &'a mut SqliteStorage, - conversation_id: impl Into, - shared_secret: SharedSecret, - remote_pub: PublicKey, - ) -> Result { - let state = RatchetState::::init_sender(shared_secret, remote_pub); - Self::create(storage, conversation_id, state) - } - - /// Initializes a new session as a receiver and persists the initial state. - pub fn create_receiver_session( - storage: &'a mut SqliteStorage, - conversation_id: impl Into, - shared_secret: SharedSecret, - dh_self: InstallationKeyPair, - ) -> Result { - let conversation_id = conversation_id.into(); - if storage.exists(&conversation_id)? { - return Self::open(storage, conversation_id); - } - - let state = RatchetState::::init_receiver(shared_secret, dh_self); - Self::create(storage, conversation_id, state) - } - - /// Encrypts a message and persists the updated state. - /// If persistence fails, the in-memory state is NOT modified. - pub fn encrypt_message(&mut self, plaintext: &[u8]) -> Result<(Vec, Header), SessionError> { - // Clone state for rollback - let state_backup = self.state.clone(); - - // Perform encryption (modifies state) - let result = self.state.encrypt_message(plaintext); - - // Try to persist - if let Err(e) = self.storage.save(&self.conversation_id, &self.state) { - // Rollback - self.state = state_backup; - return Err(SessionError::Storage(e)); - } - - Ok(result) - } - - /// Decrypts a message and persists the updated state. - /// If decryption or persistence fails, the in-memory state is NOT modified. - pub fn decrypt_message( - &mut self, - ciphertext_with_nonce: &[u8], - header: Header, - ) -> Result, SessionError> { - // Clone state for rollback - let state_backup = self.state.clone(); - - // Perform decryption (modifies state) - let plaintext = match self.state.decrypt_message(ciphertext_with_nonce, header) { - Ok(pt) => pt, - Err(e) => { - // Rollback on decrypt failure - self.state = state_backup; - return Err(SessionError::Ratchet(e)); - } - }; - - // Try to persist - if let Err(e) = self.storage.save(&self.conversation_id, &self.state) { - // Rollback - self.state = state_backup; - return Err(SessionError::Storage(e)); - } - - Ok(plaintext) - } - - /// Returns a reference to the current state (read-only). - pub fn state(&self) -> &RatchetState { - &self.state - } - - /// Returns the conversation ID. - pub fn conversation_id(&self) -> &str { - &self.conversation_id - } - - /// Manually saves the current state. - pub fn save(&mut self) -> Result<(), StorageError> { - self.storage.save(&self.conversation_id, &self.state) - } - - pub fn msg_send(&self) -> u32 { - self.state.msg_send - } - - pub fn msg_recv(&self) -> u32 { - self.state.msg_recv - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{hkdf::DefaultDomain, keypair::InstallationKeyPair, storage::StorageConfig}; - - fn create_test_storage() -> SqliteStorage { - SqliteStorage::new(StorageConfig::InMemory).unwrap() - } - - #[test] - fn test_session_create_and_open() { - let mut storage = create_test_storage(); - - let shared_secret = [0x42; 32]; - let bob_keypair = InstallationKeyPair::generate(); - let alice: RatchetState = - RatchetState::init_sender(shared_secret, bob_keypair.public().clone()); - - // Create session - { - let session = RatchetSession::create(&mut storage, "conv1", alice).unwrap(); - assert_eq!(session.conversation_id(), "conv1"); - } - - // Open existing session - { - let session: RatchetSession = - RatchetSession::open(&mut storage, "conv1").unwrap(); - assert_eq!(session.state().msg_send, 0); - } - } - - #[test] - fn test_session_encrypt_persists() { - let mut storage = create_test_storage(); - - let shared_secret = [0x42; 32]; - let bob_keypair = InstallationKeyPair::generate(); - let alice: RatchetState = - RatchetState::init_sender(shared_secret, bob_keypair.public().clone()); - - // Create and encrypt - { - let mut session = RatchetSession::create(&mut storage, "conv1", alice).unwrap(); - session.encrypt_message(b"Hello").unwrap(); - assert_eq!(session.state().msg_send, 1); - } - - // Reopen - state should be persisted - { - let session: RatchetSession = - RatchetSession::open(&mut storage, "conv1").unwrap(); - assert_eq!(session.state().msg_send, 1); - } - } - - #[test] - fn test_session_full_conversation() { - let mut storage = create_test_storage(); - - let shared_secret = [0x42; 32]; - let bob_keypair = InstallationKeyPair::generate(); - let alice: RatchetState = - RatchetState::init_sender(shared_secret, bob_keypair.public().clone()); - let bob: RatchetState = - RatchetState::init_receiver(shared_secret, bob_keypair); - - // Alice sends - let (ct, header) = { - let mut session = RatchetSession::create(&mut storage, "alice", alice).unwrap(); - session.encrypt_message(b"Hello Bob").unwrap() - }; - - // Bob receives - let plaintext = { - let mut session = RatchetSession::create(&mut storage, "bob", bob).unwrap(); - session.decrypt_message(&ct, header).unwrap() - }; - assert_eq!(plaintext, b"Hello Bob"); - - // Bob replies - let (ct2, header2) = { - let mut session: RatchetSession = - RatchetSession::open(&mut storage, "bob").unwrap(); - session.encrypt_message(b"Hi Alice").unwrap() - }; - - // Alice receives - let plaintext2 = { - let mut session: RatchetSession = - RatchetSession::open(&mut storage, "alice").unwrap(); - session.decrypt_message(&ct2, header2).unwrap() - }; - assert_eq!(plaintext2, b"Hi Alice"); - } - - #[test] - fn test_session_open_or_create() { - let mut storage = create_test_storage(); - - let shared_secret = [0x42; 32]; - let bob_keypair = InstallationKeyPair::generate(); - let bob_pub = bob_keypair.public().clone(); - - // First call creates - { - let session: RatchetSession = RatchetSession::create_sender_session( - &mut storage, - "conv1", - shared_secret, - bob_pub.clone(), - ) - .unwrap(); - assert_eq!(session.state().msg_send, 0); - } - - // Second call opens existing - { - let mut session: RatchetSession = - RatchetSession::open(&mut storage, "conv1").unwrap(); - session.encrypt_message(b"test").unwrap(); - } - - // Verify persistence - { - let session: RatchetSession = - RatchetSession::open(&mut storage, "conv1").unwrap(); - assert_eq!(session.state().msg_send, 1); - } - } -} diff --git a/double-ratchets/src/storage/types.rs.bak b/double-ratchets/src/storage/types.rs.bak deleted file mode 100644 index 6a1cd80..0000000 --- a/double-ratchets/src/storage/types.rs.bak +++ /dev/null @@ -1,81 +0,0 @@ -use crate::{ - hkdf::HkdfInfo, - state::{RatchetState, SkippedKey}, - types::MessageKey, -}; -use thiserror::Error; -use x25519_dalek::PublicKey; - -#[derive(Debug, Error)] -pub enum StorageError { - #[error("database error: {0}")] - Database(#[from] rusqlite::Error), - - #[error("conversation not found: {0}")] - ConversationNotFound(String), - - #[error("serialization error")] - Serialization, - - #[error("deserialization error")] - Deserialization, -} - -/// Stored representation of a skipped message key. - -/// Raw state data for storage (without generic parameter). -#[derive(Debug, Clone)] -pub struct RatchetStateRecord { - pub root_key: [u8; 32], - pub sending_chain: Option<[u8; 32]>, - pub receiving_chain: Option<[u8; 32]>, - pub dh_self_secret: [u8; 32], - pub dh_remote: Option<[u8; 32]>, - pub msg_send: u32, - pub msg_recv: u32, - pub prev_chain_len: u32, -} - -impl From<&RatchetState> for RatchetStateRecord { - fn from(state: &RatchetState) -> Self { - Self { - root_key: state.root_key, - sending_chain: state.sending_chain, - receiving_chain: state.receiving_chain, - dh_self_secret: state.dh_self.secret_bytes(), - dh_remote: state.dh_remote.map(|pk| pk.to_bytes()), - msg_send: state.msg_send, - msg_recv: state.msg_recv, - prev_chain_len: state.prev_chain_len, - } - } -} - -impl RatchetStateRecord { - pub fn into_ratchet_state(self, skipped_keys: Vec) -> RatchetState { - use crate::keypair::InstallationKeyPair; - use std::collections::HashMap; - use std::marker::PhantomData; - - let dh_self = InstallationKeyPair::from_secret_bytes(self.dh_self_secret); - let dh_remote = self.dh_remote.map(PublicKey::from); - - let skipped: HashMap<(PublicKey, u32), MessageKey> = skipped_keys - .into_iter() - .map(|sk| ((PublicKey::from(sk.public_key), sk.msg_num), sk.message_key)) - .collect(); - - RatchetState { - root_key: self.root_key, - sending_chain: self.sending_chain, - receiving_chain: self.receiving_chain, - dh_self, - dh_remote, - msg_send: self.msg_send, - msg_recv: self.msg_recv, - prev_chain_len: self.prev_chain_len, - skipped_keys: skipped, - _domain: PhantomData, - } - } -}