use super::{accumulator::Accumulator, composable_plaintext::ComposablePlaintext, ComposableIndex};
use crate::encryption::{unique_indexer::UniqueIndexer, EncryptionError, Plaintext};
use hmac::Mac;
use zerokms_protocol::cipherstash_config::column::TokenFilter;
#[derive(Debug)]
pub struct ExactIndex {
token_filters: Vec<TokenFilter>,
}
impl ExactIndex {
pub fn new(token_filters: Vec<TokenFilter>) -> Self {
Self { token_filters }
}
}
impl ComposableIndex for ExactIndex {
fn compose_index(
&self,
key: [u8; 32],
plaintext: ComposablePlaintext,
accumulator: Accumulator,
) -> Result<Accumulator, EncryptionError> {
let indexer = UniqueIndexer::new(key, self.token_filters.clone());
let plaintext: Plaintext = plaintext.try_into()?;
match accumulator {
Accumulator::Term(term) => {
let mut mac = indexer.create_hmac()?;
indexer.encrypt_into_hmac(&mut mac, &plaintext)?;
mac.update(term.as_ref());
Ok(Accumulator::Term(mac.finalize().into_bytes().to_vec()))
}
Accumulator::Terms(terms) => terms
.into_iter()
.map(|term| {
let mut mac = indexer.create_hmac()?;
indexer.encrypt_into_hmac(&mut mac, &plaintext)?;
mac.update(term.as_ref());
Ok(mac.finalize().into_bytes().to_vec())
})
.collect::<Result<Vec<_>, EncryptionError>>()
.map(Accumulator::Terms),
}
}
}