-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
399 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
use crate::{prelude::ClientId, CryptoError, CryptoResult}; | ||
use std::str::FromStr; | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq, Hash, derive_more::From, derive_more::Into, derive_more::Deref)] | ||
pub struct WireQualifiedClientId(ClientId); | ||
|
||
impl WireQualifiedClientId { | ||
pub fn get_user_id(&self) -> CryptoResult<String> { | ||
const COLON: u8 = 58; | ||
let mut split = self.0.split(|b| b == &COLON); | ||
let user_id = split.next().ok_or(CryptoError::InvalidClientId)?; | ||
|
||
let user_id = uuid::Uuid::try_parse_ascii(user_id).map_err(|_| CryptoError::InvalidClientId)?; | ||
let mut buf = [0; uuid::fmt::Hyphenated::LENGTH]; | ||
let user_id = user_id.hyphenated().encode_lower(&mut buf); | ||
Ok(user_id.to_string()) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
impl WireQualifiedClientId { | ||
pub fn generate() -> ClientId { | ||
let user_id = uuid::Uuid::new_v4().to_string(); | ||
let device_id = rand::random::<u64>(); | ||
let domain = "wire.com"; | ||
let client_id = format!("{user_id}:{device_id:x}@{domain}"); | ||
client_id.into_bytes().into() | ||
} | ||
} | ||
|
||
impl ToString for WireQualifiedClientId { | ||
fn to_string(&self) -> String { | ||
String::from_utf8(self.0.to_vec()).unwrap() | ||
} | ||
} | ||
|
||
impl<'a> TryFrom<&'a [u8]> for WireQualifiedClientId { | ||
type Error = CryptoError; | ||
|
||
fn try_from(bytes: &'a [u8]) -> CryptoResult<Self> { | ||
const COLON: u8 = 58; | ||
let mut split = bytes.split(|b| b == &COLON); | ||
let user_id = split.next().ok_or(CryptoError::InvalidClientId)?; | ||
|
||
let user_id = base64_simd::URL_SAFE_NO_PAD | ||
.decode_to_vec(user_id) | ||
.map_err(|_| CryptoError::InvalidClientId)?; | ||
|
||
let user_id = uuid::Uuid::from_slice(&user_id).map_err(|_| CryptoError::InvalidClientId)?; | ||
let mut buf = [0; uuid::fmt::Hyphenated::LENGTH]; | ||
let user_id = user_id.hyphenated().encode_lower(&mut buf); | ||
|
||
let rest = split.next().ok_or(CryptoError::InvalidClientId)?; | ||
if split.next().is_some() { | ||
return Err(CryptoError::InvalidClientId); | ||
} | ||
|
||
let client_id = [user_id.as_bytes(), &[COLON], rest].concat(); | ||
let client_id = ClientId::from(client_id); | ||
Ok(Self(client_id)) | ||
} | ||
} | ||
|
||
impl FromStr for WireQualifiedClientId { | ||
type Err = CryptoError; | ||
|
||
fn from_str(s: &str) -> CryptoResult<Self> { | ||
s.as_bytes().try_into() | ||
} | ||
} | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq, Hash, derive_more::From, derive_more::Into, derive_more::Deref)] | ||
pub struct QualifiedE2eiClientId(ClientId); | ||
|
||
#[cfg(test)] | ||
impl QualifiedE2eiClientId { | ||
pub fn generate() -> Self { | ||
use base64::Engine as _; | ||
|
||
let user_id = uuid::Uuid::new_v4(); | ||
let user_id = base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(user_id.as_bytes()); | ||
|
||
let device_id = rand::random::<u64>(); | ||
let domain = "wire.com"; | ||
let client_id = format!("{user_id}:{device_id:x}@{domain}"); | ||
Self(client_id.into_bytes().into()) | ||
} | ||
|
||
pub fn generate_from_user_id(user_id: &uuid::Uuid) -> Self { | ||
use base64::Engine as _; | ||
|
||
let user_id = base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(user_id.as_bytes()); | ||
|
||
let device_id = rand::random::<u64>(); | ||
let domain = "wire.com"; | ||
let client_id = format!("{user_id}:{device_id:x}@{domain}"); | ||
Self(client_id.into_bytes().into()) | ||
} | ||
|
||
pub fn to_static_str(&self) -> &'static str { | ||
Box::leak(Box::new(self.to_string())) | ||
} | ||
} | ||
|
||
impl<'a> TryFrom<&'a [u8]> for QualifiedE2eiClientId { | ||
type Error = CryptoError; | ||
|
||
fn try_from(bytes: &'a [u8]) -> CryptoResult<Self> { | ||
const COLON: u8 = 58; | ||
let mut split = bytes.split(|b| b == &COLON); | ||
let user_id = split.next().ok_or(CryptoError::InvalidClientId)?; | ||
|
||
let user_id = uuid::Uuid::from_str(std::str::from_utf8(user_id)?).map_err(|_| CryptoError::InvalidClientId)?; | ||
// let mut buf = [0; uuid::fmt::Hyphenated::LENGTH]; | ||
// let user_id = user_id.hyphenated().encode_lower(&mut buf); | ||
|
||
let user_id = base64_simd::URL_SAFE_NO_PAD.encode_to_string(user_id.as_bytes()); | ||
// let user_id = base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(user_id.as_bytes()); | ||
|
||
let rest = split.next().ok_or(CryptoError::InvalidClientId)?; | ||
if split.next().is_some() { | ||
return Err(CryptoError::InvalidClientId); | ||
} | ||
|
||
let client_id = [user_id.as_bytes(), &[COLON], rest].concat(); | ||
let client_id = ClientId::from(client_id); | ||
Ok(Self(client_id)) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
impl FromStr for QualifiedE2eiClientId { | ||
type Err = CryptoError; | ||
|
||
fn from_str(s: &str) -> CryptoResult<Self> { | ||
s.as_bytes().try_into() | ||
} | ||
} | ||
|
||
impl ToString for QualifiedE2eiClientId { | ||
fn to_string(&self) -> String { | ||
String::from_utf8(self.0.to_vec()).unwrap() | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
impl TryFrom<WireQualifiedClientId> for QualifiedE2eiClientId { | ||
type Error = CryptoError; | ||
|
||
fn try_from(wire_id: WireQualifiedClientId) -> CryptoResult<Self> { | ||
wire_id.as_slice().try_into() | ||
} | ||
} | ||
|
||
impl TryFrom<QualifiedE2eiClientId> for WireQualifiedClientId { | ||
type Error = CryptoError; | ||
|
||
fn try_from(e2ei_id: QualifiedE2eiClientId) -> CryptoResult<Self> { | ||
const COLON: u8 = 58; | ||
|
||
let mut split = e2ei_id.0.split(|b| b == &COLON); | ||
let user_id = split.next().ok_or(CryptoError::InvalidClientId)?; | ||
|
||
let user_id = base64_simd::URL_SAFE_NO_PAD.decode_to_vec(user_id).unwrap(); | ||
let user_id = uuid::Uuid::from_slice(&user_id).map_err(|_| CryptoError::InvalidClientId)?; | ||
|
||
let mut buf = [0; uuid::fmt::Hyphenated::LENGTH]; | ||
let user_id = user_id.hyphenated().encode_lower(&mut buf); | ||
|
||
let rest = split.next().ok_or(CryptoError::InvalidClientId)?; | ||
if split.next().is_some() { | ||
return Err(CryptoError::InvalidClientId); | ||
} | ||
|
||
let x = user_id.as_bytes(); | ||
let client_id = [x, &[COLON], rest].concat(); | ||
let client_id = ClientId::from(client_id); | ||
Ok(Self(client_id)) | ||
} | ||
} | ||
|
||
/*#[cfg(test)] | ||
pub mod tests { | ||
use super::*; | ||
use base64::Engine; | ||
const WIRE_ID: &'static str = "e77cf2a2-100f-49c4-872f-5041a407c3db:[email protected]"; | ||
const E2EI_ID: &'static str = "53zyohAPScSHL1BBpAfD2w:[email protected]"; | ||
#[test] | ||
fn toto() { | ||
let uid = "e77cf2a2-100f-49c4-872f-5041a407c3db"; | ||
let uid = uuid::Uuid::from_str(uid).unwrap(); | ||
let uid = base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(uid.as_bytes()); | ||
println!("{}", uid); | ||
} | ||
mod parse { | ||
use super::*; | ||
#[test] | ||
fn should_parse_wire_qualified_client_id() { | ||
assert!(WIRE_ID.parse::<WireQualifiedClientId>().is_ok()); | ||
assert!(matches!( | ||
WIRE_ID.parse::<E2eiClientId>().unwrap_err(), | ||
CryptoError::InvalidClientId | ||
)); | ||
} | ||
#[test] | ||
fn should_parse_e2ei_client_id() { | ||
assert!(E2EI_ID.parse::<E2eiClientId>().is_ok()); | ||
assert!(matches!( | ||
E2EI_ID.parse::<WireQualifiedClientId>().unwrap_err(), | ||
CryptoError::InvalidClientId | ||
)); | ||
} | ||
} | ||
mod convert { | ||
use super::*; | ||
#[test] | ||
fn to_wire_qualified_client_id_should_work() { | ||
let e2ei_id = E2EI_ID.parse::<E2eiClientId>().unwrap(); | ||
WireQualifiedClientId::try_from(e2ei_id).unwrap(); | ||
} | ||
#[test] | ||
fn to_e2ei_should_work() { | ||
let wire_id = WIRE_ID.parse::<WireQualifiedClientId>().unwrap(); | ||
E2eiClientId::try_from(wire_id).unwrap(); | ||
} | ||
} | ||
mod generate { | ||
use super::*; | ||
#[test] | ||
fn e2ei() { | ||
let new = E2eiClientId::generate(); | ||
let g = WireQualifiedClientId::try_from(new).unwrap(); | ||
let fog = E2eiClientId::try_from(g).unwrap(); | ||
} | ||
#[test] | ||
fn wire_qualified_client_id() { | ||
let new = WireQualifiedClientId::generate(); | ||
let g = E2eiClientId::try_from(new).unwrap(); | ||
let fog = WireQualifiedClientId::try_from(g).unwrap(); | ||
} | ||
} | ||
}*/ |
Oops, something went wrong.