From be95241ed4ac3f693233cc8590de0a56a6210573 Mon Sep 17 00:00:00 2001 From: Donovan Date: Tue, 16 Dec 2025 14:07:03 -0600 Subject: [PATCH] refactor client opaque --- src/app/client.rs | 20 +- src/app/server.rs | 197 ++++++++++++++++++ src/models/app.rs | 6 +- src/models/opaque.rs | 4 +- src/opaque/client.rs | 45 ++-- src/opaque/server.rs | 2 + .../opaque/in_memory/in_memory_transport.rs | 163 ++++++++------- tests/in_memory_test.rs | 55 ++--- 8 files changed, 342 insertions(+), 150 deletions(-) diff --git a/src/app/client.rs b/src/app/client.rs index 0b03bd2..ed11aa6 100644 --- a/src/app/client.rs +++ b/src/app/client.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; use nkode_rs::nkode_core::keypad::Keypad; -use crate::models::app::{CodeLoginData, CodeLoginSession, Icon, IconID, KeyLoginSession, ServerAPI, ICON_ID_SIZE}; +use crate::models::app::{CodeLoginData, CodeLoginSession, Icon, IconID, KeyLoginSession, ClientAuthAPI, ICON_ID_SIZE}; use crate::models::email::Email; use crate::models::opaque::UserSecretKey; use anyhow::Result; @@ -12,14 +12,14 @@ pub struct Login; pub struct Register; -pub struct ClientAppKey { +pub struct ClientAppKey { api: S, email: Email, user_secret_key: UserSecretKey, _state: PhantomData } -impl ClientAppKey { +impl ClientAppKey { pub async fn register(self) -> Result, String> { // self.repo.set_secret_key(&self.email, &self.user_secret_key).await?; self.api.register_key(&self.email, &self.user_secret_key).await?; @@ -32,7 +32,7 @@ impl ClientAppKey { } } -impl ClientAppKey { +impl ClientAppKey { pub async fn login(self) -> Result,String> { let key_login = self.api.login_key(&self.email, &self.user_secret_key).await?; Ok(ClientAppKeyLoggedIn{ @@ -44,14 +44,14 @@ impl ClientAppKey { } } -pub struct ClientAppKeyLoggedIn { +pub struct ClientAppKeyLoggedIn { api: S, email: Email, user_secret_key: UserSecretKey, key_login: KeyLoginSession, } -impl ClientAppKeyLoggedIn { +impl ClientAppKeyLoggedIn { pub async fn register_code(self) -> Result, String> { let icon_nonce = Nonce::new(); let icons = self.get_icons(&icon_nonce).await?; @@ -98,7 +98,7 @@ impl ClientAppKeyLoggedIn { } } -pub struct ClientAppCodeRegister { +pub struct ClientAppCodeRegister { api: S, email: Email, user_secret_key: UserSecretKey, @@ -108,7 +108,7 @@ pub struct ClientAppCodeRegister { keypad: Keypad, } -impl ClientAppCodeRegister { +impl ClientAppCodeRegister { pub async fn register(self, selected_icons: Vec) -> Result, String> { let policy = self.api.get_policy().await?; let keypad = Keypad::new(policy.clone()); @@ -137,7 +137,7 @@ impl ClientAppCodeRegister { } } -pub struct ClientAppCodeLogin { +pub struct ClientAppCodeLogin { api: S, email: Email, mask: Vec, @@ -146,7 +146,7 @@ pub struct ClientAppCodeLogin { cipher: NKodeCipher } -impl ClientAppCodeLogin { +impl ClientAppCodeLogin { pub fn sort_icons(&self) -> Vec { nkode_rs::tensor::reorder( &self.icons, diff --git a/src/app/server.rs b/src/app/server.rs index e69de29..3ed75fa 100644 --- a/src/app/server.rs +++ b/src/app/server.rs @@ -0,0 +1,197 @@ +// // in_memory_server.rs +// use std::collections::HashMap; +// use std::hash::Hash; +// use std::sync::Arc; +// use nkode_rs::nkode_core::policy::NKodePolicy; +// use tokio::sync::RwLock; +// +// use crate::models::app::{ +// CodeLoginData, CodeLoginSession, Icon, KeyLoginSession, ClientAuthAPI, +// }; +// use crate::models::email::Email; +// use crate::models::opaque::UserSecretKey; +// +// +// #[derive(Clone)] +// pub struct InMemoryServer { +// state: Arc>, +// policy: NKodePolicy, +// icon_pool: Vec, +// new_key_session: FKeySess, +// new_code_session: FCodeSess, +// } +// +// struct State { +// users: HashMap, +// key_sessions: HashMap, +// code_sessions: HashMap, +// } +// +// struct UserRecord { +// secret_key: UserSecretKey, +// code: Option, +// } +// +// struct StoredCode { +// passcode: Vec, +// data: CodeLoginData, +// } +// +// impl Default for State { +// fn default() -> Self { +// Self { +// users: HashMap::new(), +// key_sessions: HashMap::new(), +// code_sessions: HashMap::new(), +// } +// } +// } +// +// impl InMemoryServer { +// /// `icon_pool` is what `get_new_icons()` returns (cloned) each time. +// /// `new_key_session` and `new_code_session` let you decide how sessions are created +// /// without changing the ServerAPI trait or guessing constructors. +// pub fn new( +// policy: NKodePolicy, +// icon_pool: Vec, +// new_key_session: FKeySess, +// new_code_session: FCodeSess, +// ) -> Self { +// Self { +// state: Arc::new(RwLock::new(State::default())), +// policy, +// icon_pool, +// new_key_session, +// new_code_session, +// } +// } +// } +// +// impl InMemoryServer +// where +// // bounds needed for HashMap keys/values and cloning across calls +// Email: Eq + Hash + Clone, +// UserSecretKey: Clone + PartialEq, +// Icon: Clone, +// CodeLoginData: Clone, +// KeyLoginSession: Eq + Hash + Clone, +// CodeLoginSession: Eq + Hash + Clone, +// FKeySess: Fn() -> KeyLoginSession + Send + Sync + 'static, +// FCodeSess: Fn() -> CodeLoginSession + Send + Sync + 'static, +// { +// fn err(msg: impl Into) -> Result<(), String> { +// Err(msg.into()) +// } +// +// fn ok(v: T) -> Result { +// Ok(v) +// } +// +// async fn email_from_key_session(&self, sess: &KeyLoginSession) -> Result { +// let st = self.state.read().await; +// st.key_sessions +// .get(sess) +// .cloned() +// .ok_or_else(|| "invalid key login session".to_string()) +// } +// } +// +// impl ClientAuthAPI for InMemoryServer +// where +// Email: Eq + Hash + Clone, +// UserSecretKey: Clone + PartialEq, +// Icon: Clone, +// CodeLoginData: Clone, +// KeyLoginSession: Eq + Hash + Clone, +// CodeLoginSession: Eq + Hash + Clone, +// +// FKeySess: Fn() -> KeyLoginSession + Send + Sync + 'static, +// FCodeSess: Fn() -> CodeLoginSession + Send + Sync + 'static, +// { +// async fn register_key(&self, email: &Email, secret_key: &UserSecretKey) -> Result<(), String> { +// let mut st = self.state.write().await; +// +// if st.users.contains_key(email) { +// return Err("email already registered".to_string()); +// } +// +// st.users.insert( +// email.clone(), +// UserRecord { +// secret_key: secret_key.clone(), +// code: None, +// }, +// ); +// +// Ok(()) +// } +// +// async fn login_key(&self, email: &Email, secret_key: &UserSecretKey) -> Result { +// let mut st = self.state.write().await; +// +// let user = st.users.get(email).ok_or_else(|| "unknown email".to_string())?; +// if &user.secret_key != secret_key { +// return Err("invalid secret key".to_string()); +// } +// let sess = (self.new_key_session)(); +// st.key_sessions.insert(sess.clone(), email.clone()); +// Ok(sess) +// } +// +// async fn is_code_registered(&self, key_login_session: &KeyLoginSession) -> Result { +// let email = self.email_from_key_session(key_login_session).await?; +// let st = self.state.read().await; +// let user = st.users.get(&email).ok_or_else(|| "unknown email".to_string())?; +// Ok(user.code.is_some()) +// } +// +// async fn get_policy(&self) -> Result { +// Ok(self.policy.clone()) +// } +// +// async fn get_new_icons(&self, key_login_session: &KeyLoginSession) -> Result, String> { +// // Validate session (mimics auth gate) +// let _email = self.email_from_key_session(key_login_session).await?; +// Ok(self.icon_pool.clone()) +// } +// +// async fn register_code( +// &self, +// email: &Email, +// passcode: &[u64], +// key_login_session: &KeyLoginSession, +// data: &CodeLoginData, +// ) -> Result<(), String> { +// let sess_email = self.email_from_key_session(key_login_session).await?; +// if &sess_email != email { +// return Err("session email mismatch".to_string()); +// } +// let mut st = self.state.write().await; +// let user = st.users.get_mut(email).ok_or_else(|| "unknown email".to_string())?; +// user.code = Some(StoredCode { +// passcode: passcode.to_vec(), +// data: data.clone(), +// }); +// Ok(()) +// } +// +// async fn get_login_data(&self, key_login_session: &KeyLoginSession) -> Result { +// let email = self.email_from_key_session(key_login_session).await?; +// let st = self.state.read().await; +// let user = st.users.get(&email).ok_or_else(|| "unknown email".to_string())?; +// let code = user.code.as_ref().ok_or_else(|| "code not registered".to_string())?; +// Ok(code.data.clone()) +// } +// +// async fn login_code(&self, email: &Email, passcode: &[u64]) -> Result { +// let mut st = self.state.write().await; +// let user = st.users.get(email).ok_or_else(|| "unknown email".to_string())?; +// let code = user.code.as_ref().ok_or_else(|| "code not registered".to_string())?; +// if code.passcode.as_slice() != passcode { +// return Err("invalid passcode".to_string()); +// } +// let sess = (self.new_code_session)(); +// st.code_sessions.insert(sess.clone(), email.clone()); +// Ok(sess) +// } +// } diff --git a/src/models/app.rs b/src/models/app.rs index 0e27968..c1078fc 100644 --- a/src/models/app.rs +++ b/src/models/app.rs @@ -7,7 +7,6 @@ use nkode_rs::nkode_core::policy::NKodePolicy; use crate::models::email::Email; use crate::models::opaque::{OpaqueSessionKey, UserSecretKey}; -#[allow(dead_code)] struct LoginSession { email: Email, session_id: Uuid, @@ -55,7 +54,7 @@ pub struct CodeLoginData { pub(crate) keypad: Keypad, } -pub trait ServerAPI { +pub trait ClientAuthAPI { async fn register_key(&self, email: &Email, secret_key: &UserSecretKey) -> Result<(), String>; async fn register_code(&self, email: &Email, passcode: &[u64], key_login_session: &KeyLoginSession, data: &CodeLoginData) -> Result<(), String>; async fn login_key(&self, email: &Email, secret_key: &UserSecretKey) -> Result; @@ -64,4 +63,5 @@ pub trait ServerAPI { async fn get_login_data(&self, key_login_session: &KeyLoginSession) -> Result; async fn is_code_registered(&self, key_login_session: &KeyLoginSession) -> Result; async fn get_policy(&self) -> Result; -} \ No newline at end of file +} + diff --git a/src/models/opaque.rs b/src/models/opaque.rs index ca8fc95..0c48332 100644 --- a/src/models/opaque.rs +++ b/src/models/opaque.rs @@ -11,6 +11,8 @@ use nkode_rs::from_bytes::FromBytes; const USER_KEY_SIZE: usize = 16; +#[derive(Clone)] +#[derive(PartialEq)] pub struct UserSecretKey(Zeroizing<[u8; USER_KEY_SIZE]>); impl UserSecretKey { @@ -26,7 +28,7 @@ impl FromBytes for UserSecretKey { } } -const OPAQUE_SESSION_KEY_SIZE: usize = 32; +const OPAQUE_SESSION_KEY_SIZE: usize = 64; pub struct OpaqueSessionKey(Zeroizing<[u8; OPAQUE_SESSION_KEY_SIZE]>); diff --git a/src/opaque/client.rs b/src/opaque/client.rs index e3f3da4..bc26b55 100644 --- a/src/opaque/client.rs +++ b/src/opaque/client.rs @@ -48,13 +48,13 @@ impl AuthenticationData { #[async_trait] pub trait ServerConnectionRegister { async fn start( - &mut self, + &self, identifier: &[u8], message: &RegistrationRequest, ) -> Result; async fn finish( - &mut self, + &self, session_id: &Uuid, password_file: PasswordFile, ) -> Result<(), ClientAuthError>; @@ -63,31 +63,48 @@ pub trait ServerConnectionRegister { #[async_trait] pub trait ServerConnectionLogin { async fn start( - &mut self, + &self, identifier: &[u8], request: &CredentialRequest, ) -> Result; async fn finish( - &mut self, + &self, session_id: &Uuid, message: &CredentialFinalization, ) -> Result; } -// --- OPAQUE client driver --- -pub struct OpaqueAuthentication; -impl OpaqueAuthentication { +pub struct OpaqueAuthRegister(R); + +impl OpaqueAuthRegister { + pub fn new(server: R) -> Self { + Self(server) + } +} + +pub struct OpaqueAuthLogin(L); + +impl OpaqueAuthLogin { + pub fn new(server: L) -> Self { + Self(server) + } +} + + + +impl OpaqueAuthRegister { pub async fn register( + &self, auth: &AuthenticationData, - server: &mut impl ServerConnectionRegister, + // server: &mut impl ServerConnectionRegister, ) -> Result<(), ClientAuthError> { let mut rng = OsRng; let start = ClientRegistration::::start(&mut rng, &auth.secret) .map_err(|e| ClientAuthError::Opaque(format!("client reg start: {e:?}")))?; - let server_start = server + let server_start = self.0 .start(&auth.identifier, &start.message) .await .map_err(|e| ClientAuthError::Transport(format!("server reg start: {e:?}")))?; @@ -102,21 +119,23 @@ impl OpaqueAuthentication { ) .map_err(|e| ClientAuthError::Opaque(format!("client reg finish: {e:?}")))?; let password_file: PasswordFile = finish.message.serialize(); - server + self.0 .finish(&server_start.session_id, password_file) .await .map_err(|e| ClientAuthError::Transport(format!("server reg finish: {e:?}")))?; Ok(()) } +} +impl OpaqueAuthLogin { pub async fn login( + &self, auth: &AuthenticationData, - server: &mut impl ServerConnectionLogin, ) -> Result, ClientAuthError> { let mut rng = OsRng; let start = ClientLogin::::start(&mut rng, &auth.secret) .map_err(|e| ClientAuthError::Opaque(format!("client login start: {e:?}")))?; - let server_start = server + let server_start = self.0 .start(&auth.identifier, &start.message) .await .map_err(|e| ClientAuthError::Transport(format!("server login start: {e:?}")))?; @@ -130,7 +149,7 @@ impl OpaqueAuthentication { ClientLoginFinishParameters::default(), ) .map_err(|e| ClientAuthError::Opaque(format!("client login finish: {e:?}")))?; - server + self.0 .finish(&server_start.session_id, &finish.message) .await .map_err(|e| ClientAuthError::Transport(format!("server login finish: {e:?}")))?; diff --git a/src/opaque/server.rs b/src/opaque/server.rs index 8014a62..5a86961 100644 --- a/src/opaque/server.rs +++ b/src/opaque/server.rs @@ -28,7 +28,9 @@ pub trait CredKind { } } +#[derive(Clone)] pub struct Key; +#[derive(Clone)] pub struct Code; impl CredKind for Key { diff --git a/src/repository/opaque/in_memory/in_memory_transport.rs b/src/repository/opaque/in_memory/in_memory_transport.rs index 4c6ce4f..3b8a3fa 100644 --- a/src/repository/opaque/in_memory/in_memory_transport.rs +++ b/src/repository/opaque/in_memory/in_memory_transport.rs @@ -10,15 +10,16 @@ use crate::opaque::server::{OpaqueAuth, CredKind, Key, Code}; use crate::repository::opaque::in_memory::in_memory_auth_repo::InMemoryAuthRepo; use crate::repository::opaque::in_memory::in_memory_auth_session::InMemoryAuthSession; +#[derive(Clone)] pub struct InMemoryServer { - auth: OpaqueAuth, + auth: Arc>>, _kind: PhantomData, } impl InMemoryServer { pub fn new(server_setup: NKodeServerSetup) -> Self { Self { - auth: OpaqueAuth::new(server_setup, InMemoryAuthRepo::new(), InMemoryAuthSession::new()), + auth: Arc::new(Mutex::new(OpaqueAuth::new(server_setup, InMemoryAuthRepo::new(), InMemoryAuthSession::new()))), _kind: PhantomData, } } @@ -33,24 +34,24 @@ where K: CredKind + Send + Sync, { async fn start( - &mut self, + &self, identifier: &[u8], message: &RegistrationRequest, ) -> Result { // Server API takes ownership; client trait gives us a reference. // opaque-ke request types are typically Clone; if not, you'll need to adjust signatures. - self.auth + self.auth.lock().await .reg_start::(identifier, message.clone()) .await .map_err(|e| ClientAuthError::Transport(e)) } async fn finish( - &mut self, + &self, session_id: &Uuid, password_file: PasswordFile, ) -> Result<(), ClientAuthError> { - self.auth + self.auth.lock().await .reg_finish::(session_id, password_file) .await .map_err(|e| ClientAuthError::Transport(e)) @@ -63,24 +64,24 @@ where K: CredKind + Send + Sync, { async fn start( - &mut self, + &self, identifier: &[u8], request: &CredentialRequest, ) -> Result { - self.auth + self.auth.lock().await .login_start::(identifier, request.clone()) .await .map_err(|e| ClientAuthError::Transport(e)) } async fn finish( - &mut self, + &self, session_id: &Uuid, message: &CredentialFinalization, ) -> Result { // Server computes its own session key too; we just need it to validate and complete. let key = self - .auth + .auth.lock().await .login_finish::(session_id, message.clone()) .await .map_err(|e| ClientAuthError::Transport(e))?; @@ -89,74 +90,74 @@ where } } -pub struct InMemSharedServer { - inner: Arc>>, - _k: PhantomData, -} - -impl InMemSharedServer { - pub fn new(inner: Arc>>) -> Self { - Self { inner, _k: PhantomData } - } -} - -#[async_trait::async_trait] -impl ServerConnectionRegister for InMemSharedServer -where - K: CredKind + Send + Sync, -{ - async fn start( - &mut self, - identifier: &[u8], - message: &RegistrationRequest, - ) -> Result { - let mut guard = self.inner.lock().await; - guard - .reg_start::(identifier, message.clone()) - .await - .map_err(ClientAuthError::Transport) - } - - async fn finish( - &mut self, - session_id: &Uuid, - password_file: PasswordFile, - ) -> Result<(), ClientAuthError> { - let mut guard = self.inner.lock().await; - guard - .reg_finish::(session_id, password_file) - .await - .map_err(ClientAuthError::Transport) - } -} - -#[async_trait::async_trait] -impl ServerConnectionLogin for InMemSharedServer -where - K: CredKind + Send + Sync, -{ - async fn start( - &mut self, - identifier: &[u8], - request: &CredentialRequest, - ) -> Result { - let mut guard = self.inner.lock().await; - guard - .login_start::(identifier, request.clone()) - .await - .map_err(ClientAuthError::Transport) - } - - async fn finish( - &mut self, - session_id: &Uuid, - message: &CredentialFinalization, - ) -> Result { - let mut guard = self.inner.lock().await; - let key = guard - .login_finish::(session_id, message.clone()) - .await - .map_err(ClientAuthError::Transport)?; - Ok(key) - } -} +// pub struct InMemSharedServer { +// inner: Arc>>, +// _k: PhantomData, +// } +// +// impl InMemSharedServer { +// pub fn new(inner: Arc>>) -> Self { +// Self { inner, _k: PhantomData } +// } +// } +// +// #[async_trait::async_trait] +// impl ServerConnectionRegister for InMemSharedServer +// where +// K: CredKind + Send + Sync, +// { +// async fn start( +// &mut self, +// identifier: &[u8], +// message: &RegistrationRequest, +// ) -> Result { +// let mut guard = self.inner.lock().await; +// guard +// .reg_start::(identifier, message.clone()) +// .await +// .map_err(ClientAuthError::Transport) +// } +// +// async fn finish( +// &mut self, +// session_id: &Uuid, +// password_file: PasswordFile, +// ) -> Result<(), ClientAuthError> { +// let mut guard = self.inner.lock().await; +// guard +// .reg_finish::(session_id, password_file) +// .await +// .map_err(ClientAuthError::Transport) +// } +// } +// +// #[async_trait::async_trait] +// impl ServerConnectionLogin for InMemSharedServer +// where +// K: CredKind + Send + Sync, +// { +// async fn start( +// &mut self, +// identifier: &[u8], +// request: &CredentialRequest, +// ) -> Result { +// let mut guard = self.inner.lock().await; +// guard +// .login_start::(identifier, request.clone()) +// .await +// .map_err(ClientAuthError::Transport) +// } +// +// async fn finish( +// &mut self, +// session_id: &Uuid, +// message: &CredentialFinalization, +// ) -> Result { +// let mut guard = self.inner.lock().await; +// let key = guard +// .login_finish::(session_id, message.clone()) +// .await +// .map_err(ClientAuthError::Transport)?; +// Ok(key) +// } +// } diff --git a/tests/in_memory_test.rs b/tests/in_memory_test.rs index 3a361f4..f937580 100644 --- a/tests/in_memory_test.rs +++ b/tests/in_memory_test.rs @@ -1,61 +1,31 @@ -use std::sync::Arc; use opaque_ke::rand::rngs::OsRng; -use tokio::sync::Mutex; -use nkode_protocol::opaque::client::{AuthenticationData, OpaqueAuthentication, ClientAuthError}; +use nkode_protocol::opaque::client::{AuthenticationData, ClientAuthError, OpaqueAuthLogin, OpaqueAuthRegister}; use nkode_protocol::models::opaque::NKodeServerSetup; -use nkode_protocol::opaque::server::{Code, Key, OpaqueAuth}; -use nkode_protocol::repository::opaque::in_memory::in_memory_auth_repo::InMemoryAuthRepo; -use nkode_protocol::repository::opaque::in_memory::in_memory_auth_session::InMemoryAuthSession; -use nkode_protocol::repository::opaque::in_memory::in_memory_transport::{InMemoryCodeServer, InMemoryKeyServer, InMemSharedServer}; +use nkode_protocol::repository::opaque::in_memory::in_memory_transport::{InMemoryCodeServer, InMemoryKeyServer}; #[tokio::test] async fn opaque_key_registration_and_login_roundtrip() { let mut rng = OsRng; let server_setup = NKodeServerSetup::new(&mut rng); - let mut server = InMemoryKeyServer::new(server_setup); - let auth = AuthenticationData::from_secret_key("a@b.com", b"supersecret16bytes"); - OpaqueAuthentication::register(&auth, &mut server) - .await - .expect("registration should succeed"); - let session_key = OpaqueAuthentication::login(&auth, &mut server) + let server = InMemoryKeyServer::new(server_setup); + let auth_reg = OpaqueAuthRegister::new(server.clone()); + let auth_data = AuthenticationData::from_secret_key("a@b.com", b"supersecret16bytes"); + auth_reg.register(&auth_data).await.expect("registration should succeed"); + let login_reg = OpaqueAuthLogin::new(server); + let session_key =login_reg.login(&auth_data) .await .expect("login should succeed"); assert!(!session_key.is_empty()); } -#[tokio::test] -async fn opaque_code_registration_and_login_roundtrip() { - let mut rng = OsRng; - let server_setup = NKodeServerSetup::new(&mut rng); - let shared = Arc::new(Mutex::new(OpaqueAuth::new( - server_setup, - InMemoryAuthRepo::new(), - InMemoryAuthSession::new(), - ))); - let mut key_server = InMemSharedServer::::new(shared.clone()); - let mut code_server = InMemSharedServer::::new(shared.clone()); - let email = "c@d.com"; - let key_auth = AuthenticationData::from_secret_key(email, b"supersecret16bytes"); - OpaqueAuthentication::register(&key_auth, &mut key_server) - .await - .expect("key registration should succeed"); - let code = vec![1usize, 2, 3, 4, 5, 6]; - let code_auth = AuthenticationData::from_code(email, &code); - OpaqueAuthentication::register(&code_auth, &mut code_server) - .await - .expect("code registration should succeed after key exists"); - let session_key = OpaqueAuthentication::login(&code_auth, &mut code_server) - .await - .expect("login should succeed"); - assert!(!session_key.is_empty()); -} #[tokio::test] async fn opaque_login_fails_if_not_registered() { let mut rng = OsRng; let server_setup = NKodeServerSetup::new(&mut rng); - let mut server = InMemoryKeyServer::new(server_setup); + let server = InMemoryKeyServer::new(server_setup); let auth = AuthenticationData::from_secret_key("nope@nope.com", b"supersecret16bytes"); - let err = OpaqueAuthentication::login(&auth, &mut server) + let login_reg = OpaqueAuthLogin::new(server); + let err = login_reg.login(&auth) .await .expect_err("login should fail if user not registered"); match err { @@ -69,8 +39,9 @@ async fn cannot_register_code_before_key() { let mut rng = OsRng; let server_setup = NKodeServerSetup::new(&mut rng); let mut server = InMemoryCodeServer::new(server_setup); + let auth_reg = OpaqueAuthRegister::new(server.clone()); let auth = AuthenticationData::from_code("x@y.com", &[1usize,2,3,4]); - let err = OpaqueAuthentication::register(&auth, &mut server) + let err = auth_reg.register(&auth) .await .expect_err("should fail because key is not registered"); match err {