Update key package functionality (#20)

* update key package functionality

* remove local storage

* rebase with fixing error
This commit is contained in:
Ekaterina Broslavskaya
2024-07-25 10:20:58 +03:00
committed by GitHub
parent e5d798f986
commit ebeabffd80
5 changed files with 90 additions and 123 deletions

View File

@@ -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<u8>, KeyPackage)` tuples,
@@ -23,6 +23,7 @@ impl UserKeyPackages {
pub struct UserInfo {
pub id: Vec<u8>,
pub key_packages: UserKeyPackages,
pub key_packages_hash: HashSet<Vec<u8>>,
pub sign_pk: Vec<u8>,
}
@@ -54,22 +55,6 @@ pub trait SCKeyStoreService {
) -> impl std::future::Future<Output = Result<KeyPackage, KeyStoreError>>;
}
pub trait LocalKeyStoreService {
fn empty_key_store(id: &[u8]) -> Self;
fn load_to_smart_contract<T: SCKeyStoreService>(
&self,
sc: &mut T,
) -> impl std::future::Future<Output = Result<(), KeyStoreError>>;
fn get_update_from_smart_contract<T: SCKeyStoreService>(
&mut self,
sc: T,
crypto: &MlsCryptoProvider,
) -> impl std::future::Future<Output = Result<(), KeyStoreError>>;
fn get_avaliable_kp(&mut self) -> Result<KeyPackage, KeyStoreError>;
}
#[derive(Debug, thiserror::Error)]
pub enum KeyStoreError {
#[error("User doesn't exist")]

View File

@@ -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<Vec<u8>>,
}
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<T: SCKeyStoreService>(
&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<T: SCKeyStoreService>(
&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<KeyPackage, KeyStoreError> {
match self.user_info.key_packages.0.pop() {
Some(c) => Ok(c.1),
None => Err(KeyStoreError::InvalidUserDataError(
"No more keypackage available".to_string(),
)),
}
}
}

View File

@@ -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<UserKeyPackages> for Vec<KeyPackage> {
fn from(ukp: UserKeyPackages) -> Self {
let mut res: Vec<KeyPackage> = 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<T: Transport + Clone, P: Provider<T, N>, N: Network> SCKeyStoreService
for &mut ScKeyStorage<T, P, N>
{
@@ -55,27 +68,33 @@ impl<T: Transport + Clone, P: Provider<T, N>, 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<Bytes> = 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<KeyPackage> = 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<T: Transport + Clone, P: Provider<T, N>, 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 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::<Vec<(Vec<u8>, mlsKeyPackage)>>());
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::<Vec<(Vec<u8>, 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());
}
}

View File

@@ -19,6 +19,7 @@ impl Identity {
ciphersuite: Ciphersuite,
crypto: &MlsCryptoProvider,
user_wallet_address: &[u8],
number_of_kp: usize,
) -> Result<Identity, IdentityError> {
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,
})

View File

@@ -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<T, P, N> {
pub groups: HashMap<String, Group>,
provider: MlsCryptoProvider,
sc_ks: ScKeyStorage<T, P, N>,
local_ks: LocalCache,
// pub(crate) contacts: HashMap<Vec<u8>, WakuPeers>,
}
@@ -65,12 +66,11 @@ where
sc_storage_address: Address,
) -> Result<Self, UserError> {
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();