use crate::{DntContext, DntKeyError, DntResult, KeyId};
use std::collections::HashMap;
use std::fmt;
use zeroize::Zeroize;
#[derive(Clone, PartialEq, Eq)]
pub struct SecretKey([u8; 32]);
impl SecretKey {
pub fn new(bytes: [u8; 32]) -> Self {
Self(bytes)
}
pub fn from_slice(bytes: &[u8]) -> Result<Self, DntKeyError> {
if bytes.len() != 32 {
return Err(DntKeyError::InvalidKey);
}
let mut key = [0u8; 32];
key.copy_from_slice(bytes);
Ok(Self(key))
}
pub fn expose_key(&self) -> &[u8; 32] {
&self.0
}
}
impl fmt::Debug for SecretKey {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("SecretKey(REDACTED)")
}
}
impl Drop for SecretKey {
fn drop(&mut self) {
self.0.zeroize();
}
}
pub trait DntKeyProvider: Send + Sync {
fn resolve_key(&self, key_id: &KeyId, context: &DntContext) -> Result<SecretKey, DntKeyError>;
}
#[derive(Clone, Default)]
pub struct StaticDntKeyProvider {
keys: HashMap<KeyId, SecretKey>,
}
impl fmt::Debug for StaticDntKeyProvider {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("StaticDntKeyProvider")
.field("keys", &self.keys.len())
.finish()
}
}
impl StaticDntKeyProvider {
pub fn new() -> Self {
Self::default()
}
pub fn with_key(mut self, key_id: KeyId, key: SecretKey) -> Self {
self.keys.insert(key_id, key);
self
}
pub fn insert(&mut self, key_id: KeyId, key: SecretKey) -> DntResult<()> {
self.keys.insert(key_id, key);
Ok(())
}
}
impl DntKeyProvider for StaticDntKeyProvider {
fn resolve_key(&self, key_id: &KeyId, _context: &DntContext) -> Result<SecretKey, DntKeyError> {
self.keys.get(key_id).cloned().ok_or(DntKeyError::NotFound)
}
}