refactor files
This commit is contained in:
1
src/server/repository/mod.rs
Normal file
1
src/server/repository/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod opaque;
|
||||
@@ -0,0 +1,86 @@
|
||||
use std::collections::HashMap;
|
||||
use crate::shared::models::opaque::PasswordFile;
|
||||
use crate::server::repository::opaque::repos::{OpaqueDatabaseRepo, AuthRepoError};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct InMemoryAuthRepo {
|
||||
key_entries: HashMap<KeyID, PasswordFile>,
|
||||
code_entries: HashMap<CodeID, PasswordFile>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct KeyID(Vec<u8>);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct CodeID(Vec<u8>);
|
||||
|
||||
impl InMemoryAuthRepo {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn code_exists(&self, identifier: &CodeID) -> bool {
|
||||
self.code_entries.contains_key(identifier)
|
||||
}
|
||||
|
||||
fn key_exists(&self, identifier: &KeyID) -> bool {
|
||||
self.key_entries.contains_key(identifier)
|
||||
}
|
||||
}
|
||||
|
||||
impl OpaqueDatabaseRepo for InMemoryAuthRepo {
|
||||
fn new_key(
|
||||
&mut self,
|
||||
identifier: &[u8],
|
||||
password_file: PasswordFile,
|
||||
) -> Result<(), AuthRepoError> {
|
||||
if self.key_exists(&KeyID(identifier.to_vec())) {
|
||||
return Err(AuthRepoError::UserExists);
|
||||
}
|
||||
|
||||
self.key_entries
|
||||
.insert(KeyID(identifier.to_vec()), password_file);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn new_code(
|
||||
&mut self,
|
||||
identifier: &[u8],
|
||||
password_file: PasswordFile,
|
||||
) -> Result<(), AuthRepoError> {
|
||||
if !self.has_key(identifier) {
|
||||
return Err(AuthRepoError::KeyNotRegistered);
|
||||
}
|
||||
if self.code_exists(&CodeID(identifier.to_vec())) {
|
||||
return Err(AuthRepoError::UserExists);
|
||||
}
|
||||
|
||||
self.code_entries
|
||||
.insert(CodeID(identifier.to_vec()), password_file);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn has_code(&self, identifier: &[u8]) -> bool {
|
||||
self.code_entries
|
||||
.contains_key(&CodeID(identifier.to_vec()))
|
||||
}
|
||||
|
||||
fn has_key(&self, identifier: &[u8]) -> bool {
|
||||
self.key_entries
|
||||
.contains_key(&KeyID(identifier.to_vec()))
|
||||
}
|
||||
|
||||
fn get_key_passcode_file(&self, identifier: &[u8]) -> Result<PasswordFile, AuthRepoError> {
|
||||
self.key_entries
|
||||
.get(&KeyID(identifier.to_vec()))
|
||||
.cloned()
|
||||
.ok_or(AuthRepoError::KeyNotRegistered)
|
||||
}
|
||||
|
||||
fn get_code_passcode_file(&self, identifier: &[u8]) -> Result<PasswordFile, AuthRepoError> {
|
||||
self.code_entries
|
||||
.get(&CodeID(identifier.to_vec()))
|
||||
.cloned()
|
||||
.ok_or(AuthRepoError::CodeNotRegistered)
|
||||
}
|
||||
}
|
||||
102
src/server/repository/opaque/in_memory/in_memory_auth_session.rs
Normal file
102
src/server/repository/opaque/in_memory/in_memory_auth_session.rs
Normal file
@@ -0,0 +1,102 @@
|
||||
use std::collections::HashMap;
|
||||
use crate::server::opaque::{LoginCache, RegCache};
|
||||
use opaque_ke::ServerLogin;
|
||||
use uuid::Uuid;
|
||||
use crate::shared::models::opaque::NKodeCipherSuite;
|
||||
use crate::server::repository::opaque::repos::OpaqueSessionRepo;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct InMemoryAuthSession {
|
||||
reg_sessions: HashMap<Uuid, RegCache>,
|
||||
login_sessions: HashMap<Uuid, LoginCache>,
|
||||
}
|
||||
|
||||
impl InMemoryAuthSession {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl OpaqueSessionRepo for InMemoryAuthSession {
|
||||
fn new_reg_session(&mut 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) {
|
||||
return Err("session_id collision".to_string());
|
||||
}
|
||||
|
||||
self.reg_sessions.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> {
|
||||
self.reg_sessions
|
||||
.get(session_id)
|
||||
.map(|c| RegCache {
|
||||
session_id: c.session_id,
|
||||
identifier: c.identifier.clone(),
|
||||
})
|
||||
.ok_or_else(|| "registration session not found".to_string())
|
||||
}
|
||||
|
||||
fn clear_reg_session(&mut self, session_id: &Uuid) -> Result<(), String> {
|
||||
self.reg_sessions
|
||||
.remove(session_id)
|
||||
.map(|_| ())
|
||||
.ok_or_else(|| "registration session not found".to_string())
|
||||
}
|
||||
|
||||
fn new_login_session(
|
||||
&mut self,
|
||||
identifier: &[u8],
|
||||
server_login: ServerLogin<NKodeCipherSuite>,
|
||||
) -> Result<LoginCache, String> {
|
||||
let cache = LoginCache {
|
||||
session_id: Uuid::new_v4(),
|
||||
identifiers: identifier.to_vec(),
|
||||
server_login,
|
||||
};
|
||||
|
||||
if self.login_sessions.contains_key(&cache.session_id) {
|
||||
return Err("session_id collision".to_string());
|
||||
}
|
||||
|
||||
self.login_sessions.insert(
|
||||
cache.session_id,
|
||||
LoginCache {
|
||||
session_id: cache.session_id,
|
||||
identifiers: cache.identifiers.clone(),
|
||||
// move is fine; we already moved into cache, so clone to keep both:
|
||||
server_login: cache.server_login.clone(),
|
||||
},
|
||||
);
|
||||
|
||||
Ok(cache)
|
||||
}
|
||||
|
||||
fn get_login_session(&self, session_id: &Uuid) -> Result<LoginCache, String> {
|
||||
self.login_sessions
|
||||
.get(session_id)
|
||||
.map(|c| LoginCache {
|
||||
session_id: c.session_id,
|
||||
identifiers: c.identifiers.clone(),
|
||||
server_login: c.server_login.clone(),
|
||||
})
|
||||
.ok_or_else(|| "login session not found".to_string())
|
||||
}
|
||||
|
||||
fn clear_login_session(&mut self, session_id: &Uuid) -> Result<(), String> {
|
||||
self.login_sessions
|
||||
.remove(session_id)
|
||||
.map(|_| ())
|
||||
.ok_or_else(|| "login session not found".to_string())
|
||||
}
|
||||
}
|
||||
163
src/server/repository/opaque/in_memory/in_memory_transport.rs
Normal file
163
src/server/repository/opaque/in_memory/in_memory_transport.rs
Normal file
@@ -0,0 +1,163 @@
|
||||
use async_trait::async_trait;
|
||||
use std::marker::PhantomData;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
use opaque_ke::{CredentialFinalization, CredentialRequest, RegistrationRequest};
|
||||
use crate::shared::models::opaque::{OpaqueLoginSession, NKodeCipherSuite, NKodeServerSetup, OpaqueSessionKey, PasswordFile, OpaqueRegisterSession};
|
||||
use crate::client::opaque::{ClientAuthError, ServerConnectionLogin, ServerConnectionRegister};
|
||||
use crate::server::opaque::{OpaqueAuth, CredKind, Key, Code};
|
||||
use crate::server::repository::opaque::in_memory::in_memory_auth_repo::InMemoryAuthRepo;
|
||||
use crate::server::repository::opaque::in_memory::in_memory_auth_session::InMemoryAuthSession;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InMemoryServer<K: CredKind> {
|
||||
auth: Arc<Mutex<OpaqueAuth<InMemoryAuthRepo, InMemoryAuthSession>>>,
|
||||
_kind: PhantomData<K>,
|
||||
}
|
||||
|
||||
impl<K: CredKind> InMemoryServer<K> {
|
||||
pub fn new(server_setup: NKodeServerSetup) -> Self {
|
||||
Self {
|
||||
auth: Arc::new(Mutex::new(OpaqueAuth::new(server_setup, InMemoryAuthRepo::new(), InMemoryAuthSession::new()))),
|
||||
_kind: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type InMemoryKeyServer = InMemoryServer<Key>;
|
||||
pub type InMemoryCodeServer = InMemoryServer<Code>;
|
||||
|
||||
#[async_trait]
|
||||
impl<K> ServerConnectionRegister for InMemoryServer<K>
|
||||
where
|
||||
K: CredKind + Sync,
|
||||
{
|
||||
async fn start(
|
||||
&self,
|
||||
identifier: &[u8],
|
||||
message: &RegistrationRequest<NKodeCipherSuite>,
|
||||
) -> Result<OpaqueRegisterSession, ClientAuthError> {
|
||||
// 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.lock().await
|
||||
.reg_start::<K>(identifier, message.clone())
|
||||
.await
|
||||
.map_err(|e| ClientAuthError::Transport(e))
|
||||
}
|
||||
|
||||
async fn finish(
|
||||
&self,
|
||||
session_id: &Uuid,
|
||||
password_file: PasswordFile,
|
||||
) -> Result<(), ClientAuthError> {
|
||||
self.auth.lock().await
|
||||
.reg_finish::<K>(session_id, password_file)
|
||||
.await
|
||||
.map_err(|e| ClientAuthError::Transport(e))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<K> ServerConnectionLogin for InMemoryServer<K>
|
||||
where
|
||||
K: CredKind + Send + Sync,
|
||||
{
|
||||
async fn start(
|
||||
&self,
|
||||
identifier: &[u8],
|
||||
request: &CredentialRequest<NKodeCipherSuite>,
|
||||
) -> Result<OpaqueLoginSession, ClientAuthError> {
|
||||
self.auth.lock().await
|
||||
.login_start::<K>(identifier, request.clone())
|
||||
.await
|
||||
.map_err(|e| ClientAuthError::Transport(e))
|
||||
}
|
||||
|
||||
async fn finish(
|
||||
&self,
|
||||
session_id: &Uuid,
|
||||
message: &CredentialFinalization<NKodeCipherSuite>,
|
||||
) -> Result<OpaqueSessionKey, ClientAuthError> {
|
||||
// Server computes its own session key too; we just need it to validate and complete.
|
||||
let key = self
|
||||
.auth.lock().await
|
||||
.login_finish::<K>(session_id, message.clone())
|
||||
.await
|
||||
.map_err(|e| ClientAuthError::Transport(e))?;
|
||||
|
||||
Ok(key)
|
||||
}
|
||||
}
|
||||
|
||||
// pub struct InMemSharedServer<K> {
|
||||
// inner: Arc<Mutex<OpaqueAuth<InMemoryAuthRepo, InMemoryAuthSession>>>,
|
||||
// _k: PhantomData<K>,
|
||||
// }
|
||||
//
|
||||
// impl<K> InMemSharedServer<K> {
|
||||
// pub fn new(inner: Arc<Mutex<OpaqueAuth<InMemoryAuthRepo, InMemoryAuthSession>>>) -> Self {
|
||||
// Self { inner, _k: PhantomData }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[async_trait::async_trait]
|
||||
// impl<K> ServerConnectionRegister for InMemSharedServer<K>
|
||||
// where
|
||||
// K: CredKind + Send + Sync,
|
||||
// {
|
||||
// async fn start(
|
||||
// &mut self,
|
||||
// identifier: &[u8],
|
||||
// message: &RegistrationRequest<NKodeCipherSuite>,
|
||||
// ) -> Result<RegisterSession, ClientAuthError> {
|
||||
// let mut guard = self.inner.lock().await;
|
||||
// guard
|
||||
// .reg_start::<K>(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::<K>(session_id, password_file)
|
||||
// .await
|
||||
// .map_err(ClientAuthError::Transport)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[async_trait::async_trait]
|
||||
// impl<K> ServerConnectionLogin for InMemSharedServer<K>
|
||||
// where
|
||||
// K: CredKind + Send + Sync,
|
||||
// {
|
||||
// async fn start(
|
||||
// &mut self,
|
||||
// identifier: &[u8],
|
||||
// request: &CredentialRequest<NKodeCipherSuite>,
|
||||
// ) -> Result<LoginSession, ClientAuthError> {
|
||||
// let mut guard = self.inner.lock().await;
|
||||
// guard
|
||||
// .login_start::<K>(identifier, request.clone())
|
||||
// .await
|
||||
// .map_err(ClientAuthError::Transport)
|
||||
// }
|
||||
//
|
||||
// async fn finish(
|
||||
// &mut self,
|
||||
// session_id: &Uuid,
|
||||
// message: &CredentialFinalization<NKodeCipherSuite>,
|
||||
// ) -> Result<OpaqueSessionKey, ClientAuthError> {
|
||||
// let mut guard = self.inner.lock().await;
|
||||
// let key = guard
|
||||
// .login_finish::<K>(session_id, message.clone())
|
||||
// .await
|
||||
// .map_err(ClientAuthError::Transport)?;
|
||||
// Ok(key)
|
||||
// }
|
||||
// }
|
||||
3
src/server/repository/opaque/in_memory/mod.rs
Normal file
3
src/server/repository/opaque/in_memory/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod in_memory_auth_repo;
|
||||
pub mod in_memory_transport;
|
||||
pub mod in_memory_auth_session;
|
||||
2
src/server/repository/opaque/mod.rs
Normal file
2
src/server/repository/opaque/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod in_memory;
|
||||
pub mod repos;
|
||||
36
src/server/repository/opaque/repos.rs
Normal file
36
src/server/repository/opaque/repos.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use uuid::Uuid;
|
||||
use opaque_ke::ServerLogin;
|
||||
use crate::shared::models::opaque::{NKodeCipherSuite, PasswordFile};
|
||||
use crate::server::opaque::{LoginCache, RegCache};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AuthRepoError {
|
||||
UserExists,
|
||||
KeyNotRegistered,
|
||||
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>;
|
||||
|
||||
fn has_code(&self, identifier: &[u8]) -> bool;
|
||||
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>;
|
||||
}
|
||||
|
||||
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>;
|
||||
|
||||
fn new_login_session(
|
||||
&mut 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>;
|
||||
}
|
||||
Reference in New Issue
Block a user