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 wire_e2e_identity::parse_json_jwk;
6
7use crate::{Error, OpenMlsError, RecursiveError, 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            .map_err(wire_e2e_identity::E2eIdentityError::from)
33            .map_err(RecursiveError::context("parsing jwk"))?;
34        Ok(MlsExternalSender::new(pk.into(), MlsCredential::new_basic(WIRE_SERVER_IDENTITY.into())).into())
35    }
36
37    /// Parse an external sender given a raw public key.
38    ///
39    /// This supports the legacy behaviour where the server was providing the external sender public key
40    /// raw.
41    // TODO: remove at some point when the backend API is not used anymore. Tracking issue: WPB-9614
42    pub fn parse_public_key(key: &[u8], signature_scheme: SignatureScheme) -> Result<ExternalSender> {
43        CRYPTO
44            .validate_signature_key(signature_scheme, key)
45            .map_err(OpenMlsError::wrap("validating signature key"))?;
46        let key = OpenMlsSignaturePublicKey::new(key.into(), signature_scheme)
47            .map_err(OpenMlsError::wrap("creating new signature public key"))?;
48        Ok(MlsExternalSender::new(key.into(), MlsCredential::new_basic(WIRE_SERVER_IDENTITY.into())).into())
49    }
50
51    /// Parse an external sender.
52    ///
53    /// This first attempts to parse this as a JWK per `parse_jwk`,
54    /// and falls back to `parse_public_key` if the former method fails.
55    pub fn parse(key: &[u8], signature_scheme: SignatureScheme) -> Result<ExternalSender> {
56        Self::parse_jwk(key).or_else(|_| Self::parse_public_key(key, signature_scheme))
57    }
58}
59
60impl TryFrom<Vec<u8>> for ExternalSender {
61    type Error = Error;
62
63    fn try_from(value: Vec<u8>) -> Result<Self> {
64        Self::parse_jwk(&value)
65    }
66}