implement in-memory server

This commit is contained in:
2025-12-17 20:23:26 -06:00
parent fe499add9e
commit 48cd1d0e31
8 changed files with 96 additions and 131 deletions

View File

@@ -1,28 +1,28 @@
use std::marker::PhantomData;
use nkode_rs::nkode_core::keypad::Keypad;
use crate::shared::models::app::{OpaqueAPI, AuthAPI, CodeLoginData, CodeLoggedInSession, Icon, IconID, KeyLoggedInSession, ICON_ID_SIZE, LoggedInSession};
use crate::shared::models::app::{AuthAPI, CodeLoginData, CodeLoggedInSession, Icon, IconID, KeyLoggedInSession, ICON_ID_SIZE};
use crate::shared::models::email::Email;
use crate::shared::models::opaque::{OpaqueLoginSession, UserSecretKey};
use crate::shared::models::opaque::{UserSecretKey};
use anyhow::Result;
use nkode_rs::nkode_core::nkode_cipher::NKodeCipher;
use nkode_rs::from_bytes::FromBytes;
use nkode_rs::nkode_core::chacha20prng::Nonce;
use async_trait::async_trait;
use nkode_rs::nkode_core::policy::{NKodePolicy, DEFAULT_POLICY};
use crate::client::opaque::{AuthenticationData, OpaqueAuthLogin, OpaqueAuthRegister, ServerConnectionLogin, ServerConnectionRegister};
use crate::client::opaque::{AuthenticationData, OpaqueAuth, ServerConnectionLogin, ServerConnectionRegister};
pub struct Login;
pub struct Register;
struct Login;
struct Register;
pub struct ClientAppKey<State, S: OpaqueAPI> {
pub struct ClientAppKey<State, S: AuthAPI> {
api: S,
email: Email,
user_secret_key: UserSecretKey,
_state: PhantomData<State>
}
impl <S: OpaqueAPI> ClientAppKey<Register,S> {
impl <S: AuthAPI> ClientAppKey<Register,S> {
pub async fn register(self) -> Result<ClientAppKey<Login, S>, String> {
self.api.register_key(&self.email, &self.user_secret_key).await?;
Ok(ClientAppKey {
@@ -34,7 +34,7 @@ impl <S: OpaqueAPI> ClientAppKey<Register,S> {
}
}
impl <S: OpaqueAPI> ClientAppKey<Login,S> {
impl <S: AuthAPI> ClientAppKey<Login,S> {
pub async fn login(self) -> Result<ClientAppKeyLoggedIn<S>,String> {
let key_login = self.api.login_key(&self.email, &self.user_secret_key).await?;
Ok(ClientAppKeyLoggedIn{
@@ -46,14 +46,14 @@ impl <S: OpaqueAPI> ClientAppKey<Login,S> {
}
}
pub struct ClientAppKeyLoggedIn<S: OpaqueAPI> {
pub struct ClientAppKeyLoggedIn<S: AuthAPI> {
api: S,
email: Email,
user_secret_key: UserSecretKey,
key_login: KeyLoggedInSession,
}
impl <S: OpaqueAPI + AuthAPI> ClientAppKeyLoggedIn<S> {
impl <S: AuthAPI> ClientAppKeyLoggedIn<S> {
pub async fn register_code(self) -> Result<ClientAppCodeRegister<S>, String> {
let icon_nonce = Nonce::new();
let icons = self.get_icons(&icon_nonce).await?;
@@ -100,7 +100,7 @@ impl <S: OpaqueAPI + AuthAPI> ClientAppKeyLoggedIn<S> {
}
}
pub struct ClientAppCodeRegister<S: OpaqueAPI> {
pub struct ClientAppCodeRegister<S: AuthAPI> {
api: S,
email: Email,
user_secret_key: UserSecretKey,
@@ -110,7 +110,7 @@ pub struct ClientAppCodeRegister<S: OpaqueAPI> {
keypad: Keypad,
}
impl <S: OpaqueAPI + AuthAPI>ClientAppCodeRegister<S> {
impl <S: AuthAPI>ClientAppCodeRegister<S> {
pub async fn register(self, selected_icons: Vec<IconID>) -> Result<ClientAppCodeLogin<S>, String> {
let policy = self.api.get_policy().await?;
let keypad = Keypad::new(policy.clone());
@@ -139,7 +139,7 @@ impl <S: OpaqueAPI + AuthAPI>ClientAppCodeRegister<S> {
}
}
pub struct ClientAppCodeLogin<S: OpaqueAPI> {
pub struct ClientAppCodeLogin<S: AuthAPI> {
api: S,
email: Email,
mask: Vec<u64>,
@@ -148,7 +148,7 @@ pub struct ClientAppCodeLogin<S: OpaqueAPI> {
cipher: NKodeCipher
}
impl <S: OpaqueAPI>ClientAppCodeLogin<S> {
impl <S: AuthAPI>ClientAppCodeLogin<S> {
pub fn sort_icons(&self) -> Vec<Icon> {
nkode_rs::tensor::reorder(
&self.icons,
@@ -162,23 +162,22 @@ impl <S: OpaqueAPI>ClientAppCodeLogin<S> {
}
}
pub struct ClientAuth<
R: ServerConnectionRegister + Clone,
L: ServerConnectionLogin + Clone,
pub struct ClientAuth<'a, R, K>
where
R: ServerConnectionRegister + ServerConnectionLogin + Clone,
K: AuthAPI
> {
opaque_key_register: OpaqueAuthRegister<R>,
opaque_key_login: OpaqueAuthLogin<L>,
opaque_code_register: OpaqueAuthRegister<R>,
opaque_code_login: OpaqueAuthLogin<L>,
{
opaque_key_register: OpaqueAuth<'a, R>,
opaque_key_login: OpaqueAuth<'a, R>,
opaque_code_register: OpaqueAuth<'a, R>,
opaque_code_login: OpaqueAuth<'a, R>,
nkode_api: K,
}
#[async_trait]
impl<R, L, K> OpaqueAPI for ClientAuth<R, L,K>
impl<'a, R, K> AuthAPI for ClientAuth<'a, R, K>
where
R: ServerConnectionRegister + Clone + Sync + Send,
L: ServerConnectionLogin + Clone + Sync + Send,
R: ServerConnectionRegister + ServerConnectionLogin + Clone + Sync + Send,
K: AuthAPI + Sync + Send,
{
async fn register_key(&self, email: &Email, secret_key: &UserSecretKey) -> Result<(), String> {
@@ -193,36 +192,16 @@ where
async fn login_key(&self, email: &Email, secret_key: &UserSecretKey) -> Result<KeyLoggedInSession, String> {
let auth_data = AuthenticationData::from_secret_key(&email.as_str(), secret_key.as_slice());
let session_key = self.opaque_key_login.login(&auth_data).await.map_err(|e| format!("error: {}", e))?;
todo!()
// Ok(KeyLoggedInSession(
// LoggedInSession {
// email: email.clone(),
// session_key
// }
// ))
let session = self.opaque_key_login.login(&auth_data).await.map_err(|e| format!("error: {}", e))?;
Ok(KeyLoggedInSession(session))
}
async fn login_code(&self, email: &Email, passcode: &[u64]) -> Result<CodeLoggedInSession, String> {
let auth_data = AuthenticationData::from_code(email.as_str(), passcode);
let session_key = self.opaque_code_login.login(&auth_data).await.map_err(|e| format!("error: {}", e))?;
todo!()
// Ok(CodeLoggedInSession(
// LoggedInSession {
// email: email.clone(),
// session_key
// }
// ))
let session = self.opaque_code_login.login(&auth_data).await.map_err(|e| format!("error: {}", e))?;
Ok(CodeLoggedInSession(session))
}
}
#[async_trait]
impl<R, L, K> AuthAPI for ClientAuth<R, L, K>
where
R: ServerConnectionRegister + Clone + Sync + Send,
L: ServerConnectionLogin + Clone + Sync + Send,
K: AuthAPI + Sync + Send,
{
async fn get_new_icons(
&self,
key_login_session: &KeyLoggedInSession,

View File

@@ -1,6 +1,5 @@
use std::fmt;
use async_trait::async_trait;
use nkode_rs::from_bytes::FromBytes;
use uuid::Uuid;
use opaque_ke::rand::rngs::OsRng;
use opaque_ke::{
@@ -10,7 +9,7 @@ use opaque_ke::{
RegistrationRequest,
};
use crate::shared::models::app::LoggedInSession;
use crate::shared::models::opaque::{OpaqueRegisterSession, OpaqueLoginSession, NKodeCipherSuite, PasswordFile, OpaqueSessionKey};
use crate::shared::models::opaque::{OpaqueRegisterSession, OpaqueLoginSession, NKodeCipherSuite, PasswordFile};
#[derive(Debug)]
pub enum ClientAuthError {
@@ -85,86 +84,61 @@ pub trait ServerConnectionLogin {
) -> Result<LoggedInSession, ClientAuthError>;
}
pub struct OpaqueAuth<'a, S>(&'a S);
pub struct OpaqueAuthRegister<R: ServerConnectionRegister + Clone>(R);
impl <R: ServerConnectionRegister + Clone> OpaqueAuthRegister<R> {
pub fn new(server: R) -> Self {
impl<'a, S> OpaqueAuth<'a, S> {
pub fn new(server: &'a S) -> Self {
Self(server)
}
}
pub struct OpaqueAuthLogin<L: ServerConnectionLogin + Clone>(L);
impl <L: ServerConnectionLogin + Clone> OpaqueAuthLogin<L> {
pub fn new(server: L) -> Self {
Self(server)
}
}
impl <R: ServerConnectionRegister + Clone>OpaqueAuthRegister<R> {
pub async fn register(
&self,
auth: &AuthenticationData,
) -> Result<(), ClientAuthError> {
impl<S> OpaqueAuth<'_, S>
where
S: ServerConnectionRegister + ServerConnectionLogin,
{
pub async fn register(&self, auth: &AuthenticationData) -> Result<(), ClientAuthError> {
let mut rng = OsRng;
let start = ClientRegistration::<NKodeCipherSuite>::start(&mut rng, &auth.secret)
.map_err(|e| ClientAuthError::Opaque(format!("client reg start: {e:?}")))?;
let server_start = self.0
.start(&auth.identifier, &start.message)
let server_start = <S as ServerConnectionRegister>::start(&self.0, &auth.identifier, &start.message)
.await
.map_err(|e| ClientAuthError::Transport(format!("server reg start: {e:?}")))?;
let server_msg = server_start.response;
let finish = start
.state
.finish(
&mut rng,
&auth.secret,
server_msg,
server_start.response,
ClientRegistrationFinishParameters::default(),
)
.map_err(|e| ClientAuthError::Opaque(format!("client reg finish: {e:?}")))?;
let password_file: PasswordFile = finish.message.serialize();
self.0
.finish(&server_start.session_id, password_file)
<S as ServerConnectionRegister>::finish(&self.0, &server_start.session_id, password_file)
.await
.map_err(|e| ClientAuthError::Transport(format!("server reg finish: {e:?}")))?;
Ok(())
}
}
impl <L: ServerConnectionLogin + Clone>OpaqueAuthLogin<L> {
pub async fn login(
&self,
auth: &AuthenticationData,
) -> Result<OpaqueSessionKey, ClientAuthError> {
pub async fn login(&self, auth: &AuthenticationData) -> Result<LoggedInSession, ClientAuthError> {
let mut rng = OsRng;
let start = ClientLogin::<NKodeCipherSuite>::start(&mut rng, &auth.secret)
.map_err(|e| ClientAuthError::Opaque(format!("client login start: {e:?}")))?;
let server_start = self.0
.start(&auth.identifier, &start.message)
.await
.map_err(|e| ClientAuthError::Transport(format!("server login start: {e:?}")))?;
let server_msg = server_start.response.clone();
let server_start =
<S as ServerConnectionLogin>::start(&self.0, &auth.identifier, &start.message)
.await
.map_err(|e| ClientAuthError::Transport(format!("server login start: {e:?}")))?;
let finish = start
.state
.finish(
&mut rng,
&auth.secret,
server_msg,
server_start.response,
ClientLoginFinishParameters::default(),
)
.map_err(|e| ClientAuthError::Opaque(format!("client login finish: {e:?}")))?;
self.0
.finish(&server_start.session_id, &finish.message)
let session = <S as ServerConnectionLogin>::finish(&self.0, &server_start.session_id, &finish.message)
.await
.map_err(|e| ClientAuthError::Transport(format!("server login finish: {e:?}")))?;
Ok(
OpaqueSessionKey::from_bytes(finish.session_key.as_slice())
.map_err(|e| ClientAuthError::Opaque(format!("from bytes error {e:?}")))?
)
Ok(session)
}
}

View File

@@ -10,6 +10,7 @@ use crate::shared::models::app::{CodeLoggedInSession, CodeLoginData, KeyLoggedIn
use crate::shared::models::email::Email;
use crate::shared::models::opaque::{NKodeCipherSuite, NKodeServerSetup, OpaqueLoginSession, OpaqueRegisterSession, OpaqueSessionKey, PasswordFile};
pub struct ServerApp<R: OpaqueDatabaseRepo, S: OpaqueSessionRepo, U: UserRepo> {
server_setup: NKodeServerSetup,
opaque_db: R,

View File

@@ -1,5 +1,4 @@
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::Arc;
use async_trait::async_trait;
use opaque_ke::ServerLogin;

View File

@@ -2,7 +2,7 @@ use async_trait::async_trait;
use std::marker::PhantomData;
use uuid::Uuid;
use opaque_ke::{CredentialFinalization, CredentialRequest, RegistrationRequest};
use crate::shared::models::opaque::{NKodeCipherSuite, NKodeServerSetup, OpaqueLoginSession, OpaqueRegisterSession, PasswordFile};
use crate::shared::models::opaque::{NKodeCipherSuite, OpaqueLoginSession, OpaqueRegisterSession, PasswordFile};
use crate::client::opaque::{ClientAuthError, ServerConnectionLogin, ServerConnectionRegister};
use crate::server::app::{Code, Key};
use crate::server::app::ServerApp;
@@ -12,30 +12,25 @@ use crate::server::repository::in_memory::in_memory_opaque_session::InMemoryOpaq
use crate::server::repository::in_memory::in_memory_user_db::InMemoryUserDB;
use crate::shared::models::app::LoggedInSession;
pub struct InMemoryServer<K: CredKind> {
auth_db: ServerApp<InMemoryOpaqueDB, InMemoryOpaqueSession, InMemoryUserDB>,
pub type InMemoryKeyServer<'a> = InMemoryServer<'a, Key>;
pub type InMemoryCodeServer<'a> = InMemoryServer<'a, Code>;
pub struct InMemoryServer<'a, K: CredKind> {
auth_db: &'a ServerApp<InMemoryOpaqueDB, InMemoryOpaqueSession, InMemoryUserDB>,
_kind: PhantomData<K>,
}
impl<K: CredKind> InMemoryServer<K> {
pub fn new(server_setup: NKodeServerSetup) -> Self {
impl<'a, K: CredKind> InMemoryServer<'a, K> {
pub fn new(server_app: &'a ServerApp<InMemoryOpaqueDB, InMemoryOpaqueSession, InMemoryUserDB>) -> Self {
Self {
auth_db: ServerApp::new(
server_setup,
InMemoryOpaqueDB::new(),
InMemoryOpaqueSession::new(),
InMemoryUserDB::new()
),
auth_db: server_app,
_kind: PhantomData,
}
}
}
pub type InMemoryKeyServer = InMemoryServer<Key>;
pub type InMemoryCodeServer = InMemoryServer<Code>;
#[async_trait]
impl<K> ServerConnectionRegister for InMemoryServer<K>
impl<'a, K> ServerConnectionRegister for InMemoryServer<'a, K>
where
K: CredKind + Sync,
{
@@ -64,7 +59,7 @@ where
}
#[async_trait]
impl<K> ServerConnectionLogin for InMemoryServer<K>
impl<'a, K> ServerConnectionLogin for InMemoryServer<'a,K>
where
K: CredKind + Send + Sync,
{

View File

@@ -1,4 +1,4 @@
pub mod in_memory_opaque_db;
pub mod in_memory_transport;
pub mod in_memory_opaque_session;
mod in_memory_user_db;
pub mod in_memory_user_db;

View File

@@ -58,15 +58,12 @@ pub struct CodeLoginData {
}
#[async_trait]
pub trait OpaqueAPI {
pub trait AuthAPI {
async fn register_key(&self, email: &Email, secret_key: &UserSecretKey) -> Result<(), String>;
async fn register_code(&self, email: &Email, passcode: &[u64], key_login_session: &KeyLoggedInSession, data: &CodeLoginData) -> Result<(), String>;
async fn login_key(&self, email: &Email, secret_key: &UserSecretKey) -> Result<KeyLoggedInSession, String>;
async fn login_code(&self, email: &Email, passcode: &[u64]) -> Result<CodeLoggedInSession, String>;
}
#[async_trait]
pub trait AuthAPI {
async fn get_new_icons(&self, key_login_session: &KeyLoggedInSession) -> Result<Vec<Icon>, String>;
async fn get_login_data(&self, key_login_session: &KeyLoggedInSession) -> Result<CodeLoginData, String>;
async fn is_code_registered(&self, key_login_session: &KeyLoggedInSession) -> Result<bool, String>;