diff --git a/sc_key_store/src/lib.rs b/sc_key_store/src/lib.rs index 8b63dd9..2e4efb2 100644 --- a/sc_key_store/src/lib.rs +++ b/sc_key_store/src/lib.rs @@ -1,8 +1,8 @@ -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 +23,7 @@ impl UserKeyPackages { pub struct UserInfo { pub id: Vec, pub key_packages: UserKeyPackages, + pub key_packages_hash: HashSet>, pub sign_pk: Vec, } @@ -54,22 +55,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 deleted file mode 100644 index af7a7d8..0000000 --- a/sc_key_store/src/local_ks.rs +++ /dev/null @@ -1,52 +0,0 @@ -use std::collections::HashSet; - -use mls_crypto::openmls_provider::MlsCryptoProvider; -use openmls::prelude::KeyPackage; - -use crate::{KeyStoreError, LocalKeyStoreService, SCKeyStoreService, UserInfo, UserKeyPackages}; - -pub struct LocalCache { - user_info: UserInfo, - // map of reserved key_packages [group_id, key_package_hash] - pub reserved_key_pkg_hash: HashSet>, -} - -impl LocalKeyStoreService for LocalCache { - fn empty_key_store(id: &[u8]) -> Self { - LocalCache { - user_info: UserInfo { - id: id.to_vec(), - key_packages: UserKeyPackages::default(), - sign_pk: Vec::with_capacity(32), - }, - reserved_key_pkg_hash: HashSet::new(), - } - } - - async fn load_to_smart_contract( - &self, - sc: &mut T, - ) -> Result<(), KeyStoreError> { - sc.add_user_kp(&self.user_info.id, self.user_info.key_packages.clone()) - .await - } - - 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); - Ok(()) - } - - fn get_avaliable_kp(&mut self) -> Result { - match self.user_info.key_packages.0.pop() { - Some(c) => Ok(c.1), - None => Err(KeyStoreError::InvalidUserDataError( - "No more keypackage available".to_string(), - )), - } - } -} diff --git a/sc_key_store/src/sc_ks.rs b/sc_key_store/src/sc_ks.rs index 5d377c7..c4ed942 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 { @@ -55,27 +68,33 @@ impl, N: Network> SCKeyStoreService "no key packages".to_string(), )); } - if self - .does_user_exist(ukp.get_id_from_kp().as_slice()) - .await? - { + let user_id = ukp.get_id_from_kp(); + if self.does_user_exist(user_id.as_slice()).await? { 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( + Address::from_slice(user_id.as_slice()), + 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..082f76a 100644 --- a/src/user.rs +++ b/src/user.rs @@ -22,13 +22,15 @@ 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 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 +50,6 @@ pub struct User { pub groups: HashMap, provider: MlsCryptoProvider, sc_ks: ScKeyStorage, - local_ks: LocalCache, // pub(crate) contacts: HashMap, WakuPeers>, } @@ -65,12 +66,11 @@ 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 mut user = User { groups: HashMap::new(), identity: id, provider: crypto, - local_ks: LocalCache::empty_key_store(user_wallet_address), sc_ks: ScKeyStorage::new(provider, sc_storage_address), // contacts: HashMap::new(), }; @@ -115,13 +115,10 @@ 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?; Ok(()) } @@ -293,6 +290,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();