use crate::backends::SledBackend;
use crate::crypto::{decrypt_value, encrypt_value};
use crate::error::{EnigmaStorageError, Result};
use crate::key_provider::{KeyProvider, MasterKey};
pub struct EncryptedStore {
backend: SledBackend,
key: MasterKey,
namespace: String,
}
impl EncryptedStore {
pub fn open(path: &str, namespace: &str, provider: &dyn KeyProvider) -> Result<EncryptedStore> {
let backend = SledBackend::open(path)?;
let key = provider.get_or_create_master_key()?;
Ok(EncryptedStore {
backend,
key,
namespace: namespace.to_owned(),
})
}
pub fn put(&self, key: &str, value: &[u8]) -> Result<()> {
Self::validate_key(key)?;
let ciphertext = encrypt_value(&self.key, &self.namespace, key, value)?;
self.backend.insert(key, &ciphertext)
}
pub fn get(&self, key: &str) -> Result<Option<Vec<u8>>> {
Self::validate_key(key)?;
let stored = self.backend.get(key)?;
match stored {
Some(data) => {
let value = decrypt_value(&self.key, &self.namespace, key, &data)?;
Ok(Some(value))
}
None => Ok(None),
}
}
pub fn delete(&self, key: &str) -> Result<bool> {
Self::validate_key(key)?;
self.backend.remove(key)
}
pub fn flush(&self) -> Result<()> {
self.backend.flush()
}
fn validate_key(key: &str) -> Result<()> {
if key.is_empty() || key.len() > 256 || key.chars().any(|c| c.is_control()) {
return Err(EnigmaStorageError::InvalidKey);
}
Ok(())
}
}