// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // Copyright by contributors to this project. // SPDX-License-Identifier: (Apache-2.0 OR MIT)
//! Definitions to build a [`Client`]. //! //! See [`ClientBuilder`].
/// Base client configuration that is backed by SQLite storage. #[cfg(feature = "sqlite")] pubtype BaseSqlConfig = Config<
SqLiteKeyPackageStorage,
SqLitePreSharedKeyStorage,
SqLiteGroupStateStorage,
Missing,
DefaultMlsRules,
Missing,
>;
/// Builder for [`Client`] /// /// This is returned by [`Client::builder`] and allows to tweak settings the `Client` will use. At a /// minimum, the builder must be told the [`CryptoProvider`] and [`IdentityProvider`] to use. Other /// settings have default values. This means that the following /// methods must be called before [`ClientBuilder::build`]: /// /// - To specify the [`CryptoProvider`]: [`ClientBuilder::crypto_provider`] /// - To specify the [`IdentityProvider`]: [`ClientBuilder::identity_provider`] /// /// # Example /// /// ``` /// use mls_rs::{ /// Client, /// identity::{SigningIdentity, basic::{BasicIdentityProvider, BasicCredential}}, /// CipherSuite, /// }; /// /// use mls_rs_crypto_openssl::OpensslCryptoProvider; /// /// // Replace by code to load the certificate and secret key /// let secret_key = b"never hard-code secrets".to_vec().into(); /// let public_key = b"test invalid public key".to_vec().into(); /// let basic_identity = BasicCredential::new(b"name".to_vec()); /// let signing_identity = SigningIdentity::new(basic_identity.into_credential(), public_key); /// /// /// let _client = Client::builder() /// .crypto_provider(OpensslCryptoProvider::default()) /// .identity_provider(BasicIdentityProvider::new()) /// .signing_identity(signing_identity, secret_key, CipherSuite::CURVE25519_AES128) /// .build(); /// ``` /// /// # Spelling out a `Client` type /// /// There are two main ways to spell out a `Client` type if needed (e.g. function return type). /// /// The first option uses `impl MlsConfig`: /// ``` /// use mls_rs::{ /// Client, /// client_builder::MlsConfig, /// identity::{SigningIdentity, basic::{BasicIdentityProvider, BasicCredential}}, /// CipherSuite, /// }; /// /// use mls_rs_crypto_openssl::OpensslCryptoProvider; /// /// fn make_client() -> Client<impl MlsConfig> { /// // Replace by code to load the certificate and secret key /// let secret_key = b"never hard-code secrets".to_vec().into(); /// let public_key = b"test invalid public key".to_vec().into(); /// let basic_identity = BasicCredential::new(b"name".to_vec()); /// let signing_identity = SigningIdentity::new(basic_identity.into_credential(), public_key); /// /// Client::builder() /// .crypto_provider(OpensslCryptoProvider::default()) /// .identity_provider(BasicIdentityProvider::new()) /// .signing_identity(signing_identity, secret_key, CipherSuite::CURVE25519_AES128) /// .build() /// } ///``` /// /// The second option is more verbose and consists in writing the full `Client` type: /// ``` /// use mls_rs::{ /// Client, /// client_builder::{BaseConfig, WithIdentityProvider, WithCryptoProvider}, /// identity::{SigningIdentity, basic::{BasicIdentityProvider, BasicCredential}}, /// CipherSuite, /// }; /// /// use mls_rs_crypto_openssl::OpensslCryptoProvider; /// /// type MlsClient = Client< /// WithIdentityProvider< /// BasicIdentityProvider, /// WithCryptoProvider<OpensslCryptoProvider, BaseConfig>, /// >, /// >; /// /// fn make_client_2() -> MlsClient { /// // Replace by code to load the certificate and secret key /// let secret_key = b"never hard-code secrets".to_vec().into(); /// let public_key = b"test invalid public key".to_vec().into(); /// let basic_identity = BasicCredential::new(b"name".to_vec()); /// let signing_identity = SigningIdentity::new(basic_identity.into_credential(), public_key); /// /// Client::builder() /// .crypto_provider(OpensslCryptoProvider::default()) /// .identity_provider(BasicIdentityProvider::new()) /// .signing_identity(signing_identity, secret_key, CipherSuite::CURVE25519_AES128) /// .build() /// } /// /// ``` #[derive(Debug)] pubstruct ClientBuilder<C>(C);
impl<C: IntoConfig> ClientBuilder<C> { /// Add an extension type to the list of extension types supported by the client. pubfn extension_type(self, type_: ExtensionType) -> ClientBuilder<IntoConfigOutput<C>> { self.extension_types(Some(type_))
}
/// Add multiple extension types to the list of extension types supported by the client. pubfn extension_types<I>(self, types: I) -> ClientBuilder<IntoConfigOutput<C>> where
I: IntoIterator<Item = ExtensionType>,
{ letmut c = self.0.into_config();
c.0.settings.extension_types.extend(types);
ClientBuilder(c)
}
/// Add a custom proposal type to the list of proposals types supported by the client. pubfn custom_proposal_type(self, type_: ProposalType) -> ClientBuilder<IntoConfigOutput<C>> { self.custom_proposal_types(Some(type_))
}
/// Add multiple custom proposal types to the list of proposal types supported by the client. pubfn custom_proposal_types<I>(self, types: I) -> ClientBuilder<IntoConfigOutput<C>> where
I: IntoIterator<Item = ProposalType>,
{ letmut c = self.0.into_config();
c.0.settings.custom_proposal_types.extend(types);
ClientBuilder(c)
}
/// Add a protocol version to the list of protocol versions supported by the client. /// /// If no protocol version is explicitly added, the client will support all protocol versions /// supported by this crate. pubfn protocol_version(self, version: ProtocolVersion) -> ClientBuilder<IntoConfigOutput<C>> { self.protocol_versions(Some(version))
}
/// Add multiple protocol versions to the list of protocol versions supported by the client. /// /// If no protocol version is explicitly added, the client will support all protocol versions /// supported by this crate. pubfn protocol_versions<I>(self, versions: I) -> ClientBuilder<IntoConfigOutput<C>> where
I: IntoIterator<Item = ProtocolVersion>,
{ letmut c = self.0.into_config();
c.0.settings.protocol_versions.extend(versions);
ClientBuilder(c)
}
/// Add a key package extension to the list of key package extensions supported by the client. pubfn key_package_extension<T>( self,
extension: T,
) -> Result<ClientBuilder<IntoConfigOutput<C>>, ExtensionError> where
T: MlsExtension, Self: Sized,
{ letmut c = self.0.into_config();
c.0.settings.key_package_extensions.set_from(extension)?;
Ok(ClientBuilder(c))
}
/// Add multiple key package extensions to the list of key package extensions supported by the /// client. pubfn key_package_extensions( self,
extensions: ExtensionList,
) -> ClientBuilder<IntoConfigOutput<C>> { letmut c = self.0.into_config();
c.0.settings.key_package_extensions.append(extensions);
ClientBuilder(c)
}
/// Add a leaf node extension to the list of leaf node extensions supported by the client. pubfn leaf_node_extension<T>( self,
extension: T,
) -> Result<ClientBuilder<IntoConfigOutput<C>>, ExtensionError> where
T: MlsExtension, Self: Sized,
{ letmut c = self.0.into_config();
c.0.settings.leaf_node_extensions.set_from(extension)?;
Ok(ClientBuilder(c))
}
/// Add multiple leaf node extensions to the list of leaf node extensions supported by the /// client. pubfn leaf_node_extensions( self,
extensions: ExtensionList,
) -> ClientBuilder<IntoConfigOutput<C>> { letmut c = self.0.into_config();
c.0.settings.leaf_node_extensions.append(extensions);
ClientBuilder(c)
}
/// Set the lifetime duration in seconds of key packages generated by the client. pubfn key_package_lifetime(self, duration_in_s: u64) -> ClientBuilder<IntoConfigOutput<C>> { letmut c = self.0.into_config();
c.0.settings.lifetime_in_s = duration_in_s;
ClientBuilder(c)
}
/// Set the key package repository to be used by the client. /// /// By default, an in-memory repository is used. pubfn key_package_repo<K>(self, key_package_repo: K) -> ClientBuilder<WithKeyPackageRepo<K, C>> where
K: KeyPackageStorage,
{ let Config(c) = self.0.into_config();
/// Set the PSK store to be used by the client. /// /// By default, an in-memory store is used. pubfn psk_store<P>(self, psk_store: P) -> ClientBuilder<WithPskStore<P, C>> where
P: PreSharedKeyStorage,
{ let Config(c) = self.0.into_config();
/// Set the group state storage to be used by the client. /// /// By default, an in-memory storage is used. pubfn group_state_storage<G>( self,
group_state_storage: G,
) -> ClientBuilder<WithGroupStateStorage<G, C>> where
G: GroupStateStorage,
{ let Config(c) = self.0.into_config();
/// Set the identity validator to be used by the client. pubfn identity_provider<I>( self,
identity_provider: I,
) -> ClientBuilder<WithIdentityProvider<I, C>> where
I: IdentityProvider,
{ let Config(c) = self.0.into_config();
/// Set the crypto provider to be used by the client. pubfn crypto_provider<Cp>( self,
crypto_provider: Cp,
) -> ClientBuilder<WithCryptoProvider<Cp, C>> where
Cp: CryptoProvider,
{ let Config(c) = self.0.into_config();
/// Set the user-defined proposal rules to be used by the client. /// /// User-defined rules are used when sending and receiving commits before /// enforcing general MLS protocol rules. If the rule set returns an error when /// receiving a commit, the entire commit is considered invalid. If the /// rule set would return an error when sending a commit, individual proposals /// may be filtered out to compensate. pubfn mls_rules<Pr>(self, mls_rules: Pr) -> ClientBuilder<WithMlsRules<Pr, C>> where
Pr: MlsRules,
{ let Config(c) = self.0.into_config();
/// Set the protocol version used by the client. By default, the client uses version MLS 1.0 pubfn used_protocol_version( self,
version: ProtocolVersion,
) -> ClientBuilder<IntoConfigOutput<C>> { letmut c = self.0.into_config();
c.0.version = version;
ClientBuilder(c)
}
/// Set the signing identity used by the client as well as the matching signer and cipher suite. /// This must be called in order to create groups and key packages. pubfn signing_identity( self,
signing_identity: SigningIdentity,
signer: SignatureSecretKey,
cipher_suite: CipherSuite,
) -> ClientBuilder<IntoConfigOutput<C>> { letmut c = self.0.into_config();
c.0.signer = Some(signer);
c.0.signing_identity = Some((signing_identity, cipher_suite));
ClientBuilder(c)
}
/// Set the signer used by the client. This must be called in order to join groups. pubfn signer(self, signer: SignatureSecretKey) -> ClientBuilder<IntoConfigOutput<C>> { letmut c = self.0.into_config();
c.0.signer = Some(signer);
ClientBuilder(c)
}
if c.0.settings.protocol_versions.is_empty() {
c.0.settings.protocol_versions = ProtocolVersion::all().collect();
}
c
}
/// Build a client. /// /// See [`ClientBuilder`] documentation if the return type of this function needs to be spelled /// out. pubfn build(self) -> Client<IntoConfigOutput<C>> { letmut c = self.build_config(); let version = c.0.version; let signer = c.0.signer.take(); let signing_identity = c.0.signing_identity.take();
impl<C: IntoConfig<PskStore = InMemoryPreSharedKeyStorage>> ClientBuilder<C> { /// Add a PSK to the in-memory PSK store. pubfn psk( self,
psk_id: ExternalPskId,
psk: PreSharedKey,
) -> ClientBuilder<IntoConfigOutput<C>> { letmut c = self.0.into_config();
c.0.psk_store.insert(psk_id, psk);
ClientBuilder(c)
}
}
/// Marker type for required `ClientBuilder` services that have not been specified yet. #[derive(Debug)] pubstruct Missing;
/// Change the key package repository used by a client configuration. /// /// See [`ClientBuilder::key_package_repo`]. pubtype WithKeyPackageRepo<K, C> = Config<
K,
<C as IntoConfig>::PskStore,
<C as IntoConfig>::GroupStateStorage,
<C as IntoConfig>::IdentityProvider,
<C as IntoConfig>::MlsRules,
<C as IntoConfig>::CryptoProvider,
>;
/// Change the PSK store used by a client configuration. /// /// See [`ClientBuilder::psk_store`]. pubtype WithPskStore<P, C> = Config<
<C as IntoConfig>::KeyPackageRepository,
P,
<C as IntoConfig>::GroupStateStorage,
<C as IntoConfig>::IdentityProvider,
<C as IntoConfig>::MlsRules,
<C as IntoConfig>::CryptoProvider,
>;
/// Change the group state storage used by a client configuration. /// /// See [`ClientBuilder::group_state_storage`]. pubtype WithGroupStateStorage<G, C> = Config<
<C as IntoConfig>::KeyPackageRepository,
<C as IntoConfig>::PskStore,
G,
<C as IntoConfig>::IdentityProvider,
<C as IntoConfig>::MlsRules,
<C as IntoConfig>::CryptoProvider,
>;
/// Change the identity validator used by a client configuration. /// /// See [`ClientBuilder::identity_provider`]. pubtype WithIdentityProvider<I, C> = Config<
<C as IntoConfig>::KeyPackageRepository,
<C as IntoConfig>::PskStore,
<C as IntoConfig>::GroupStateStorage,
I,
<C as IntoConfig>::MlsRules,
<C as IntoConfig>::CryptoProvider,
>;
/// Change the proposal rules used by a client configuration. /// /// See [`ClientBuilder::mls_rules`]. pubtype WithMlsRules<Pr, C> = Config<
<C as IntoConfig>::KeyPackageRepository,
<C as IntoConfig>::PskStore,
<C as IntoConfig>::GroupStateStorage,
<C as IntoConfig>::IdentityProvider,
Pr,
<C as IntoConfig>::CryptoProvider,
>;
/// Change the crypto provider used by a client configuration. /// /// See [`ClientBuilder::crypto_provider`]. pubtype WithCryptoProvider<Cp, C> = Config<
<C as IntoConfig>::KeyPackageRepository,
<C as IntoConfig>::PskStore,
<C as IntoConfig>::GroupStateStorage,
<C as IntoConfig>::IdentityProvider,
<C as IntoConfig>::MlsRules,
Cp,
>;
/// Helper alias for `Config`. pubtype IntoConfigOutput<C> = Config<
<C as IntoConfig>::KeyPackageRepository,
<C as IntoConfig>::PskStore,
<C as IntoConfig>::GroupStateStorage,
<C as IntoConfig>::IdentityProvider,
<C as IntoConfig>::MlsRules,
<C as IntoConfig>::CryptoProvider,
>;
/// Helper alias to make a `Config` from a `ClientConfig` pubtype MakeConfig<C> = Config<
<C as ClientConfig>::KeyPackageRepository,
<C as ClientConfig>::PskStore,
<C as ClientConfig>::GroupStateStorage,
<C as ClientConfig>::IdentityProvider,
<C as ClientConfig>::MlsRules,
<C as ClientConfig>::CryptoProvider,
>;
impl<Kpr, Ps, Gss, Ip, Pr, Cp> ClientConfig for ConfigInner<Kpr, Ps, Gss, Ip, Pr, Cp> where
Kpr: KeyPackageStorage + Clone,
Ps: PreSharedKeyStorage + Clone,
Gss: GroupStateStorage + Clone,
Ip: IdentityProvider + Clone,
Pr: MlsRules + Clone,
Cp: CryptoProvider + Clone,
{ type KeyPackageRepository = Kpr; type PskStore = Ps; type GroupStateStorage = Gss; type IdentityProvider = Ip; type MlsRules = Pr; type CryptoProvider = Cp;
/// Helper trait to allow consuming crates to easily write a client type as `Client<impl MlsConfig>` /// /// It is not meant to be implemented by consuming crates. `T: MlsConfig` implies `T: ClientConfig`. pubtrait MlsConfig: Clone + Send + Sync + Sealed { #[doc(hidden)] type Output: ClientConfig;
#[doc(hidden)] fn get(&self) -> &Self::Output;
}
/// Blanket implementation so that `T: MlsConfig` implies `T: ClientConfig` impl<T: MlsConfig> ClientConfig for T { type KeyPackageRepository = <T::Output as ClientConfig>::KeyPackageRepository; type PskStore = <T::Output as ClientConfig>::PskStore; type GroupStateStorage = <T::Output as ClientConfig>::GroupStateStorage; type IdentityProvider = <T::Output as ClientConfig>::IdentityProvider; type MlsRules = <T::Output as ClientConfig>::MlsRules; type CryptoProvider = <T::Output as ClientConfig>::CryptoProvider;
/// Definitions meant to be private that are inaccessible outside this crate. They need to be marked /// `pub` because they appear in public definitions. mod private { use mls_rs_core::{
crypto::{CipherSuite, SignatureSecretKey},
identity::SigningIdentity,
protocol_version::ProtocolVersion,
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.