Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: parse ClientId as an URI #74

Merged
merged 2 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions openmls/src/credentials/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ impl tls_codec::Serialize for Credential {
impl tls_codec::Deserialize for Credential {
fn tls_deserialize<R: Read>(bytes: &mut R) -> Result<Self, tls_codec::Error> {
let val = u16::tls_deserialize(bytes)?;
let credential_type = CredentialType::try_from(val)
.map_err(|e| tls_codec::Error::DecodingError(e.to_string()))?;
let credential_type = CredentialType::from(val);
match credential_type {
CredentialType::Basic => Ok(Credential::from(MlsCredentialType::Basic(
BasicCredential::tls_deserialize(bytes)?,
Expand Down
8 changes: 3 additions & 5 deletions openmls/src/credentials/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@
//! There are multiple [`CredentialType`]s, although OpenMLS currently only
//! supports the [`BasicCredential`].

use std::{
convert::TryFrom,
io::{Read, Write},
};
use std::io::{Read, Write};

use serde::{Deserialize, Serialize};
use tls_codec::{TlsDeserialize, TlsSerialize, TlsSize, VLBytes};
Expand All @@ -34,6 +31,7 @@ use tls_codec::{TlsDeserialize, TlsSerialize, TlsSize, VLBytes};
mod codec;
#[cfg(test)]
mod tests;

use errors::*;
use openmls_x509_credential::X509Ext;
use x509_cert::{der::Decode, PkiPath};
Expand Down Expand Up @@ -184,7 +182,7 @@ impl Certificate {

fn try_new(certificates: Vec<Vec<u8>>) -> Result<Self, CredentialError> {
let leaf = certificates
.get(0)
.first()
.ok_or(CredentialError::InvalidCertificateChain)?;
let leaf = x509_cert::Certificate::from_der(leaf)?;
let identity = leaf
Expand Down
3 changes: 0 additions & 3 deletions openmls/src/group/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ pub use core_group::proposals::*;
pub use core_group::staged_commit::StagedCommit;
pub use mls_group::config::*;
pub use mls_group::membership::*;
pub use mls_group::processing::*;
pub use mls_group::*;
pub use public_group::*;

Expand All @@ -38,8 +37,6 @@ pub(crate) use core_group::create_commit_params::*;
#[cfg(any(feature = "test-utils", test))]
pub(crate) mod tests;
use openmls_traits::random::OpenMlsRand;
#[cfg(any(feature = "test-utils", test))]
pub use proposals::*;

/// A group ID. The group ID is chosen by the creator of the group and should be globally unique.
#[derive(
Expand Down
11 changes: 2 additions & 9 deletions openmls/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// MlsGroup
pub use crate::group::{config::CryptoConfig, core_group::Member, errors::*, ser::*, *};

pub use crate::group::public_group::{errors::*, process::*, *};
pub use crate::group::public_group::errors::*;

// Ciphersuite
pub use crate::ciphersuite::{hash_ref::KeyPackageRef, signable::*, signature::*, *};
Expand All @@ -24,14 +24,7 @@ pub use crate::versions::*;
pub use crate::extensions::{errors::*, *};

// Framing
pub use crate::framing::{
message_in::*,
message_out::{MlsMessageOutBody, *},
mls_content_in::FramedContentBodyIn,
sender::*,
validation::*,
*,
};
pub use crate::framing::{message_out::MlsMessageOutBody, mls_content_in::FramedContentBodyIn, *};

// Key packages
pub use crate::key_packages::{errors::*, *};
Expand Down
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
35 changes: 29 additions & 6 deletions x509_credential/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use base64::Engine;
use openmls_basic_credential::SignatureKeyPair;
use percent_encoding::percent_decode_str;
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 All @@ -34,7 +36,7 @@ impl CertificateKeyPair {
},
)?;

let leaf = pki_path.get(0).ok_or(CryptoError::CryptoLibraryError)?;
let leaf = pki_path.first().ok_or(CryptoError::CryptoLibraryError)?;

let signature_scheme = leaf.signature_scheme()?;
let pk = leaf.public_key()?;
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:https://[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:https://";

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:https://[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:https://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);
}
Loading