cipherstash-client 0.12.5

The official CipherStash SDK
Documentation
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),
        }
    }
}