diff --git a/nkode-rs b/nkode-rs index e5712b4..a81a09a 160000 --- a/nkode-rs +++ b/nkode-rs @@ -1 +1 @@ -Subproject commit e5712b4a92f1363a1cb7692e15cb74f6dfbef0eb +Subproject commit a81a09ac8696ba2b8fabdc4296a8f11dbd89e38d diff --git a/src/client/app.rs b/src/client/app.rs index 4070a59..a3437d1 100644 --- a/src/client/app.rs +++ b/src/client/app.rs @@ -2,20 +2,20 @@ use std::marker::PhantomData; use crate::client::client_auth_api::ClientAuth; use crate::client::opaque::{ServerConnectionLogin, ServerConnectionRegister}; use crate::client::repo::ClientRepo; -use crate::client::states::{KeyLogin, KeyRegister, UserStateCodeLogin, UserStateCodeRegister, UserStateKey}; +use crate::client::states::{DisplayKeypad, KeyLogin, KeyRegister, UserStateCodeLogin, UserStateCodeRegister, UserStateKey}; use crate::shared::models::app::{Icon, IconID}; use crate::shared::email::Email; use crate::shared::opaque::UserSecretKey; use crate::shared::user_api::UserAPI; -pub struct ClientApp<'a,'b ,State, K,C, U, R> +pub struct ClientApp<'a,'b, 'c,State, K,C, U, R> where K: ServerConnectionRegister + ServerConnectionLogin, C: ServerConnectionRegister + ServerConnectionLogin, U: UserAPI, R: ClientRepo { - auth_api: ClientAuth<'a,'b ,K,C, U>, + auth_api: ClientAuth<'a,'b,'c ,K,C, U>, client_repo: R, code_reg: Option, key_login: Option>, @@ -25,14 +25,14 @@ where -impl <'a,'b ,State, K,C, U, R>ClientApp<'a,'b ,State, K,C, U, R> +impl <'a,'b,'c ,State, K,C, U, R>ClientApp<'a,'b,'c ,State, K,C, U, R> where K: ServerConnectionRegister + ServerConnectionLogin, C: ServerConnectionRegister + ServerConnectionLogin, U: UserAPI, R: ClientRepo, { - pub fn new(auth_api: ClientAuth<'a,'b , K,C, U>, client_repo: R) -> Self { + pub fn new(auth_api: ClientAuth<'a,'b,'c, K,C, U>, client_repo: R) -> Self { Self { auth_api, client_repo, @@ -43,7 +43,7 @@ where } } - fn into_state(self) -> ClientApp<'a,'b, NextState, K,C, U, R> { + fn into_state(self) -> ClientApp<'a,'b,'c, NextState, K,C, U, R> { ClientApp { auth_api: self.auth_api, client_repo: self.client_repo, @@ -56,24 +56,24 @@ where } pub struct NewUserRegisterKey; -impl <'a,'b, K, C, U, R> ClientApp<'a,'b, NewUserRegisterKey, K,C, U, R> +impl <'a,'b, 'c,K, C, U, R> ClientApp<'a,'b,'c, NewUserRegisterKey, K,C, U, R> where K: ServerConnectionRegister + ServerConnectionLogin, C: ServerConnectionRegister + ServerConnectionLogin, U: UserAPI, R: ClientRepo, { - pub async fn new_user(mut self, email: Email, secret_key: UserSecretKey) -> Result, String> { + pub async fn new_user(mut self, email: Email, secret_key: UserSecretKey) -> Result, String> { let key_register = UserStateKey::::new(email.clone(), secret_key.clone()); self.client_repo.add_secret_key(email.clone(), secret_key.clone()).await?; - let key_login = match key_register.register(&self.auth_api).await.map_err(|e| format!("error: {e:?}")) { + let key_login = match key_register.register(&self.auth_api).await.map_err(|e| format!("error key reg: {e:?}")) { Ok(s) => s, Err(e) => { self.client_repo.remove_secret_key(&email).await.expect("couldn't delete"); return Err(format!("error registering key {}", e)) } }; - let key_logged_in = key_login.login(&self.auth_api).await.map_err(|e| format!("error: {e:?}"))?; + let key_logged_in = key_login.login(&self.auth_api).await.map_err(|e| format!("error key login: {e:?}"))?; let code_register = key_logged_in.to_register_code(&self.auth_api).await?; self.code_reg = Some(code_register); Ok(self.into_state::()) @@ -82,7 +82,7 @@ where pub struct NewUserRegisterCode; -impl <'a,'b, K, C, U, R> ClientApp<'a,'b, NewUserRegisterCode, K,C, U, R> +impl <'a,'b,'c, K, C, U, R> ClientApp<'a,'b,'c, NewUserRegisterCode, K,C, U, R> where K: ServerConnectionRegister + ServerConnectionLogin, C: ServerConnectionRegister + ServerConnectionLogin, @@ -98,7 +98,7 @@ where ) } - pub async fn new_user_register_code(mut self, selected_icons: Vec) -> Result, String> { + pub async fn new_user_register_code(mut self, selected_icons: Vec) -> Result, String> { let code_register = self.code_reg.ok_or("no code register".to_string())?; self.code_reg = None; self.code_login = Some(code_register.clone().register(&self.auth_api,selected_icons).await?); @@ -109,14 +109,14 @@ where pub struct UserKeyLogin; -impl <'a,'b, K, C, U, R> ClientApp<'a,'b, UserKeyLogin, K,C, U, R> +impl <'a,'b, 'c,K, C, U, R> ClientApp<'a,'b, 'c,UserKeyLogin, K,C, U, R> where K: ServerConnectionRegister + ServerConnectionLogin, C: ServerConnectionRegister + ServerConnectionLogin, U: UserAPI, R: ClientRepo, { - pub async fn login(mut self, email: Email, secret_key: UserSecretKey) -> Result, String> { + pub async fn login(mut self, email: Email, secret_key: UserSecretKey) -> Result, String> { self.code_login = Some( UserStateKey::::new(email, secret_key) .login(&self.auth_api).await? @@ -127,20 +127,20 @@ where } pub struct UserCodeLogin; -impl <'a,'b, K, C, U, R> ClientApp<'a,'b, UserCodeLogin, K,C, U, R> +impl <'a,'b,'c, K, C, U, R> ClientApp<'a,'b,'c, UserCodeLogin, K,C, U, R> where K: ServerConnectionRegister + ServerConnectionLogin, C: ServerConnectionRegister + ServerConnectionLogin, U: UserAPI, R: ClientRepo, { - pub async fn get_keypad(&self) -> Result>, String> { + pub fn get_keypad(&self) -> Result { let code_login = self.code_login.clone().ok_or("no code login")?; - Ok(code_login.get_keypad().await) + Ok(code_login.get_keypad()) } - pub async fn login(self, key_selection: Vec) -> Result<(), String> { - let code_login = self.code_login.unwrap().login(&self.auth_api, &key_selection).await?; + pub async fn login(self, key_selection: &Vec) -> Result<(), String> { + let code_login = self.code_login.unwrap().login(&self.auth_api, key_selection).await?; self.client_repo.add_code_logged_in(code_login.0.email.clone(), code_login).await } } diff --git a/src/client/client_auth_api.rs b/src/client/client_auth_api.rs index 4a0da78..664402a 100644 --- a/src/client/client_auth_api.rs +++ b/src/client/client_auth_api.rs @@ -9,7 +9,7 @@ use crate::client::opaque::{OpaqueAuthData, OpaqueAuth, ServerConnectionLogin, S use crate::shared::signed_session_data::SignedSessionData; use crate::shared::user_api::UserAPI; -pub struct ClientAuth<'a,'b, K,C, U> +pub struct ClientAuth<'a,'b,'c, K,C, U> where K: ServerConnectionRegister + ServerConnectionLogin, C: ServerConnectionRegister + ServerConnectionLogin, @@ -19,16 +19,16 @@ where opaque_key_login: OpaqueAuth<'a, K>, opaque_code_register: OpaqueAuth<'b, C>, opaque_code_login: OpaqueAuth<'b, C>, - user_api: U + user_api: &'c U } -impl<'a,'b, K,C, U> ClientAuth<'a,'b, K,C, U> +impl<'a,'b,'c, K,C, U> ClientAuth<'a,'b,'c, K,C, U> where K: ServerConnectionRegister + ServerConnectionLogin, C: ServerConnectionRegister + ServerConnectionLogin, U: UserAPI, { - pub fn new(key_connection: &'a K, code_connection: &'b C, user_api: U) -> Self { + pub fn new(key_connection: &'a K, code_connection: &'b C, user_api: &'c U) -> Self { Self{ opaque_key_register: OpaqueAuth::new(key_connection), opaque_key_login: OpaqueAuth::new(key_connection), @@ -41,7 +41,7 @@ where #[async_trait] -impl<'a,'b, K,C, U> AuthAPI for ClientAuth<'a,'b, K,C, U> +impl<'a,'b,'c, K,C, U> AuthAPI for ClientAuth<'a,'b,'c, K,C, U> where K: ServerConnectionRegister + ServerConnectionLogin, C: ServerConnectionRegister + ServerConnectionLogin, @@ -53,6 +53,7 @@ where } async fn register_code(&self, email: &Email, passcode: &[u64], key_login_session: &KeyLoggedInSession, register_code_data: RegisterCodeData) -> Result<(), String> { + println!("register passcode: {:?}", passcode.to_vec()); let auth_data = OpaqueAuthData::from_code(email.as_str(), passcode); self.opaque_code_register.register(&auth_data).await.map_err(|e| format!("error: {}", e))?; let signed_session = SignedSessionData::new( @@ -70,6 +71,7 @@ where } async fn login_code(&self, email: &Email, passcode: &[u64], key_login_session: &KeyLoggedInSession, keypad: Keypad) -> Result { + println!("login passcode: {:?}", passcode.to_vec()); let auth_data = OpaqueAuthData::from_code(email.as_str(), passcode); let signed_session = SignedSessionData::new( key_login_session.0.session_id, @@ -77,7 +79,7 @@ where &key_login_session.0.session_key ).map_err(|e| format!("error: {e:?}"))?; self.user_api.update_keypad(signed_session).await?; - let session = self.opaque_code_login.login(&auth_data).await.map_err(|e| format!("error: {}", e))?; + let session = self.opaque_code_login.login(&auth_data).await.map_err(|e| format!("opaque code login error: {}", e))?; Ok(CodeLoggedInSession(session)) } diff --git a/src/client/states.rs b/src/client/states.rs index 73d0bbe..b7850e6 100644 --- a/src/client/states.rs +++ b/src/client/states.rs @@ -114,7 +114,7 @@ impl UserStateCodeRegister { let (cipher, cipher_nonce) = NKodeCipher::new(policy, &secret_key); let passcode_idx: Vec = selected_icons .iter() - .filter_map(|x1| self.icons.iter().position(|x| x.id() == x1)) + .filter_map(|x1| self.icons.iter().position(|x| x.id == *x1)) .collect(); let ciphered_nkode = cipher.encipher(&passcode_idx).unwrap(); let data = CodeLoginData{ @@ -143,6 +143,10 @@ impl UserStateCodeRegister { self.icons.clone() } } +pub struct DisplayKeypad { + pub sorted_icons: Vec, + pub keypad: Keypad, +} #[derive(Clone)] pub struct UserStateCodeLogin { @@ -169,7 +173,10 @@ impl UserStateCodeLogin { todo!() } - pub async fn get_keypad(&self) -> Vec> { - todo!() + pub fn get_keypad(&self) -> DisplayKeypad { + DisplayKeypad{ + sorted_icons: self.sort_icons(), + keypad: self.keypad.clone(), + } } } \ No newline at end of file diff --git a/src/server/app.rs b/src/server/app.rs index c310f17..eb4314c 100644 --- a/src/server/app.rs +++ b/src/server/app.rs @@ -15,7 +15,7 @@ pub struct ServerApp { server_setup: NKodeServerSetup, opaque_db: R, opaque_sess: S, - user_db: U, + pub user_db: U, } impl ServerApp { @@ -85,7 +85,7 @@ impl ServerApp( &self, session_id: &Uuid, finalize: CredentialFinalization, @@ -93,7 +93,6 @@ impl ServerApp ServerApp ServerApp, ) -> Result { - let session = KeyLoggedInSession(self.login_finish(session_id, finalize).await?); + let session = KeyLoggedInSession(self.login_finish::(session_id, finalize).await?); self.user_db.set_key_session(session.clone()).await?; Ok(session) } @@ -123,7 +124,7 @@ impl ServerApp, ) -> Result { - let session = CodeLoggedInSession(self.login_finish(session_id, finalize).await?); + let session = CodeLoggedInSession(self.login_finish::(session_id, finalize).await?); self.user_db.set_code_session(session.clone()).await?; Ok(session) } @@ -162,6 +163,10 @@ impl CredKind for Key { async fn set_password_file(repo: &R, id: &[u8], pf: PasswordFile) -> Result<(), AuthRepoError> { repo.new_key(id, pf).await } + + async fn set_session(repo: &R, session: LoggedInSession) -> Result<(), String> { + repo.set_key_session(KeyLoggedInSession(session)).await + } } #[async_trait] @@ -182,4 +187,8 @@ impl CredKind for Code { Err(AuthRepoError::KeyNotRegistered) } } + + async fn set_session(repo: &R, session: LoggedInSession) -> Result<(), String> { + repo.set_code_session(CodeLoggedInSession(session)).await + } } diff --git a/src/server/models.rs b/src/server/models.rs index 525ea43..20d9a1e 100644 --- a/src/server/models.rs +++ b/src/server/models.rs @@ -2,6 +2,8 @@ use async_trait::async_trait; use uuid::Uuid; use opaque_ke::ServerLogin; use crate::server::repository::opaque_repo::{AuthRepoError, OpaqueDatabaseRepo}; +use crate::server::repository::user_repo::UserRepo; +use crate::shared::models::app::LoggedInSession; use crate::shared::opaque::{NKodeCipherSuite, PasswordFile}; pub struct RegCache { @@ -23,4 +25,5 @@ pub trait CredKind: Send + Sync { async fn prereq_for_register(_repo: &R, _id: &[u8]) -> Result<(), AuthRepoError> { Ok(()) } + async fn set_session(repo: &R, session: LoggedInSession) -> Result<(), String>; } \ No newline at end of file diff --git a/src/server/repository/in_memory/in_memory_transport.rs b/src/server/repository/in_memory/in_memory_transport.rs index 20c785b..72c2165 100644 --- a/src/server/repository/in_memory/in_memory_transport.rs +++ b/src/server/repository/in_memory/in_memory_transport.rs @@ -79,7 +79,7 @@ where ) -> Result { Ok(self .auth_db - .login_finish(session_id, message.clone()) + .login_finish::(session_id, message.clone()) .await .map_err(|e| ClientAuthError::Transport(e))? ) diff --git a/src/server/repository/in_memory/in_memory_user_db.rs b/src/server/repository/in_memory/in_memory_user_db.rs index 832192c..09069de 100644 --- a/src/server/repository/in_memory/in_memory_user_db.rs +++ b/src/server/repository/in_memory/in_memory_user_db.rs @@ -44,28 +44,28 @@ impl UserRepo for InMemoryUserDB { self.key_session.lock().await .get(&session_id) .cloned() - .ok_or_else(|| format!("key session not found for session_id={}", session_id)) + .ok_or(format!("key session not found for session_id={}", session_id)) } async fn get_code_session(&self, session_id: &Uuid) -> Result { self.code_session.lock().await .get(&session_id) .cloned() - .ok_or_else(|| format!("code session not found for session_id={}", session_id)) + .ok_or(format!("code session not found for session_id={}", session_id)) } async fn set_key_session(&self, session: KeyLoggedInSession) -> Result<(), String> { - self.key_session.lock().await.insert(session.0.session_id, session).ok_or("couldn't set key session".to_string())?; + self.key_session.lock().await.insert(session.0.session_id, session); Ok(()) } async fn set_code_session(&self, session: CodeLoggedInSession) -> Result<(), String> { - self.code_session.lock().await.insert(session.0.session_id, session).ok_or("couldn't set code session".to_string())?; + self.code_session.lock().await.insert(session.0.session_id, session); Ok(()) } async fn set_code_login_data(&self, email: Email, data: CodeLoginData) -> Result<(), String> { - self.code_data_store.lock().await.insert(email, data).ok_or("couldn't set code login data")?; + self.code_data_store.lock().await.insert(email, data); Ok(()) } @@ -114,11 +114,11 @@ impl UserAPI for InMemoryUserDB { async fn set_code_login_data(&self, session: SignedSessionData) -> Result<(), String> { let key_session = self.get_key_session(&session.session_id).await?; session.verify(&key_session.0.session_key).map_err(|e| format!("session error: {e:?}"))?; - self.code_data_store.lock().await.insert(session.data.code_login_data.email.clone(), session.data.code_login_data).ok_or("couldn't set code data".to_string())?; + self.code_data_store.lock().await.insert(session.data.code_login_data.email.clone(), session.data.code_login_data); let mut owned_icons = self.owned_icons.lock().await; for icon in session.data.icons { - let icon_id = icon.id().clone(); - owned_icons.insert(icon_id.clone(), icon).ok_or(format!("error inserting icon into owned icons {}", icon_id))?; + let icon_id = icon.id.clone(); + owned_icons.insert(icon_id.clone(), icon); } Ok(()) } @@ -130,7 +130,7 @@ impl UserAPI for InMemoryUserDB { let mut code_data_store = self.code_data_store.lock().await; let mut code_data = code_data_store.remove(&email).ok_or("user doesn't have code data".to_string())?; code_data.keypad = session.data; - code_data_store.insert(email, code_data).ok_or("couldn't update keypad")?; + code_data_store.insert(email, code_data); Ok(()) } @@ -149,8 +149,8 @@ impl UserAPI for InMemoryUserDB { session.verify(&key_session.0.session_key).map_err(|e| format!("session error: {e:?}"))?; let mut owned_icons = self.owned_icons.lock().await; for icon in session.data { - let icon_id = icon.id().clone(); - owned_icons.insert(icon_id.clone(), icon).ok_or(format!("error inserting icon into owned icons {}", icon_id))?; + let icon_id = icon.id.clone(); + owned_icons.insert(icon_id.clone(), icon); } Ok(()) } diff --git a/src/shared/models/app.rs b/src/shared/models/app.rs index cf145b5..2523dde 100644 --- a/src/shared/models/app.rs +++ b/src/shared/models/app.rs @@ -2,7 +2,6 @@ use std::fmt; use async_trait::async_trait; use nkode_rs::nkode_core::chacha20prng::Nonce; use nkode_rs::nkode_core::keypad::Keypad; use serde::{Deserialize, Serialize}; -use getset::Getters; use nkode_rs::from_bytes::FromBytes; use nkode_rs::nkode_core::policy::NKodePolicy; use uuid::Uuid; @@ -24,7 +23,7 @@ pub struct CodeLoggedInSession(pub(crate) LoggedInSession); pub const ICON_ID_SIZE: usize = 32; #[derive(Debug, Clone, PartialEq, Eq,Hash, Serialize, Deserialize)] -pub struct IconID([u8; 32]); +pub struct IconID(pub [u8; 32]); impl fmt::Display for IconID { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -41,12 +40,10 @@ impl FromBytes for IconID { } } -#[derive(Debug, Clone, Serialize, Deserialize, Getters)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Icon { - #[get = "pub"] - id: IconID, - #[get = "pub"] - data: Vec, + pub id: IconID, + pub data: Vec, } impl Icon { diff --git a/tests/in_memory_client_app_test.rs b/tests/in_memory_client_app_test.rs index fcd4608..80c2d21 100644 --- a/tests/in_memory_client_app_test.rs +++ b/tests/in_memory_client_app_test.rs @@ -8,26 +8,37 @@ use nkode_protocol::server::repository::in_memory::in_memory_opaque_session::InM use nkode_protocol::server::repository::in_memory::in_memory_transport::{InMemoryCodeServer, InMemoryKeyServer, InMemoryServerTransport}; use nkode_protocol::server::repository::in_memory::in_memory_user_db::InMemoryUserDB; use nkode_protocol::shared::email::Email; -use nkode_protocol::shared::models::app::IconID; +use nkode_protocol::shared::models::app::{Icon, IconID, ICON_ID_SIZE}; use nkode_protocol::shared::opaque::{NKodeServerSetup, UserSecretKey}; +use nkode_protocol::shared::user_api::IconPoolAPI; #[tokio::test] async fn in_memory_client_app() { - let mut rng = OsRng; let server_setup = NKodeServerSetup::new(&mut rng); + let user_db = InMemoryUserDB::new(); + let n: usize = 200; + let mut new_icons: Vec = Vec::with_capacity(n); + for i in 0u8..(n as u8) { + let id = IconID([i; ICON_ID_SIZE]); // [0; 32], [1; 32], ... [199; 32] + new_icons.push(Icon { + id, + data: vec![i], // dummy payload; adjust as needed + }); + } + user_db.add_icons(new_icons).await.unwrap(); let server = ServerApp::new( server_setup, InMemoryOpaqueDB::new(), InMemoryOpaqueSession::new(), - InMemoryUserDB::new() + user_db, ); let key_transport: InMemoryKeyServer = InMemoryServerTransport::new(&server); let code_transport: InMemoryCodeServer = InMemoryServerTransport::new(&server); - let user_db = InMemoryUserDB::new(); - let client_auth = ClientAuth::new(&key_transport, &code_transport, user_db); + let client_auth = ClientAuth::new(&key_transport, &code_transport, &server.user_db); let client_repo = InMemoryClientRepo::new(); - let client_app_new_user: ClientApp< + let new_user: ClientApp< + '_, '_, '_, NewUserRegisterKey, @@ -38,12 +49,15 @@ async fn in_memory_client_app() { > = ClientApp::new(client_auth, client_repo); let user_email = Email::new("a@b.com").unwrap(); let user_secret_key = UserSecretKey::new(); - let client_app_register_code = client_app_new_user.new_user(user_email, user_secret_key).await.unwrap(); - let _: Vec = client_app_register_code - .get_new_user_icons().await.unwrap() - .iter() - .map( - |el| el.id().clone() - ).collect(); - // let client_app_user_login = client_app_register_code.new_user_register_code(icons[0..4].to_vec()).await.unwrap(); + let register_code = new_user.new_user(user_email, user_secret_key).await.unwrap(); + let icons: Vec = register_code.get_new_user_icons().await.unwrap(); + let icon_ids:Vec = icons.iter().map(|el| el.id.clone()).collect(); + let selected_icons = icon_ids[0..4].to_vec(); + let code_login = register_code.new_user_register_code(selected_icons.clone()).await.unwrap(); + let display_keypad = code_login.get_keypad().unwrap(); + let icon_idxs: Vec = selected_icons.iter().map(|x| { + display_keypad.sorted_icons.iter().position(|x1| {x1.id == *x}).unwrap() + }).collect(); + let selected_keys = display_keypad.keypad.select_keys(&icon_idxs).unwrap(); + code_login.login(&selected_keys).await.unwrap(); }