implement server app

This commit is contained in:
2025-12-17 13:26:40 -06:00
parent 3029a41386
commit ac2ddf86df
5 changed files with 104 additions and 91 deletions

View File

@@ -1,11 +1,14 @@
use std::collections::HashMap;
use crate::shared::models::opaque::PasswordFile;
use crate::server::repository::opaque_repo::{OpaqueDatabaseRepo, AuthRepoError};
use tokio::sync::Mutex;
use std::sync::Arc;
use async_trait::async_trait;
#[derive(Debug, Default)]
pub struct InMemoryOpaqueDB {
key_entries: HashMap<KeyID, PasswordFile>,
code_entries: HashMap<CodeID, PasswordFile>,
key_entries: Arc<Mutex<HashMap<KeyID, PasswordFile>>>,
code_entries: Arc<Mutex<HashMap<CodeID, PasswordFile>>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -19,66 +22,67 @@ impl InMemoryOpaqueDB {
Self::default()
}
fn code_exists(&self, identifier: &CodeID) -> bool {
self.code_entries.contains_key(identifier)
async fn code_exists(&self, identifier: &CodeID) -> bool {
self.code_entries.lock().await.contains_key(identifier)
}
fn key_exists(&self, identifier: &KeyID) -> bool {
self.key_entries.contains_key(identifier)
async fn key_exists(&self, identifier: &KeyID) -> bool {
self.key_entries.lock().await.contains_key(identifier)
}
}
#[async_trait]
impl OpaqueDatabaseRepo for InMemoryOpaqueDB {
fn new_key(
&mut self,
async fn new_key(
&self,
identifier: &[u8],
password_file: PasswordFile,
) -> Result<(), AuthRepoError> {
if self.key_exists(&KeyID(identifier.to_vec())) {
if self.key_exists(&KeyID(identifier.to_vec())).await {
return Err(AuthRepoError::UserExists);
}
self.key_entries
self.key_entries.lock().await
.insert(KeyID(identifier.to_vec()), password_file);
Ok(())
}
fn new_code(
&mut self,
async fn new_code(
&self,
identifier: &[u8],
password_file: PasswordFile,
) -> Result<(), AuthRepoError> {
if !self.has_key(identifier) {
if !self.has_key(identifier).await {
return Err(AuthRepoError::KeyNotRegistered);
}
if self.code_exists(&CodeID(identifier.to_vec())) {
if self.code_exists(&CodeID(identifier.to_vec())).await {
return Err(AuthRepoError::UserExists);
}
self.code_entries
self.code_entries.lock().await
.insert(CodeID(identifier.to_vec()), password_file);
Ok(())
}
fn has_code(&self, identifier: &[u8]) -> bool {
self.code_entries
async fn has_code(&self, identifier: &[u8]) -> bool {
self.code_entries.lock().await
.contains_key(&CodeID(identifier.to_vec()))
}
fn has_key(&self, identifier: &[u8]) -> bool {
self.key_entries
async fn has_key(&self, identifier: &[u8]) -> bool {
self.key_entries.lock().await
.contains_key(&KeyID(identifier.to_vec()))
}
fn get_key_passcode_file(&self, identifier: &[u8]) -> Result<PasswordFile, AuthRepoError> {
self.key_entries
async fn get_key_passcode_file(&self, identifier: &[u8]) -> Result<PasswordFile, AuthRepoError> {
self.key_entries.lock().await
.get(&KeyID(identifier.to_vec()))
.cloned()
.ok_or(AuthRepoError::KeyNotRegistered)
}
fn get_code_passcode_file(&self, identifier: &[u8]) -> Result<PasswordFile, AuthRepoError> {
self.code_entries
async fn get_code_passcode_file(&self, identifier: &[u8]) -> Result<PasswordFile, AuthRepoError> {
self.code_entries.lock().await
.get(&CodeID(identifier.to_vec()))
.cloned()
.ok_or(AuthRepoError::CodeNotRegistered)

View File

@@ -1,5 +1,9 @@
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::Arc;
use async_trait::async_trait;
use opaque_ke::ServerLogin;
use tokio::sync::Mutex;
use uuid::Uuid;
use crate::server::models::{LoginCache, RegCache};
use crate::shared::models::opaque::NKodeCipherSuite;
@@ -7,8 +11,8 @@ use crate::server::repository::opaque_repo::OpaqueSessionRepo;
#[derive(Default)]
pub struct InMemoryOpaqueSession {
reg_sessions: HashMap<Uuid, RegCache>,
login_sessions: HashMap<Uuid, LoginCache>,
reg_sessions: Arc<Mutex<HashMap<Uuid, RegCache>>>,
login_sessions: Arc<Mutex<HashMap<Uuid, LoginCache>>>,
}
impl InMemoryOpaqueSession {
@@ -17,28 +21,27 @@ impl InMemoryOpaqueSession {
}
}
#[async_trait]
impl OpaqueSessionRepo for InMemoryOpaqueSession {
fn new_reg_session(&mut self, identifier: &[u8]) -> Result<RegCache, String> {
async fn new_reg_session(&self, identifier: &[u8]) -> Result<RegCache, String> {
let cache = RegCache {
session_id: Uuid::new_v4(),
identifier: identifier.to_vec(),
};
// Extremely unlikely collision, but keep the invariant anyway.
if self.reg_sessions.contains_key(&cache.session_id) {
if self.reg_sessions.lock().await.contains_key(&cache.session_id) {
return Err("session_id collision".to_string());
}
self.reg_sessions.insert(cache.session_id, RegCache {
self.reg_sessions.lock().await.insert(cache.session_id, RegCache {
session_id: cache.session_id,
identifier: cache.identifier.clone(),
});
Ok(cache)
}
fn get_reg_session(&self, session_id: &Uuid) -> Result<RegCache, String> {
async fn get_reg_session(&self, session_id: &Uuid) -> Result<RegCache, String> {
self.reg_sessions
.lock()
.await
.get(session_id)
.map(|c| RegCache {
session_id: c.session_id,
@@ -47,15 +50,17 @@ impl OpaqueSessionRepo for InMemoryOpaqueSession {
.ok_or_else(|| "registration session not found".to_string())
}
fn clear_reg_session(&mut self, session_id: &Uuid) -> Result<(), String> {
async fn clear_reg_session(&self, session_id: &Uuid) -> Result<(), String> {
self.reg_sessions
.lock()
.await
.remove(session_id)
.map(|_| ())
.ok_or_else(|| "registration session not found".to_string())
}
fn new_login_session(
&mut self,
async fn new_login_session(
&self,
identifier: &[u8],
server_login: ServerLogin<NKodeCipherSuite>,
) -> Result<LoginCache, String> {
@@ -64,12 +69,10 @@ impl OpaqueSessionRepo for InMemoryOpaqueSession {
identifiers: identifier.to_vec(),
server_login,
};
if self.login_sessions.contains_key(&cache.session_id) {
if self.login_sessions.lock().await.contains_key(&cache.session_id) {
return Err("session_id collision".to_string());
}
self.login_sessions.insert(
self.login_sessions.lock().await.insert(
cache.session_id,
LoginCache {
session_id: cache.session_id,
@@ -78,12 +81,11 @@ impl OpaqueSessionRepo for InMemoryOpaqueSession {
server_login: cache.server_login.clone(),
},
);
Ok(cache)
}
fn get_login_session(&self, session_id: &Uuid) -> Result<LoginCache, String> {
self.login_sessions
async fn get_login_session(&self, session_id: &Uuid) -> Result<LoginCache, String> {
self.login_sessions.lock().await
.get(session_id)
.map(|c| LoginCache {
session_id: c.session_id,
@@ -93,8 +95,8 @@ impl OpaqueSessionRepo for InMemoryOpaqueSession {
.ok_or_else(|| "login session not found".to_string())
}
fn clear_login_session(&mut self, session_id: &Uuid) -> Result<(), String> {
self.login_sessions
async fn clear_login_session(&self, session_id: &Uuid) -> Result<(), String> {
self.login_sessions.lock().await
.remove(session_id)
.map(|_| ())
.ok_or_else(|| "login session not found".to_string())

View File

@@ -1,3 +1,4 @@
use async_trait::async_trait;
use uuid::Uuid;
use opaque_ke::ServerLogin;
use crate::server::models::{LoginCache, RegCache};
@@ -9,27 +10,29 @@ pub enum AuthRepoError {
CodeNotRegistered,
}
pub trait OpaqueDatabaseRepo {
fn new_key(&mut self, identifier: &[u8], password_file: PasswordFile) -> Result<(), AuthRepoError>;
fn new_code(&mut self, identifier: &[u8], password_file: PasswordFile) -> Result<(), AuthRepoError>;
#[async_trait]
pub trait OpaqueDatabaseRepo: Send + Sync {
async fn new_key(&self, identifier: &[u8], password_file: PasswordFile) -> Result<(), AuthRepoError>;
async fn new_code(&self, identifier: &[u8], password_file: PasswordFile) -> Result<(), AuthRepoError>;
fn has_code(&self, identifier: &[u8]) -> bool;
fn has_key(&self, identifier: &[u8]) -> bool;
async fn has_code(&self, identifier: &[u8]) -> bool;
async fn has_key(&self, identifier: &[u8]) -> bool;
fn get_key_passcode_file(&self, identifier: &[u8]) -> Result<PasswordFile, AuthRepoError>;
fn get_code_passcode_file(&self, identifier: &[u8]) -> Result<PasswordFile, AuthRepoError>;
async fn get_key_passcode_file(&self, identifier: &[u8]) -> Result<PasswordFile, AuthRepoError>;
async fn get_code_passcode_file(&self, identifier: &[u8]) -> Result<PasswordFile, AuthRepoError>;
}
#[async_trait]
pub trait OpaqueSessionRepo {
fn new_reg_session(&mut self, identifier: &[u8]) -> Result<RegCache, String>;
fn get_reg_session(&self, session_id: &Uuid) -> Result<RegCache, String>;
fn clear_reg_session(&mut self, session_id: &Uuid) -> Result<(), String>;
async fn new_reg_session(&self, identifier: &[u8]) -> Result<RegCache, String>;
async fn get_reg_session(&self, session_id: &Uuid) -> Result<RegCache, String>;
async fn clear_reg_session(&self, session_id: &Uuid) -> Result<(), String>;
fn new_login_session(
&mut self,
async fn new_login_session(
&self,
identifier: &[u8],
server_login: ServerLogin<NKodeCipherSuite>,
) -> Result<LoginCache, String>;
fn get_login_session(&self, session_id: &Uuid) -> Result<LoginCache, String>;
fn clear_login_session(&mut self, session_id: &Uuid) -> Result<(), String>;
async fn get_login_session(&self, session_id: &Uuid) -> Result<LoginCache, String>;
async fn clear_login_session(&self, session_id: &Uuid) -> Result<(), String>;
}