diff --git a/conversations/src/identity.rs b/conversations/src/identity.rs index 76c2700..8ca27be 100644 --- a/conversations/src/identity.rs +++ b/conversations/src/identity.rs @@ -24,6 +24,13 @@ impl Identity { } } + pub fn from_secret(name: impl Into, secret: PrivateKey) -> Self { + Self { + name: name.into(), + secret, + } + } + pub fn public_key(&self) -> PublicKey { PublicKey::from(&self.secret) } diff --git a/conversations/src/storage/db.rs b/conversations/src/storage/db.rs index 3bd0085..84ced02 100644 --- a/conversations/src/storage/db.rs +++ b/conversations/src/storage/db.rs @@ -12,6 +12,7 @@ const CHAT_SCHEMA: &str = " -- Identity table (single row) CREATE TABLE IF NOT EXISTS identity ( id INTEGER PRIMARY KEY CHECK (id = 1), + name TEXT NOT NULL, secret_key BLOB NOT NULL ); @@ -61,10 +62,12 @@ impl ChatStorage { /// Saves the identity (secret key). pub fn save_identity(&mut self, identity: &Identity) -> Result<(), StorageError> { - let record = IdentityRecord::from(identity); self.db.connection().execute( - "INSERT OR REPLACE INTO identity (id, secret_key) VALUES (1, ?1)", - params![record.secret_key.as_slice()], + "INSERT OR REPLACE INTO identity (id, name, secret_key) VALUES (1, ?1, ?2)", + params![ + identity.get_name(), + identity.secret().DANGER_to_bytes().as_slice() + ], )?; Ok(()) } @@ -74,19 +77,23 @@ impl ChatStorage { let mut stmt = self .db .connection() - .prepare("SELECT secret_key FROM identity WHERE id = 1")?; + .prepare("SELECT name, secret_key FROM identity WHERE id = 1")?; let result = stmt.query_row([], |row| { - let secret_key: Vec = row.get(0)?; - Ok(secret_key) + let name: String = row.get(0)?; + let secret_key: Vec = row.get(1)?; + Ok((name, secret_key)) }); match result { - Ok(secret_key) => { + Ok((name, secret_key)) => { let bytes: [u8; 32] = secret_key .try_into() .map_err(|_| StorageError::InvalidData("Invalid secret key length".into()))?; - let record = IdentityRecord { secret_key: bytes }; + let record = IdentityRecord { + name, + secret_key: bytes, + }; Ok(Some(Identity::from(record))) } Err(RusqliteError::QueryReturnedNoRows) => Ok(None), @@ -229,13 +236,13 @@ mod tests { assert!(storage.load_identity().unwrap().is_none()); // Save identity - let identity = Identity::new(); - let address = identity.address(); + let identity = Identity::new("default"); + let pubkey = identity.public_key(); storage.save_identity(&identity).unwrap(); // Load identity let loaded = storage.load_identity().unwrap().unwrap(); - assert_eq!(loaded.address(), address); + assert_eq!(loaded.public_key(), pubkey); } #[test] diff --git a/conversations/src/storage/types.rs b/conversations/src/storage/types.rs index 553ac1b..bc0fa95 100644 --- a/conversations/src/storage/types.rs +++ b/conversations/src/storage/types.rs @@ -3,13 +3,16 @@ //! Note: Ratchet state types (RatchetStateRecord, SkippedKeyRecord) are in //! double_ratchets::storage module and handled by RatchetStorage. -use x25519_dalek::{PublicKey, StaticSecret}; +use x25519_dalek::PublicKey; +use crate::crypto::PrivateKey; use crate::identity::Identity; /// Record for storing identity (secret key). #[derive(Debug)] pub struct IdentityRecord { + /// The identity name. + pub name: String, /// The secret key bytes (32 bytes). pub secret_key: [u8; 32], } @@ -17,15 +20,16 @@ pub struct IdentityRecord { impl From<&Identity> for IdentityRecord { fn from(identity: &Identity) -> Self { Self { - secret_key: identity.secret().to_bytes(), + name: identity.get_name().to_string(), + secret_key: identity.secret().DANGER_to_bytes(), } } } impl From for Identity { fn from(record: IdentityRecord) -> Self { - let secret = StaticSecret::from(record.secret_key); - Identity::from_secret(secret) + let secret = PrivateKey::from(record.secret_key); + Identity::from_secret(record.name, secret) } } diff --git a/storage/src/errors.rs b/storage/src/errors.rs index 1410f85..9d65d64 100644 --- a/storage/src/errors.rs +++ b/storage/src/errors.rs @@ -26,6 +26,10 @@ pub enum StorageError { /// Transaction error. #[error("transaction error: {0}")] Transaction(String), + + /// Invalid data error. + #[error("invalid data: {0}")] + InvalidData(String), } impl From for StorageError {