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