From 4ca68285012ab26c1812dcf96e4d4020f3c5ecc6 Mon Sep 17 00:00:00 2001 From: kaichaosun Date: Fri, 30 Jan 2026 15:46:15 +0800 Subject: [PATCH] chore: use tempfile for examples --- Cargo.lock | 105 +++++++++++++++++- double-ratchets/Cargo.toml | 3 + .../examples/double_ratchet_basic.rs | 7 +- double-ratchets/examples/out_of_order_demo.rs | 61 +++++----- .../examples/serialization_demo.rs | 12 +- double-ratchets/examples/storage_demo.rs | 30 ++--- double-ratchets/src/storage/session.rs | 4 +- 7 files changed, 154 insertions(+), 68 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fe8c616..1f43b1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -224,6 +224,7 @@ dependencies = [ "safer-ffi", "serde", "storage", + "tempfile", "thiserror", "x25519-dalek", "zeroize", @@ -265,6 +266,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "ext-trait" version = "1.0.1" @@ -312,6 +323,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + [[package]] name = "fiat-crypto" version = "0.2.9" @@ -361,6 +378,18 @@ dependencies = [ "wasi", ] +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + [[package]] name = "hashbrown" version = "0.15.5" @@ -464,6 +493,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + [[package]] name = "logos-chat" version = "0.1.0" @@ -501,6 +536,12 @@ version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -631,6 +672,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.8.5" @@ -658,7 +705,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.17", ] [[package]] @@ -684,6 +731,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -883,6 +943,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys", +] + [[package]] name = "thiserror" version = "2.0.18" @@ -988,6 +1061,30 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "winnow" version = "0.7.14" @@ -997,6 +1094,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" + [[package]] name = "with_builtin_macros" version = "0.0.3" diff --git a/double-ratchets/Cargo.toml b/double-ratchets/Cargo.toml index 91061cb..6d1038c 100644 --- a/double-ratchets/Cargo.toml +++ b/double-ratchets/Cargo.toml @@ -25,3 +25,6 @@ serde = "1.0" [features] headers = ["safer-ffi/headers"] + +[dev-dependencies] +tempfile = "3" \ No newline at end of file diff --git a/double-ratchets/examples/double_ratchet_basic.rs b/double-ratchets/examples/double_ratchet_basic.rs index 297cc10..a48fc14 100644 --- a/double-ratchets/examples/double_ratchet_basic.rs +++ b/double-ratchets/examples/double_ratchet_basic.rs @@ -1,4 +1,4 @@ -use double_ratchets::{InstallationKeyPair, RatchetState, hkdf::PrivateV1Domain}; +use double_ratchets::{InstallationKeyPair, RatchetState}; fn main() { // === Initial shared secret (X3DH / prekey result in real systems) === @@ -6,9 +6,8 @@ fn main() { let bob_dh = InstallationKeyPair::generate(); - let mut alice: RatchetState = - RatchetState::init_sender(shared_secret, bob_dh.public().clone()); - let mut bob: RatchetState = RatchetState::init_receiver(shared_secret, bob_dh); + let mut alice: RatchetState = RatchetState::init_sender(shared_secret, bob_dh.public().clone()); + let mut bob: RatchetState = RatchetState::init_receiver(shared_secret, bob_dh); let (ciphertext, header) = alice.encrypt_message(b"Hello Bob!"); diff --git a/double-ratchets/examples/out_of_order_demo.rs b/double-ratchets/examples/out_of_order_demo.rs index d40c6a5..e99cdfd 100644 --- a/double-ratchets/examples/out_of_order_demo.rs +++ b/double-ratchets/examples/out_of_order_demo.rs @@ -2,23 +2,23 @@ //! //! Run with: cargo run --example out_of_order_demo -p double-ratchets -use double_ratchets::{InstallationKeyPair, RatchetSession, RatchetStorage, hkdf::DefaultDomain}; +use double_ratchets::{InstallationKeyPair, RatchetSession, RatchetStorage}; +use tempfile::NamedTempFile; fn main() { println!("=== Out-of-Order Message Handling Demo ===\n"); - // Setup - ensure_tmp_directory(); - let alice_db_path = "./tmp/out_of_order_demo_alice.db"; - let bob_db_path = "./tmp/out_of_order_demo_bob.db"; - let encryption_key = "super-secret-key-123!"; - let _ = std::fs::remove_file(alice_db_path); - let _ = std::fs::remove_file(bob_db_path); + let alice_db_file = NamedTempFile::new().unwrap(); + let alice_db_path = alice_db_file.path().to_str().unwrap(); + let bob_db_file = NamedTempFile::new().unwrap(); + let bob_db_path = bob_db_file.path().to_str().unwrap(); let shared_secret = [0x42u8; 32]; let bob_keypair = InstallationKeyPair::generate(); let bob_public = bob_keypair.public().clone(); + let conv_id = "out_of_order_conv"; + let encryption_key = "super-secret-key-123!"; // Collect messages for out-of-order delivery let mut messages: Vec<(Vec, double_ratchets::Header)> = Vec::new(); @@ -30,23 +30,21 @@ fn main() { let mut bob_storage = RatchetStorage::new(bob_db_path, encryption_key).expect("Failed to create Bob storage"); - let mut alice_session: RatchetSession = - RatchetSession::create_sender_session( - &mut alice_storage, - conv_id, - shared_secret, - bob_public, - ) - .unwrap(); + let mut alice_session: RatchetSession = RatchetSession::create_sender_session( + &mut alice_storage, + conv_id, + shared_secret, + bob_public, + ) + .unwrap(); - let mut bob_session: RatchetSession = - RatchetSession::create_receiver_session( - &mut bob_storage, - conv_id, - shared_secret, - bob_keypair, - ) - .unwrap(); + let mut bob_session: RatchetSession = RatchetSession::create_receiver_session( + &mut bob_storage, + conv_id, + shared_secret, + bob_keypair, + ) + .unwrap(); println!(" Sessions created for Alice and Bob"); @@ -76,8 +74,7 @@ fn main() { let mut bob_storage = RatchetStorage::new(bob_db_path, encryption_key).expect("Failed to reopen Bob storage"); - let bob_session: RatchetSession = - RatchetSession::open(&mut bob_storage, conv_id).unwrap(); + let bob_session: RatchetSession = RatchetSession::open(&mut bob_storage, conv_id).unwrap(); println!( " After restart, Bob's skipped_keys: {}", bob_session.state().skipped_keys.len() @@ -91,7 +88,7 @@ fn main() { let mut bob_storage = RatchetStorage::new(bob_db_path, encryption_key).expect("Failed to open Bob storage"); - let mut bob_session: RatchetSession = + let mut bob_session: RatchetSession = RatchetSession::open(&mut bob_storage, conv_id).unwrap(); let (ct, header) = &messages[1]; @@ -108,7 +105,7 @@ fn main() { let mut bob_storage = RatchetStorage::new(bob_db_path, encryption_key).expect("Failed to open Bob storage"); - let mut bob_session: RatchetSession = + let mut bob_session: RatchetSession = RatchetSession::open(&mut bob_storage, conv_id).unwrap(); let pt = bob_session.decrypt_message(&ct4, header4.clone()).unwrap(); @@ -126,7 +123,7 @@ fn main() { let mut bob_storage = RatchetStorage::new(bob_db_path, encryption_key).expect("Failed to open Bob storage"); - let mut bob_session: RatchetSession = + let mut bob_session: RatchetSession = RatchetSession::open(&mut bob_storage, conv_id).unwrap(); match bob_session.decrypt_message(&ct4, header4) { @@ -141,9 +138,3 @@ fn main() { println!("\n=== Demo Complete ==="); } - -fn ensure_tmp_directory() { - if let Err(e) = std::fs::create_dir_all("./tmp") { - eprintln!("Failed to create tmp directory: {}", e); - } -} diff --git a/double-ratchets/examples/serialization_demo.rs b/double-ratchets/examples/serialization_demo.rs index 76a5878..5833f0e 100644 --- a/double-ratchets/examples/serialization_demo.rs +++ b/double-ratchets/examples/serialization_demo.rs @@ -1,4 +1,4 @@ -use double_ratchets::{InstallationKeyPair, RatchetState, hkdf::PrivateV1Domain}; +use double_ratchets::{InstallationKeyPair, RatchetState}; fn main() { // === Initial shared secret (X3DH / prekey result in real systems) === @@ -6,9 +6,8 @@ fn main() { let bob_dh = InstallationKeyPair::generate(); - let mut alice: RatchetState = - RatchetState::init_sender(shared_secret, bob_dh.public().clone()); - let mut bob: RatchetState = RatchetState::init_receiver(shared_secret, bob_dh); + let mut alice: RatchetState = RatchetState::init_sender(shared_secret, bob_dh.public().clone()); + let mut bob: RatchetState = RatchetState::init_receiver(shared_secret, bob_dh); let (ciphertext, header) = alice.encrypt_message(b"Hello Bob!"); @@ -35,9 +34,8 @@ fn main() { // === Deserialize alice and bob state from bytes === println!("Restart alice and bob"); - let mut alice_new: RatchetState = - RatchetState::from_bytes(&alice_state).unwrap(); - let mut bob_new: RatchetState = RatchetState::from_bytes(&bob_state).unwrap(); + let mut alice_new: RatchetState = RatchetState::from_bytes(&alice_state).unwrap(); + let mut bob_new: RatchetState = RatchetState::from_bytes(&bob_state).unwrap(); // === Alice sends a message === let (ciphertext, header) = alice_new.encrypt_message(b"Hello Bob!"); diff --git a/double-ratchets/examples/storage_demo.rs b/double-ratchets/examples/storage_demo.rs index 9b08a1e..8202995 100644 --- a/double-ratchets/examples/storage_demo.rs +++ b/double-ratchets/examples/storage_demo.rs @@ -2,17 +2,18 @@ //! //! Run with: cargo run --example storage_demo -p double-ratchets -use double_ratchets::{InstallationKeyPair, RatchetSession, RatchetStorage, hkdf::PrivateV1Domain}; +use double_ratchets::{InstallationKeyPair, RatchetSession, RatchetStorage}; +use tempfile::NamedTempFile; fn main() { println!("=== Double Ratchet Storage Demo ===\n"); - ensure_tmp_directory(); - let alice_db_path = "./tmp/double_ratchet_encrypted_alice.db"; - let bob_db_path = "./tmp/double_ratchet_encrypted_bob.db"; + let alice_db_file = NamedTempFile::new().unwrap(); + let alice_db_path = alice_db_file.path().to_str().unwrap(); + let bob_db_file = NamedTempFile::new().unwrap(); + let bob_db_path = bob_db_file.path().to_str().unwrap(); + let encryption_key = "super-secret-key-123!"; - let _ = std::fs::remove_file(alice_db_path); - let _ = std::fs::remove_file(bob_db_path); // Initial conversation with encryption { @@ -41,13 +42,6 @@ fn main() { let _ = std::fs::remove_file(bob_db_path); } -fn ensure_tmp_directory() { - if let Err(e) = std::fs::create_dir_all("./tmp") { - eprintln!("Failed to create tmp directory: {}", e); - return; - } -} - /// Simulates a conversation between Alice and Bob. /// Each party saves/loads state from storage for each operation. fn run_conversation(alice_storage: &mut RatchetStorage, bob_storage: &mut RatchetStorage) { @@ -57,7 +51,7 @@ fn run_conversation(alice_storage: &mut RatchetStorage, bob_storage: &mut Ratche let conv_id = "conv1"; - let mut alice_session: RatchetSession = RatchetSession::create_sender_session( + let mut alice_session: RatchetSession = RatchetSession::create_sender_session( alice_storage, conv_id, shared_secret, @@ -65,7 +59,7 @@ fn run_conversation(alice_storage: &mut RatchetStorage, bob_storage: &mut Ratche ) .unwrap(); - let mut bob_session: RatchetSession = + let mut bob_session: RatchetSession = RatchetSession::create_receiver_session(bob_storage, conv_id, shared_secret, bob_keypair) .unwrap(); @@ -125,10 +119,8 @@ fn continue_after_restart(alice_storage: &mut RatchetStorage, bob_storage: &mut // Load persisted states let conv_id = "conv1"; - let mut alice_session: RatchetSession = - RatchetSession::open(alice_storage, conv_id).unwrap(); - let mut bob_session: RatchetSession = - RatchetSession::open(bob_storage, conv_id).unwrap(); + let mut alice_session: RatchetSession = RatchetSession::open(alice_storage, conv_id).unwrap(); + let mut bob_session: RatchetSession = RatchetSession::open(bob_storage, conv_id).unwrap(); println!(" Sessions restored for Alice and Bob",); // Continue conversation diff --git a/double-ratchets/src/storage/session.rs b/double-ratchets/src/storage/session.rs index 40be01f..e7ad71e 100644 --- a/double-ratchets/src/storage/session.rs +++ b/double-ratchets/src/storage/session.rs @@ -4,7 +4,7 @@ use x25519_dalek::PublicKey; use crate::{ InstallationKeyPair, SessionError, - hkdf::HkdfInfo, + hkdf::{DefaultDomain, HkdfInfo}, state::{Header, RatchetState}, types::SharedSecret, }; @@ -13,7 +13,7 @@ use super::RatchetStorage; /// 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> { +pub struct RatchetSession<'a, D: HkdfInfo + Clone = DefaultDomain> { storage: &'a mut RatchetStorage, conversation_id: String, state: RatchetState,