Skip to main content

core_crypto/mls/
external_sender.rs

1use openmls::{
2    extensions::ExternalSender as MlsExternalSender,
3    prelude::{Credential as MlsCredential, OpenMlsCrypto as _, OpenMlsSignaturePublicKey, SignatureScheme},
4};
5use rusty_jwt_tools::prelude::parse_json_jwk;
6
7use crate::{Error, OpenMlsError, Result, mls_provider::CRYPTO};
8
9const WIRE_SERVER_IDENTITY: &str = "wire-server";
10
11/// A RFC 9420 External Sender
12///
13/// This can be used to initialize a subconversation.
14#[derive(
15    Debug, Clone, PartialEq, Eq, derive_more::From, derive_more::Into, derive_more::Deref, derive_more::DerefMut,
16)]
17pub struct ExternalSender(pub(crate) MlsExternalSender);
18
19impl ExternalSender {
20    /// Serialize this external sender into a byte vector.
21    ///
22    /// This produces the public key and matches [`Self::parse_public_key`].
23    pub fn serialize(&self) -> Vec<u8> {
24        self.0.signature_key().as_slice().to_vec()
25    }
26
27    /// Parse an external sender given a JWK.
28    ///
29    /// This expects a raw json serialized JWK. It works with any Signature scheme.
30    pub fn parse_jwk(jwk: &[u8]) -> Result<ExternalSender> {
31        let pk = parse_json_jwk(jwk)?;
32        Ok(MlsExternalSender::new(pk.into(), MlsCredential::new_basic(WIRE_SERVER_IDENTITY.into())).into())
33    }
34
35    /// Parse an external sender given a raw public key.
36    ///
37    /// This supports the legacy behaviour where the server was providing the external sender public key
38    /// raw.
39    // TODO: remove at some point when the backend API is not used anymore. Tracking issue: WPB-9614
40    pub fn parse_public_key(key: &[u8], signature_scheme: SignatureScheme) -> Result<ExternalSender> {
41        CRYPTO
42            .validate_signature_key(signature_scheme, key)
43            .map_err(OpenMlsError::wrap("validating signature key"))?;
44        let key = OpenMlsSignaturePublicKey::new(key.into(), signature_scheme)
45            .map_err(OpenMlsError::wrap("creating new signature public key"))?;
46        Ok(MlsExternalSender::new(key.into(), MlsCredential::new_basic(WIRE_SERVER_IDENTITY.into())).into())
47    }
48
49    /// Parse an external sender.
50    ///
51    /// This first attempts to parse this as a JWK per `parse_jwk`,
52    /// and falls back to `parse_public_key` if the former method fails.
53    pub fn parse(key: &[u8], signature_scheme: SignatureScheme) -> Result<ExternalSender> {
54        Self::parse_jwk(key).or_else(|_| Self::parse_public_key(key, signature_scheme))
55    }
56}
57
58impl TryFrom<Vec<u8>> for ExternalSender {
59    type Error = Error;
60
61    fn try_from(value: Vec<u8>) -> Result<Self> {
62        Self::parse_jwk(&value)
63    }
64}