diff --git a/core/conversations/src/conversation.rs b/core/conversations/src/conversation.rs index 3581eba..69a1137 100644 --- a/core/conversations/src/conversation.rs +++ b/core/conversations/src/conversation.rs @@ -2,6 +2,7 @@ mod direct_v1; pub mod group_v1; mod group_v2; pub mod mls_extensions; +mod mls_utils; pub use crate::errors::ChatError; use crate::outcomes::ConvoOutcome; @@ -11,6 +12,7 @@ use crate::types::ConvoMetadata; pub use direct_v1::DirectV1Convo; pub use group_v1::GroupV1Convo; pub use group_v2::{GroupV2Clock, GroupV2Convo}; +pub use mls_utils::UnverifiedSender; use shared_traits::IdentIdRef; pub type ConversationId = String; @@ -47,7 +49,7 @@ pub(crate) trait GroupConvo: Convo + std::fmt::Debug + S /// Each current member's MLS leaf-credential content (hex-encoded), self /// included. - fn members(&self) -> Result>, ChatError>; + fn members(&self) -> Result, ChatError>; // All GroupConvos MUST return ConvoMetadata // the return type is Option<_> to support legacy ConvoTypes which // are being phased out. diff --git a/core/conversations/src/conversation/group_v1.rs b/core/conversations/src/conversation/group_v1.rs index af64e98..a87e5f9 100644 --- a/core/conversations/src/conversation/group_v1.rs +++ b/core/conversations/src/conversation/group_v1.rs @@ -13,7 +13,7 @@ use std::collections::VecDeque; use tracing::debug; use crate::conversation::ConversationIdRef; -use crate::conversation::mls_utils::signer_for_sender; +use crate::conversation::mls_utils::{UnverifiedSender, signer_for_sender}; use crate::inbox_v2::MlsProvider; use crate::service_context::{ExternalServices, ServiceContext}; @@ -349,11 +349,11 @@ impl GroupConvo for GroupV1Convo { self.send_payload(cx, commit.to_bytes()?) } - fn members(&self) -> Result>, ChatError> { + fn members(&self) -> Result, ChatError> { Ok(self .mls_group .members() - .map(|m| m.credential.serialized_content().to_vec()) + .map(|m| UnverifiedSender::from(m)) .collect()) } diff --git a/core/conversations/src/conversation/group_v2.rs b/core/conversations/src/conversation/group_v2.rs index 7929bdf..d940c91 100644 --- a/core/conversations/src/conversation/group_v2.rs +++ b/core/conversations/src/conversation/group_v2.rs @@ -25,13 +25,13 @@ use openmls::prelude::tls_codec::Deserialize as _; use openmls::prelude::{KeyPackageIn, OpenMlsProvider as _, ProtocolVersion}; use openmls_traits::crypto::OpenMlsCrypto; use prost::Message; -use shared_traits::{IdentId, IdentIdRef}; +use shared_traits::{IdentId, IdentIdRef, SignerId}; use std::sync::Arc; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use tracing::{info, instrument}; use crate::IdentityProvider; -use crate::conversation::{ConversationIdRef, ExternalServices, ServiceContext}; +use crate::conversation::{ConversationIdRef, ExternalServices, ServiceContext, UnverifiedSender}; use crate::{ ConvoOutcome, DeliveryService, RegistrationService, conversation::{ChatError, Convo, GroupConvo, Identified}, @@ -376,13 +376,22 @@ where result.and(flushed) } - fn members(&self) -> Result>, ChatError> { + fn members(&self) -> Result, ChatError> { // Guarantee the local member is listed so callers see the full roster. let mut members = self.conversation.members()?; let self_id = self.conversation.member_id_bytes().to_vec(); if !members.contains(&self_id) { members.push(self_id); } + + let members = members + .into_iter() + .map(|cred| UnverifiedSender { + // TODO: (!) Replace is actual SenderId. + signer_id: SignerId::from(b"".as_slice()), + cred, + }) + .collect(); Ok(members) } diff --git a/core/conversations/src/conversation/mls_utils.rs b/core/conversations/src/conversation/mls_utils.rs index ca6ce41..16ca194 100644 --- a/core/conversations/src/conversation/mls_utils.rs +++ b/core/conversations/src/conversation/mls_utils.rs @@ -1,7 +1,9 @@ use openmls::{ + credentials::CredentialType, framing::{ProcessedMessage, Sender}, - group::MlsGroup, + group::{Member, MlsGroup}, }; +use tracing::warn; use crate::{ChatError, SignerId}; @@ -25,3 +27,22 @@ pub fn signer_for_sender( }; Ok(sender_sig_key.into()) } + +#[derive(Debug, Clone)] +pub struct UnverifiedSender { + pub signer_id: SignerId, + pub cred: Vec, +} + +impl From for UnverifiedSender { + fn from(value: Member) -> Self { + if CredentialType::Basic != value.credential.credential_type() { + warn!(credtype = ?value.credential, "Incorrect credentialType"); + }; + + let cred = value.credential.serialized_content().to_vec(); + let signer_id = SignerId::from(value.signature_key); + + Self { signer_id, cred } + } +} diff --git a/core/conversations/src/core.rs b/core/conversations/src/core.rs index 803858e..182a429 100644 --- a/core/conversations/src/core.rs +++ b/core/conversations/src/core.rs @@ -1,6 +1,6 @@ use crate::causal_history::{CausalHistoryStore, MissingMessage}; use crate::conversation::{ - ConversationIdRef, DirectV1Convo, GroupV1Convo, GroupV2Convo, Identified, + ConversationIdRef, DirectV1Convo, GroupV1Convo, GroupV2Convo, Identified, UnverifiedSender, }; use crate::service_context::{ExternalServices, ServiceContext}; use crate::service_traits::AuthVerifyService; @@ -294,7 +294,7 @@ impl<'a, S: ExternalServices + 'static> Core { /// Each member's MLS leaf-credential content (hex-encoded); errors if /// `convo_id` names a direct (non-group) conversation. - pub fn group_members(&mut self, convo_id: &str) -> Result>, ChatError> { + pub fn group_members(&mut self, convo_id: &str) -> Result, ChatError> { if self.cached_convos.contains_key(convo_id) { let convo = self .cached_convos diff --git a/core/conversations/src/lib.rs b/core/conversations/src/lib.rs index fa0504b..0a22ca8 100644 --- a/core/conversations/src/lib.rs +++ b/core/conversations/src/lib.rs @@ -13,7 +13,7 @@ mod utils; pub use causal_history::{Frontier, MissingMessage}; pub use chat_sqlite::ChatStorage; pub use chat_sqlite::StorageConfig; -pub use conversation::GroupV2Clock; +pub use conversation::{GroupV2Clock, UnverifiedSender}; pub use core::{ConversationId, Core}; /// Timing/policy for GroupV2 conversations (de-mls's per-conversation config). /// Defaults to the de-mls library defaults; inject via diff --git a/core/conversations/src/service_traits.rs b/core/conversations/src/service_traits.rs index cbd4f29..0aae08e 100644 --- a/core/conversations/src/service_traits.rs +++ b/core/conversations/src/service_traits.rs @@ -12,10 +12,11 @@ use crate::{ConversationId, types::AddressedEnvelope}; /// An AuthVerifyService is responsible for verifying that a provided Credential is valid /// for the given signer. Implementations must return AuthResult::Valid only if the two can /// be cryptogrpahically bound together. -pub trait AuthVerifyService: Debug { +pub trait AuthVerifyService: Debug + Clone { fn validate(&self, signer: &[u8], credential: &[u8]) -> AuthResult; } +#[derive(Debug, PartialEq)] pub enum AuthResult { Valid, Mismatch,