diff --git a/sc_key_store/src/lib.rs b/sc_key_store/src/lib.rs index 8b63dd9..4331a68 100644 --- a/sc_key_store/src/lib.rs +++ b/sc_key_store/src/lib.rs @@ -1,8 +1,9 @@ -pub mod local_ks; +// pub mod local_ks; pub mod sc_ks; use mls_crypto::openmls_provider::MlsCryptoProvider; use openmls::prelude::*; +use std::collections::HashSet; /// The DS returns a list of key packages for a user as `UserKeyPackages`. /// This is a tuple struct holding a vector of `(Vec, KeyPackage)` tuples, @@ -23,6 +24,7 @@ impl UserKeyPackages { pub struct UserInfo { pub id: Vec, pub key_packages: UserKeyPackages, + pub key_packages_hash: HashSet>, pub sign_pk: Vec, } @@ -54,22 +56,6 @@ pub trait SCKeyStoreService { ) -> impl std::future::Future>; } -pub trait LocalKeyStoreService { - fn empty_key_store(id: &[u8]) -> Self; - - fn load_to_smart_contract( - &self, - sc: &mut T, - ) -> impl std::future::Future>; - fn get_update_from_smart_contract( - &mut self, - sc: T, - crypto: &MlsCryptoProvider, - ) -> impl std::future::Future>; - - fn get_avaliable_kp(&mut self) -> Result; -} - #[derive(Debug, thiserror::Error)] pub enum KeyStoreError { #[error("User doesn't exist")] diff --git a/sc_key_store/src/local_ks.rs b/sc_key_store/src/local_ks.rs index af7a7d8..ccab6f7 100644 --- a/sc_key_store/src/local_ks.rs +++ b/sc_key_store/src/local_ks.rs @@ -3,7 +3,7 @@ use std::collections::HashSet; use mls_crypto::openmls_provider::MlsCryptoProvider; use openmls::prelude::KeyPackage; -use crate::{KeyStoreError, LocalKeyStoreService, SCKeyStoreService, UserInfo, UserKeyPackages}; +use crate::{KeyStoreError, SCKeyStoreService, UserInfo, UserKeyPackages}; pub struct LocalCache { user_info: UserInfo, @@ -11,18 +11,26 @@ pub struct LocalCache { pub reserved_key_pkg_hash: HashSet>, } -impl LocalKeyStoreService for LocalCache { - fn empty_key_store(id: &[u8]) -> Self { +impl LocalCache { + fn empty_key_store(id: &[u8], sign_pk: &[u8]) -> Self { LocalCache { user_info: UserInfo { id: id.to_vec(), key_packages: UserKeyPackages::default(), - sign_pk: Vec::with_capacity(32), + key_packages_hash: HashSet::default(), + sign_pk: sign_pk.to_vec(), }, reserved_key_pkg_hash: HashSet::new(), } } + fn fill_empty_key_store(&mut self, ukp: UserKeyPackages) -> Result<(), KeyStoreError> { + let ukp_hash: HashSet> = ukp.0.iter().map(|(k, _)| k.to_owned()).collect(); + self.user_info.key_packages.clone_from(&ukp); + self.user_info.key_packages_hash.clone_from(&ukp_hash); + Ok(()) + } + async fn load_to_smart_contract( &self, sc: &mut T, @@ -31,13 +39,18 @@ impl LocalKeyStoreService for LocalCache { .await } + // TODO: add a check if the key has been deleted and update the local data async fn get_update_from_smart_contract( &mut self, sc: T, crypto: &MlsCryptoProvider, ) -> Result<(), KeyStoreError> { let info = sc.get_user(&self.user_info.id, crypto).await?; - self.user_info.key_packages.clone_from(&info.key_packages); + let ukp_from_sc = &info.key_packages; + let ukp_hash: HashSet> = ukp_from_sc.0.iter().map(|(k, _)| k.to_owned()).collect(); + + self.user_info.key_packages.clone_from(ukp_from_sc); + self.reserved_key_pkg_hash.clone_from(&ukp_hash); Ok(()) } diff --git a/sc_key_store/src/sc_ks.rs b/sc_key_store/src/sc_ks.rs index 5d377c7..d252ecc 100644 --- a/sc_key_store/src/sc_ks.rs +++ b/sc_key_store/src/sc_ks.rs @@ -13,7 +13,7 @@ use openmls::{ prelude::{KeyPackage as mlsKeyPackage, TlsDeserializeTrait, TlsSerializeTrait}, versions::ProtocolVersion, }; -use std::str::FromStr; +use std::{collections::HashSet, str::FromStr}; use crate::UserInfo; use crate::UserKeyPackages; @@ -36,6 +36,19 @@ where } } +impl From for Vec { + fn from(ukp: UserKeyPackages) -> Self { + let mut res: Vec = Vec::with_capacity(ukp.0.len()); + for kp in ukp.0 { + let bytes = kp.1.tls_serialize_detached().unwrap(); + let kp_bytes = Bytes::copy_from_slice(bytes.as_slice()); + let kp_sc: KeyPackage = KeyPackage::from((vec![kp_bytes],)); + res.push(kp_sc) + } + res + } +} + impl, N: Network> SCKeyStoreService for &mut ScKeyStorage { @@ -62,20 +75,26 @@ impl, N: Network> SCKeyStoreService return Err(KeyStoreError::AlreadyExistedUserError); } - let mut kp_bytes: Vec = Vec::with_capacity(ukp.0.len()); - for kp in ukp.0 { - let bytes = kp.1.tls_serialize_detached()?; - kp_bytes.push(Bytes::copy_from_slice(bytes.as_slice())) - } - - let kp: KeyPackage = KeyPackage::from((kp_bytes,)); - let add_user_binding = self.instance.addUser(Bytes::copy_from_slice(sign_pk), kp); - let res = add_user_binding.send().await; - - match res { - Ok(_) => Ok(()), - Err(err) => Err(KeyStoreError::AlloyError(err)), + let ukp_sc: Vec = ukp.into(); + for (i, kp_sc) in ukp_sc.iter().enumerate() { + if i == 0 { + let add_user_binding = self + .instance + .addUser(Bytes::copy_from_slice(sign_pk), kp_sc.to_owned()); + let res = add_user_binding.send().await; + match res { + Ok(_) => continue, + Err(err) => return Err(KeyStoreError::AlloyError(err)), + } + } + let add_kp_binding = self.instance.addKeyPackage(kp_sc.to_owned()); + let res = add_kp_binding.send().await; + match res { + Ok(_) => continue, + Err(err) => return Err(KeyStoreError::AlloyError(err)), + } } + Ok(()) } async fn get_user( @@ -94,6 +113,7 @@ impl, N: Network> SCKeyStoreService let mut user = UserInfo { id: id.to_vec(), key_packages: UserKeyPackages::default(), + key_packages_hash: HashSet::default(), sign_pk: user._0.signaturePubKey.to_vec(), }; @@ -209,22 +229,24 @@ mod test { }; signature_keys.store(crypto.key_store()).unwrap(); - let key_package = mlsKeyPackage::builder() - .build( - CryptoConfig { - ciphersuite, - version: ProtocolVersion::default(), - }, - crypto, - &signature_keys, - credential_with_key.clone(), - ) - .unwrap(); - - let kp = key_package.hash_ref(crypto.crypto()).unwrap(); - - let mut kpgs = HashMap::from([(kp.as_slice().to_vec(), key_package)]); - let ukp = UserKeyPackages(kpgs.drain().collect::, mlsKeyPackage)>>()); + let mut kps = HashMap::new(); + for _ in 0..3 { + let key_package = mlsKeyPackage::builder() + .build( + CryptoConfig { + ciphersuite, + version: ProtocolVersion::default(), + }, + crypto, + &signature_keys, + credential_with_key.clone(), + ) + .unwrap(); + let kp = key_package.hash_ref(crypto.crypto()).unwrap(); + kps.insert(kp.as_slice().to_vec(), key_package); + } + let ukp = UserKeyPackages(kps.drain().collect::, mlsKeyPackage)>>()); + (ukp, signature_keys) } @@ -257,7 +279,16 @@ mod test { let res = storage .get_avaliable_user_kp(alice_address.as_slice(), &crypto) .await; - println!("Get user kp: {:#?}", res); + // println!("Get user kp: {:#?}", res); assert!(res.is_ok()); + + let res2 = storage + .get_avaliable_user_kp(alice_address.as_slice(), &crypto) + .await; + // println!("Get user kp: {:#?}", res); + assert!(res.is_ok()); + + // HERE SHOULD BE NOT EQUAL + assert_ne!(res.unwrap(), res2.unwrap()); } } diff --git a/src/identity.rs b/src/identity.rs index a57d7a2..79b0bbf 100644 --- a/src/identity.rs +++ b/src/identity.rs @@ -19,6 +19,7 @@ impl Identity { ciphersuite: Ciphersuite, crypto: &MlsCryptoProvider, user_wallet_address: &[u8], + number_of_kp: usize, ) -> Result { let credential = Credential::new(user_wallet_address.to_vec(), CredentialType::Basic)?; let signature_keys = SignatureKeyPair::new(ciphersuite.signature_algorithm())?; @@ -28,19 +29,23 @@ impl Identity { }; signature_keys.store(crypto.key_store())?; - let key_package = KeyPackage::builder().build( - CryptoConfig { - ciphersuite, - version: ProtocolVersion::default(), - }, - crypto, - &signature_keys, - credential_with_key.clone(), - )?; + let mut kps = HashMap::new(); + for _ in 0..number_of_kp { + let key_package = KeyPackage::builder().build( + CryptoConfig { + ciphersuite, + version: ProtocolVersion::default(), + }, + crypto, + &signature_keys, + credential_with_key.clone(), + )?; + let kp = key_package.hash_ref(crypto.crypto())?; + kps.insert(kp.as_slice().to_vec(), key_package); + } - let kp = key_package.hash_ref(crypto.crypto())?; Ok(Identity { - kp: HashMap::from([(kp.as_slice().to_vec(), key_package)]), + kp: kps, credential_with_key, signer: signature_keys, }) diff --git a/src/user.rs b/src/user.rs index 6656e84..06ff301 100644 --- a/src/user.rs +++ b/src/user.rs @@ -22,13 +22,16 @@ use tokio::sync::broadcast::Receiver; use ds::ds::*; use mls_crypto::openmls_provider::*; -use sc_key_store::{local_ks::LocalCache, sc_ks::ScKeyStorage, *}; +use sc_key_store::{sc_ks::ScKeyStorage, *}; +// use sc_key_store::local_ks::LocalCache; // use waku_bindings::*; // use crate::conversation::*; use crate::identity::{Identity, IdentityError}; +const NUMBER_OF_KP: usize = 2; + pub struct Group { group_name: String, conversation: Conversation, @@ -48,7 +51,8 @@ pub struct User { pub groups: HashMap, provider: MlsCryptoProvider, sc_ks: ScKeyStorage, - local_ks: LocalCache, + // we don't need local storage as long as we are working with openmls + // local_ks: LocalCache, // pub(crate) contacts: HashMap, WakuPeers>, } @@ -65,12 +69,13 @@ where sc_storage_address: Address, ) -> Result { let crypto = MlsCryptoProvider::default(); - let id = Identity::new(CIPHERSUITE, &crypto, user_wallet_address)?; + let id = Identity::new(CIPHERSUITE, &crypto, user_wallet_address, NUMBER_OF_KP)?; + // let sign_pk = id.signature_pub_key(); let mut user = User { groups: HashMap::new(), identity: id, provider: crypto, - local_ks: LocalCache::empty_key_store(user_wallet_address), + // local_ks: LocalCache::empty_key_store(user_wallet_address, sign_pk.as_slice()), sc_ks: ScKeyStorage::new(provider, sc_storage_address), // contacts: HashMap::new(), }; @@ -115,14 +120,12 @@ where } async fn register(&mut self) -> Result<(), UserError> { - let kp = self.key_packages(); + let ukp = self.key_packages(); self.sc_ks .borrow_mut() - .add_user(kp, self.identity.signer.public()) - .await?; - self.local_ks - .get_update_from_smart_contract(self.sc_ks.borrow_mut(), &self.provider) + .add_user(ukp.clone(), self.identity.signature_pub_key().as_slice()) .await?; + // self.local_ks.fill_empty_key_store(ukp)?; Ok(()) } @@ -293,6 +296,7 @@ where .use_ratchet_tree_extension(true) .build(); + // TODO: After we move from openmls, we will have to delete the used key package here ourselves. let mls_group = MlsGroup::new_from_welcome(&self.provider, &group_config, welcome, None)?; let group_id = mls_group.group_id().to_vec();