mirror of
https://github.com/vacp2p/de-mls.git
synced 2026-01-09 21:48:02 -05:00
Update key package functionality (#20)
* update key package functionality * remove local storage * rebase with fixing error
This commit is contained in:
committed by
GitHub
parent
e5d798f986
commit
ebeabffd80
@@ -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")]
|
||||
|
||||
@@ -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(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
16
src/user.rs
16
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<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();
|
||||
|
||||
Reference in New Issue
Block a user