diff --git a/native/native_rust_library/Cargo.lock b/native/native_rust_library/Cargo.lock --- a/native/native_rust_library/Cargo.lock +++ b/native/native_rust_library/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +dependencies = [ + "memchr", +] + [[package]] name = "anyhow" version = "1.0.65" @@ -651,6 +660,7 @@ "opaque-ke", "prost", "rand", + "regex", "sha2", "tokio", "tokio-stream", @@ -899,6 +909,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ + "aho-corasick", + "memchr", "regex-syntax", ] diff --git a/native/native_rust_library/Cargo.toml b/native/native_rust_library/Cargo.toml --- a/native/native_rust_library/Cargo.toml +++ b/native/native_rust_library/Cargo.toml @@ -20,6 +20,7 @@ digest = "0.9" curve25519-dalek = "3.2" sha2 = "0.9" +regex = "1.6" [build-dependencies] cxx-build = "1.0" diff --git a/native/native_rust_library/src/crypto_tools.rs b/native/native_rust_library/src/crypto_tools.rs new file mode 100644 --- /dev/null +++ b/native/native_rust_library/src/crypto_tools.rs @@ -0,0 +1,82 @@ +use crate::ffi::DeviceType; +use rand::distributions::{Alphanumeric, DistString}; +#[cfg(test)] +use regex::Regex; + +// DEVICE_ID_CHAR_LENGTH has to be kept in sync with deviceIDCharLength +// which is defined in web/utils/device-id.js +// and with DEVICE_CHAR_LENGTH +// defined in services/tunnelbroker/src/Constants.h +const DEVICE_ID_CHAR_LENGTH: usize = 64; +// DEVICE_ID_FORMAT_REGEX has to be kept in sync with deviceIDFormatRegex +// which is defined in web/utils/device-id.js +// and with DEVICEID_FORMAT_REGEX +// defined in services/tunnelbroker/src/Constants.h +#[cfg(test)] +const DEVICE_ID_FORMAT_REGEX: &str = "^(ks|mobile|web):[a-zA-Z0-9]{64}$"; + +// generate_device_id has to be kept in sync with generateDeviceID +// which is defined in web/utils/device-id.js +pub fn generate_device_id(device_type: DeviceType) -> Result { + let prefix = match device_type { + DeviceType::KEYSERVER => "ks", + DeviceType::WEB => "web", + DeviceType::MOBILE => "mobile", + _ => { + return Err(String::from("Incorrect device type provieded")); + } + }; + let mut rng = rand::thread_rng(); + let suffix: String = + Alphanumeric.sample_string(&mut rng, DEVICE_ID_CHAR_LENGTH); + + Ok(format!("{}:{}", &prefix, &suffix)) +} + +#[cfg(test)] +mod tests { + use super::*; + + fn check_regex(s: &String) -> bool { + Regex::new(&DEVICE_ID_FORMAT_REGEX).unwrap().is_match(&s) + } + + #[test] + fn generate_device_id_ks() { + for _x in 1..100 { + let result = generate_device_id(DeviceType::KEYSERVER).unwrap(); + assert!( + check_regex(&result), + "result: {} does not match regex {}", + &result, + &DEVICE_ID_FORMAT_REGEX + ); + } + } + + #[test] + fn generate_device_id_web() { + for _x in 1..100 { + let result = generate_device_id(DeviceType::WEB).unwrap(); + assert!( + check_regex(&result), + "result: {} does not match regex {}", + &result, + &DEVICE_ID_FORMAT_REGEX + ); + } + } + + #[test] + fn generate_device_id_mobile() { + for _x in 1..100 { + let result = generate_device_id(DeviceType::MOBILE).unwrap(); + assert!( + check_regex(&result), + "result: {} does not match regex {}", + &result, + &DEVICE_ID_FORMAT_REGEX + ); + } + } +} diff --git a/native/native_rust_library/src/lib.rs b/native/native_rust_library/src/lib.rs --- a/native/native_rust_library/src/lib.rs +++ b/native/native_rust_library/src/lib.rs @@ -4,12 +4,14 @@ use tonic::{transport::Channel, Status}; use tracing::instrument; +mod crypto_tools; mod identity_client; mod opaque; mod identity { tonic::include_proto!("identity"); } +use crypto_tools::generate_device_id; use identity::identity_service_client::IdentityServiceClient; use identity_client::{ get_user_id, login_user_pake, login_user_wallet, register_user, @@ -31,7 +33,15 @@ #[cxx::bridge] mod ffi { + + enum DeviceType { + KEYSERVER, + WEB, + MOBILE, + } + extern "Rust" { + // Identity Service Client type Client; fn initialize_client() -> Box; fn get_user_id_blocking( @@ -68,6 +78,8 @@ siwe_signature: Vec, user_public_key: String, ) -> Result; + // Crypto Tools + fn generate_device_id(device_type: DeviceType) -> Result; } }