chore: use tempfile for examples

This commit is contained in:
kaichaosun 2026-01-30 15:46:15 +08:00
parent 8ed4239477
commit 4ca6828501
No known key found for this signature in database
GPG Key ID: 223E0F992F4F03BF
7 changed files with 154 additions and 68 deletions

105
Cargo.lock generated
View File

@ -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"

View File

@ -25,3 +25,6 @@ serde = "1.0"
[features]
headers = ["safer-ffi/headers"]
[dev-dependencies]
tempfile = "3"

View File

@ -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<PrivateV1Domain> =
RatchetState::init_sender(shared_secret, bob_dh.public().clone());
let mut bob: RatchetState<PrivateV1Domain> = 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!");

View File

@ -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<u8>, 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<DefaultDomain> =
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<DefaultDomain> =
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<DefaultDomain> =
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<DefaultDomain> =
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<DefaultDomain> =
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<DefaultDomain> =
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);
}
}

View File

@ -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<PrivateV1Domain> =
RatchetState::init_sender(shared_secret, bob_dh.public().clone());
let mut bob: RatchetState<PrivateV1Domain> = 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<PrivateV1Domain> =
RatchetState::from_bytes(&alice_state).unwrap();
let mut bob_new: RatchetState<PrivateV1Domain> = 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!");

View File

@ -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<PrivateV1Domain> = 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<PrivateV1Domain> =
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<PrivateV1Domain> =
RatchetSession::open(alice_storage, conv_id).unwrap();
let mut bob_session: RatchetSession<PrivateV1Domain> =
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

View File

@ -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<D>,