Skip to content

Commit

Permalink
feat: parse ClientId as an URI
Browse files Browse the repository at this point in the history
  • Loading branch information
beltram committed Jan 10, 2024
1 parent 7496165 commit 8e30301
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 5 deletions.
1 change: 1 addition & 0 deletions x509_credential/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ openmls_basic_credential = { version = "0.2.0", path = "../basic_credential" }
fluvio-wasm-timer = "0.2"
base64 = "0.21"
uuid = "1.4"
percent-encoding = "2.3"

# Rust Crypto
secrecy = { version = "0.8", features = ["serde"] }
Expand Down
33 changes: 28 additions & 5 deletions x509_credential/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//! An implementation of the x509 credential from the MLS spec.
use base64::Engine;
use percent_encoding::percent_decode_str;
use openmls_basic_credential::SignatureKeyPair;
use x509_cert::der::Decode;
use x509_cert::Certificate;
Expand All @@ -18,7 +19,8 @@ use openmls_traits::{
pub struct CertificateKeyPair(pub SignatureKeyPair);

impl CertificateKeyPair {
/// Constructs the `CertificateKeyPair` from a private key and a der encoded certificate chain
/// Constructs the `CertificateKeyPair` from a private key and a der encoded
/// certificate chain
pub fn new(sk: Vec<u8>, cert_chain: Vec<Vec<u8>>) -> Result<Self, CryptoError> {
if cert_chain.len() < 2 {
return Err(CryptoError::IncompleteCertificateChain);
Expand Down Expand Up @@ -105,8 +107,6 @@ pub trait X509Ext {
fn identity(&self) -> Result<Vec<u8>, CryptoError>;
}

const CLIENT_ID_PREFIX: &str = "im:wireapp=";

impl X509Ext for Certificate {
fn is_valid(&self) -> Result<(), CryptoError> {
if !self.is_time_valid()? {
Expand Down Expand Up @@ -214,11 +214,16 @@ impl X509Ext for Certificate {
}
}

/// Turn 'wireapp://[email protected]' into
/// '647a4b64-b64c-44e7-8c5a-9e2c2652f65c:[email protected]'
fn try_to_qualified_wire_client_id(client_id: &str) -> Option<Vec<u8>> {
const COLON: u8 = 58;
const WIRE_URI_SCHEME: &str = "wireapp://";

let client_id = client_id.strip_prefix(WIRE_URI_SCHEME)?;
let client_id = percent_decode_str(client_id).decode_utf8().ok()?;

let client_id = client_id.strip_prefix(CLIENT_ID_PREFIX)?;
let (user_id, rest) = client_id.split_once('/')?;
let (user_id, rest) = client_id.split_once('!')?;
let user_id = to_hyphenated_user_id(user_id)?;

let client_id = [&user_id[..], &[COLON], rest.as_bytes()].concat();
Expand All @@ -237,3 +242,21 @@ fn to_hyphenated_user_id(user_id: &str) -> Option<[u8; uuid::fmt::Hyphenated::LE

Some(buf)
}

#[test]
fn to_qualified_wire_client_id_should_work() {
const EXPECTED: &str = "647a4b64-b64c-44e7-8c5a-9e2c2652f65c:[email protected]";

let input = "wireapp://[email protected]";
let output = try_to_qualified_wire_client_id(input).unwrap();
let output = std::str::from_utf8(&output).unwrap();
assert_eq!(output, EXPECTED);

// should percent decode the username before splitting it
// here '!' is percent encoded into '%21'
// that's the form in the x509 EE certificate
let input = "wireapp://ZHpLZLZMROeMWp4sJlL2XA%[email protected]";
let output = try_to_qualified_wire_client_id(input).unwrap();
let output = std::str::from_utf8(&output).unwrap();
assert_eq!(output, EXPECTED);
}

0 comments on commit 8e30301

Please sign in to comment.