use std::fmt::{self, Debug};
use std::hash::{Hash, Hasher};
use std::sync::Arc;
use tor_hscrypto::pk::{HsClientDescEncSecretKey, HsClientIntroAuthKeypair, HsId};
use tor_keymgr::{ArtiPath, ArtiPathComponent, CTorPath, KeySpecifier};
#[derive(Clone, Default)]
pub struct HsClientSecretKeys {
pub(crate) keys: Arc<ClientSecretKeyValues>,
}
impl Debug for HsClientSecretKeys {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut d = f.debug_tuple("HsClientSecretKeys");
d.field(&Arc::as_ptr(&self.keys));
self.keys
.ks_hsc_desc_enc
.as_ref()
.map(|_| d.field(&"<desc_enc>"));
self.keys
.ks_hsc_intro_auth
.as_ref()
.map(|_| d.field(&"<intro_uath>"));
d.finish()
}
}
impl PartialEq for HsClientSecretKeys {
fn eq(&self, other: &Self) -> bool {
self.is_empty() && other.is_empty() || Arc::ptr_eq(&self.keys, &other.keys)
}
}
impl Eq for HsClientSecretKeys {}
impl Hash for HsClientSecretKeys {
fn hash<H: Hasher>(&self, state: &mut H) {
Arc::as_ptr(&self.keys).hash(state);
}
}
impl HsClientSecretKeys {
pub fn none() -> Self {
Self::default()
}
pub fn is_empty(&self) -> bool {
let ClientSecretKeyValues {
ks_hsc_desc_enc,
ks_hsc_intro_auth,
} = &*self.keys;
ks_hsc_desc_enc.is_none() && ks_hsc_intro_auth.is_none()
}
}
type ClientSecretKeyValues = HsClientSecretKeysBuilder;
#[derive(Default, Debug)]
pub struct HsClientSecretKeysBuilder {
pub(crate) ks_hsc_desc_enc: Option<HsClientDescEncSecretKey>,
pub(crate) ks_hsc_intro_auth: Option<HsClientIntroAuthKeypair>,
}
impl HsClientSecretKeysBuilder {
pub fn ks_hsc_desc_enc(&mut self, ks: HsClientDescEncSecretKey) -> &mut Self {
self.ks_hsc_desc_enc = Some(ks);
self
}
pub fn ks_hsc_intro_auth(&mut self, ks: HsClientIntroAuthKeypair) -> &mut Self {
self.ks_hsc_intro_auth = Some(ks);
self
}
pub fn build(self) -> Result<HsClientSecretKeys, tor_config::ConfigBuildError> {
Ok(HsClientSecretKeys {
keys: Arc::new(self),
})
}
}
#[derive(Clone, Debug, derive_more::Display, derive_more::Into, derive_more::AsRef)]
pub struct HsClientSpecifier(ArtiPathComponent);
impl HsClientSpecifier {
pub fn new(inner: String) -> Result<Self, tor_keymgr::Error> {
ArtiPathComponent::new(inner).map(Self)
}
}
pub struct HsClientSecretKeySpecifier {
client_id: HsClientSpecifier,
hs_id: HsId,
role: HsClientKeyRole,
}
#[derive(Debug, Clone, Copy, PartialEq, derive_more::Display)]
#[non_exhaustive]
pub enum HsClientKeyRole {
#[display(fmt = "KP_hsc_desc_enc")]
DescEnc,
#[display(fmt = "KP_hsc_intro_auth")]
IntroAuth,
}
impl HsClientSecretKeySpecifier {
pub fn new(client_id: HsClientSpecifier, hs_id: HsId, role: HsClientKeyRole) -> Self {
Self {
client_id,
hs_id,
role,
}
}
}
impl KeySpecifier for HsClientSecretKeySpecifier {
fn arti_path(&self) -> tor_keymgr::Result<ArtiPath> {
ArtiPath::new(format!(
"client/{}/{}/{}",
self.client_id, self.hs_id, self.role
))
}
fn ctor_path(&self) -> Option<CTorPath> {
todo!()
}
}