use std::collections::HashMap;
use crate::{
crypto::{aead::AeadDecrypt, key_derivation::KeyDerivation},
header::KeyId,
};
use super::generic::GenericDecryptionKey;
pub trait KeyLookup<A, D>
where
A: AeadDecrypt<Secret = D::Secret>,
D: KeyDerivation,
{
fn get_key<K>(&self, key_id: K) -> Option<&GenericDecryptionKey<A, D>>
where
K: Into<KeyId>;
}
pub trait KeyStore<A, D>
where
A: AeadDecrypt<Secret = D::Secret>,
D: KeyDerivation,
{
type Key: AsRef<GenericDecryptionKey<A, D>>;
type Error: std::error::Error + Send + Sync + 'static;
#[must_use = "a key must be recorded once the frame decrypts, or dropped"]
fn lookup(&self, key_id: KeyId) -> Result<Self::Key, Self::Error>;
fn record(&mut self, key: Self::Key);
}
#[derive(Debug, Clone, Copy, thiserror::Error)]
#[error("the key store holds no key for it")]
pub struct KeyNotFound;
impl<'store, A, D, S> KeyStore<A, D> for &'store S
where
A: AeadDecrypt<Secret = D::Secret> + 'store,
D: KeyDerivation + 'store,
S: KeyLookup<A, D>,
{
type Key = &'store GenericDecryptionKey<A, D>;
type Error = KeyNotFound;
fn lookup(&self, key_id: KeyId) -> Result<Self::Key, Self::Error> {
(*self).get_key(key_id).ok_or(KeyNotFound)
}
fn record(&mut self, _key: Self::Key) {}
}
impl<A, D> KeyLookup<A, D> for GenericDecryptionKey<A, D>
where
A: AeadDecrypt<Secret = D::Secret>,
D: KeyDerivation,
{
fn get_key<K>(&self, key_id: K) -> Option<&GenericDecryptionKey<A, D>>
where
K: Into<KeyId>,
{
let key_id = key_id.into();
if self.key_id() == key_id {
Some(self)
} else {
None
}
}
}
impl<A, D> KeyLookup<A, D> for HashMap<KeyId, GenericDecryptionKey<A, D>>
where
A: AeadDecrypt<Secret = D::Secret>,
D: KeyDerivation,
{
fn get_key<K>(&self, key_id: K) -> Option<&GenericDecryptionKey<A, D>>
where
K: Into<KeyId>,
{
let key_id = key_id.into();
self.get(&key_id)
}
}