diff --git a/Cargo.lock b/Cargo.lock index d8fbc00..47a7dc7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -108,6 +108,17 @@ dependencies = [ "prost", ] +[[package]] +name = "chat-sqlite" +version = "0.1.0" +dependencies = [ + "crypto", + "hex", + "storage", + "tempfile", + "zeroize", +] + [[package]] name = "cipher" version = "0.4.4" @@ -502,6 +513,7 @@ dependencies = [ "base64", "blake2", "chat-proto", + "chat-sqlite", "crypto", "double-ratchets", "hex", @@ -512,7 +524,6 @@ dependencies = [ "tempfile", "thiserror", "x25519-dalek", - "zeroize", ] [[package]] @@ -930,6 +941,7 @@ dependencies = [ name = "storage" version = "0.1.0" dependencies = [ + "crypto", "rusqlite", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index ca37bad..161cf69 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ resolver = "3" members = [ + "core/chat-sqlite", "core/conversations", "core/crypto", "core/double-ratchets", diff --git a/core/chat-sqlite/Cargo.toml b/core/chat-sqlite/Cargo.toml new file mode 100644 index 0000000..e7740cd --- /dev/null +++ b/core/chat-sqlite/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "chat-sqlite" +version = "0.1.0" +edition = "2024" +description = "SQLite storage implementation for libchat" + +[dependencies] +crypto = { path = "../crypto" } +hex = "0.4.3" +storage = { path = "../storage" } +zeroize = { version = "1.8.2", features = ["derive"] } + +[dev-dependencies] +tempfile = "3" diff --git a/core/conversations/src/sqlite.rs b/core/chat-sqlite/src/lib.rs similarity index 96% rename from core/conversations/src/sqlite.rs rename to core/chat-sqlite/src/lib.rs index 480ae9f..1433212 100644 --- a/core/conversations/src/sqlite.rs +++ b/core/chat-sqlite/src/lib.rs @@ -1,19 +1,16 @@ -//! Chat-specific storage implementation. +//! Chat-specific SQLite storage implementation. mod migrations; mod types; -use crypto::PrivateKey; -use storage::{RusqliteError, SqliteDb, StorageConfig, StorageError, params}; +use crypto::{Identity, PrivateKey}; +use storage::{ + ConversationKind, ConversationMeta, ConversationStore, EphemeralKeyStore, IdentityStore, + RusqliteError, SqliteDb, StorageConfig, StorageError, params, +}; use zeroize::Zeroize; -use crate::{ - identity::Identity, - sqlite::types::IdentityRecord, - store::{ - ConversationKind, ConversationMeta, ConversationStore, EphemeralKeyStore, IdentityStore, - }, -}; +use crate::types::IdentityRecord; /// Chat-specific storage operations. /// @@ -37,7 +34,6 @@ impl ChatStorage { migrations::apply_migrations(db.connection_mut())?; Ok(Self { db }) } - } impl IdentityStore for ChatStorage { @@ -241,6 +237,11 @@ impl ConversationStore for ChatStorage { #[cfg(test)] mod tests { + use storage::{ + ConversationKind, ConversationMeta, ConversationStore, EphemeralKeyStore, IdentityStore, + StorageConfig, + }; + use super::*; #[test] @@ -265,7 +266,7 @@ mod tests { let mut storage = ChatStorage::new(StorageConfig::InMemory).unwrap(); let key1 = PrivateKey::random(); - let pub1: crate::crypto::PublicKey = (&key1).into(); + let pub1: crypto::PublicKey = (&key1).into(); let hex1 = hex::encode(pub1.as_bytes()); // Initially not found diff --git a/core/conversations/src/sqlite/migrations.rs b/core/chat-sqlite/src/migrations.rs similarity index 100% rename from core/conversations/src/sqlite/migrations.rs rename to core/chat-sqlite/src/migrations.rs diff --git a/core/conversations/src/sqlite/migrations/001_initial_schema.sql b/core/chat-sqlite/src/migrations/001_initial_schema.sql similarity index 100% rename from core/conversations/src/sqlite/migrations/001_initial_schema.sql rename to core/chat-sqlite/src/migrations/001_initial_schema.sql diff --git a/core/conversations/src/sqlite/types.rs b/core/chat-sqlite/src/types.rs similarity index 96% rename from core/conversations/src/sqlite/types.rs rename to core/chat-sqlite/src/types.rs index c34f9be..786bc54 100644 --- a/core/conversations/src/sqlite/types.rs +++ b/core/chat-sqlite/src/types.rs @@ -2,8 +2,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop}; -use crate::crypto::PrivateKey; -use crate::identity::Identity; +use crypto::{Identity, PrivateKey}; /// Record for storing identity (secret key). /// Implements ZeroizeOnDrop to securely clear secret key from memory. diff --git a/core/conversations/Cargo.toml b/core/conversations/Cargo.toml index 4ea9408..62f8f87 100644 --- a/core/conversations/Cargo.toml +++ b/core/conversations/Cargo.toml @@ -8,6 +8,7 @@ crate-type = ["rlib","staticlib","dylib"] [dependencies] base64 = "0.22" +chat-sqlite = { path = "../chat-sqlite" } blake2.workspace = true chat-proto = { git = "https://github.com/logos-messaging/chat_proto" } crypto = { path = "../crypto" } @@ -19,7 +20,6 @@ safer-ffi = "0.1.13" thiserror = "2.0.17" x25519-dalek = { version = "2.0.1", features = ["static_secrets", "reusable_secrets", "getrandom"] } storage = { path = "../storage" } -zeroize = { version = "1.8.2", features = ["derive"] } [dev-dependencies] tempfile = "3" diff --git a/core/conversations/src/api.rs b/core/conversations/src/api.rs index ea16f76..3daaf4a 100644 --- a/core/conversations/src/api.rs +++ b/core/conversations/src/api.rs @@ -13,12 +13,12 @@ use safer_ffi::{ prelude::{c_slice, repr_c}, }; +use chat_sqlite::ChatStorage; use storage::StorageConfig; use crate::{ context::{Context, Introduction}, errors::ChatError, - sqlite::ChatStorage, types::ContentData, }; diff --git a/core/conversations/src/context.rs b/core/conversations/src/context.rs index e7945b3..04a8ec1 100644 --- a/core/conversations/src/context.rs +++ b/core/conversations/src/context.rs @@ -1,17 +1,18 @@ use std::rc::Rc; use std::sync::Arc; +use chat_sqlite::ChatStorage; +use crypto::Identity; use double_ratchets::{RatchetState, RatchetStorage}; -use storage::StorageConfig; +use storage::{ + ChatStore, ConversationKind, ConversationMeta, IdentityStore, StorageConfig, +}; use crate::{ conversation::{ConversationId, Convo, Id, PrivateV1Convo}, errors::ChatError, - identity::Identity, inbox::Inbox, proto::{EncryptedPayload, EnvelopeV1, Message}, - sqlite::ChatStorage, - store::{ChatStore, ConversationKind, ConversationMeta, IdentityStore}, types::{AddressedEnvelope, ContentData}, }; @@ -216,9 +217,9 @@ impl Context { #[cfg(test)] mod mock { use crypto::PrivateKey; - use storage::StorageError; - - use crate::store::{ConversationStore, EphemeralKeyStore, IdentityStore}; + use storage::{ + ConversationStore, EphemeralKeyStore, IdentityStore, StorageError, + }; use super::*; use std::collections::HashMap; @@ -315,7 +316,10 @@ mod mock { #[cfg(test)] mod tests { - use crate::{context::mock::MockChatStore, sqlite::ChatStorage, store::ConversationStore}; + use chat_sqlite::ChatStorage; + use storage::ConversationStore; + + use crate::context::mock::MockChatStore; use super::*; diff --git a/core/conversations/src/inbox/handler.rs b/core/conversations/src/inbox/handler.rs index 6bc2221..d275cd9 100644 --- a/core/conversations/src/inbox/handler.rs +++ b/core/conversations/src/inbox/handler.rs @@ -10,7 +10,7 @@ use crypto::{PrekeyBundle, SymmetricKey32}; use crate::context::Introduction; use crate::conversation::{ChatError, ConversationId, Convo, Id, PrivateV1Convo}; use crate::crypto::{CopyBytes, PrivateKey, PublicKey}; -use crate::identity::Identity; +use crypto::Identity; use crate::inbox::handshake::InboxHandshake; use crate::proto; use crate::types::{AddressedEncryptedPayload, ContentData}; @@ -239,9 +239,8 @@ impl Id for Inbox { #[cfg(test)] mod tests { use super::*; - use crate::sqlite::ChatStorage; - use crate::store::EphemeralKeyStore; - use storage::StorageConfig; + use chat_sqlite::ChatStorage; + use storage::{EphemeralKeyStore, StorageConfig}; #[test] fn test_invite_privatev1_roundtrip() { diff --git a/core/conversations/src/lib.rs b/core/conversations/src/lib.rs index 0e25b4f..9254169 100644 --- a/core/conversations/src/lib.rs +++ b/core/conversations/src/lib.rs @@ -3,18 +3,15 @@ mod context; mod conversation; mod crypto; mod errors; -mod identity; mod inbox; mod proto; -mod sqlite; -mod store; mod types; mod utils; pub use api::*; +pub use chat_sqlite::ChatStorage; pub use context::{Context, Introduction}; pub use errors::ChatError; -pub use sqlite::ChatStorage; pub use storage::StorageConfig; #[cfg(test)] diff --git a/core/conversations/src/identity.rs b/core/crypto/src/identity.rs similarity index 96% rename from core/conversations/src/identity.rs rename to core/crypto/src/identity.rs index 1aebb30..7b29b2f 100644 --- a/core/conversations/src/identity.rs +++ b/core/crypto/src/identity.rs @@ -1,6 +1,6 @@ use std::fmt; -use crate::crypto::{PrivateKey, PublicKey}; +use crate::{PrivateKey, PublicKey}; #[derive(Clone)] pub struct Identity { diff --git a/core/crypto/src/lib.rs b/core/crypto/src/lib.rs index 4b095ba..fff9cd2 100644 --- a/core/crypto/src/lib.rs +++ b/core/crypto/src/lib.rs @@ -1,7 +1,9 @@ +mod identity; mod keys; mod x3dh; mod xeddsa_sign; +pub use identity::Identity; pub use keys::{PrivateKey, PublicKey, SymmetricKey32}; pub use x3dh::{DomainSeparator, PrekeyBundle, X3Handshake}; pub use xeddsa_sign::{Ed25519Signature, SignatureError, xeddsa_sign, xeddsa_verify}; diff --git a/core/storage/Cargo.toml b/core/storage/Cargo.toml index 40d11d6..3339759 100644 --- a/core/storage/Cargo.toml +++ b/core/storage/Cargo.toml @@ -5,5 +5,6 @@ edition = "2024" description = "Shared storage layer for libchat" [dependencies] +crypto = { path = "../crypto" } thiserror = "2" rusqlite = { version = "0.35", features = ["bundled-sqlcipher-vendored-openssl"] } diff --git a/core/storage/src/lib.rs b/core/storage/src/lib.rs index 9240dc2..7854355 100644 --- a/core/storage/src/lib.rs +++ b/core/storage/src/lib.rs @@ -7,9 +7,14 @@ mod errors; mod sqlite; +mod store; pub use errors::StorageError; pub use sqlite::{SqliteDb, StorageConfig}; +pub use store::{ + ChatStore, ConversationKind, ConversationMeta, ConversationStore, EphemeralKeyStore, + IdentityStore, +}; // Re-export rusqlite types that domain crates will need pub use rusqlite::{Connection, Error as RusqliteError, Transaction, params}; diff --git a/core/conversations/src/store.rs b/core/storage/src/store.rs similarity index 96% rename from core/conversations/src/store.rs rename to core/storage/src/store.rs index 8187bde..299660d 100644 --- a/core/conversations/src/store.rs +++ b/core/storage/src/store.rs @@ -1,7 +1,6 @@ -use crypto::PrivateKey; -use storage::StorageError; +use crypto::{Identity, PrivateKey}; -use crate::identity::Identity; +use crate::StorageError; /// Persistence operations for installation identity data. pub trait IdentityStore {