use std::sync::Arc;
use oxistore_core::{KvSnapshot, KvStore, KvTxn, RangeIter, StoreError};
use crate::aead::{
decrypt_with_aead, derive_cell_id, encrypt_with_aead, AeadKind, XChaCha20Poly1305Aead,
};
use crate::cell::{decrypt_cell, encrypt_cell, CellId};
use crate::error::EncryptError;
use crate::keys::KeyProvider;
use crate::snapshot::EncryptedSnapshot;
use crate::txn::EncryptedTxn;
pub struct EncryptedKv<T: KvStore, K: KeyProvider, A: crate::aead::Aead = XChaCha20Poly1305Aead> {
inner: Arc<T>,
key_provider: Arc<K>,
aead: A,
}
impl<T: KvStore, K: KeyProvider, A: crate::aead::Aead> std::fmt::Debug for EncryptedKv<T, K, A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EncryptedKv")
.field("inner_type", &std::any::type_name::<T>())
.field("key_material", &"[REDACTED]")
.field("aead_type", &std::any::type_name::<A>())
.finish()
}
}
impl<T: KvStore, K: KeyProvider> EncryptedKv<T, K, XChaCha20Poly1305Aead> {
pub fn new(inner: T, key_provider: K) -> Self {
Self {
inner: Arc::new(inner),
key_provider: Arc::new(key_provider),
aead: XChaCha20Poly1305Aead,
}
}
}
impl<T: KvStore, K: KeyProvider, A: crate::aead::Aead> EncryptedKv<T, K, A> {
pub fn with_aead(inner: T, key_provider: K, aead: A) -> Self {
Self {
inner: Arc::new(inner),
key_provider: Arc::new(key_provider),
aead,
}
}
fn encrypt_value(&self, aad: &[u8], plaintext: &[u8]) -> Result<Vec<u8>, EncryptError> {
let key = self.key_provider.key32()?;
encrypt_with_aead(&self.aead, key, aad, plaintext)
}
fn decrypt_value(&self, aad: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, EncryptError> {
let key = self.key_provider.key32()?;
decrypt_with_aead(&self.aead, key, aad, ciphertext)
}
pub fn put_cell(&self, key: &[u8], cell_id: CellId, value: &[u8]) -> Result<(), EncryptError> {
let ct = encrypt_cell(self.key_provider.as_ref(), cell_id, value)?;
self.inner.put(key, &ct).map_err(EncryptError::from)
}
pub fn get_cell(&self, key: &[u8], cell_id: CellId) -> Result<Option<Vec<u8>>, EncryptError> {
match self.inner.get(key).map_err(EncryptError::from)? {
None => Ok(None),
Some(ct) => {
let pt = decrypt_cell(self.key_provider.as_ref(), cell_id, &ct)?;
Ok(Some(pt))
}
}
}
pub fn inner_ref(&self) -> &T {
&self.inner
}
}
impl<T: KvStore, K: KeyProvider, A: crate::aead::Aead> KvStore for EncryptedKv<T, K, A> {
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, StoreError> {
let aad = derive_cell_id(key);
match self.inner.get(key)? {
None => Ok(None),
Some(ct) => {
let pt = self.decrypt_value(&aad, &ct).map_err(StoreError::from)?;
Ok(Some(pt))
}
}
}
fn put(&self, key: &[u8], value: &[u8]) -> Result<(), StoreError> {
let aad = derive_cell_id(key);
let ct = self.encrypt_value(&aad, value).map_err(StoreError::from)?;
self.inner.put(key, &ct)
}
fn delete(&self, key: &[u8]) -> Result<(), StoreError> {
self.inner.delete(key)
}
fn contains(&self, key: &[u8]) -> Result<bool, StoreError> {
self.inner.contains(key)
}
fn range<'a>(&'a self, lo: &[u8], hi: &[u8]) -> Result<RangeIter<'a>, StoreError> {
let key_bytes = *self.key_provider.key32().map_err(StoreError::from)?;
let raw_items: Vec<_> = self.inner.range(lo, hi)?.collect::<Vec<_>>();
let mut decrypted = Vec::with_capacity(raw_items.len());
for item in raw_items {
let (k, ct) = item?;
let aad = derive_cell_id(&k);
let pt =
decrypt_with_aead(&self.aead, &key_bytes, &aad, &ct).map_err(StoreError::from)?;
decrypted.push(Ok((k, pt)));
}
Ok(Box::new(decrypted.into_iter()))
}
fn transaction(&self) -> Result<Box<dyn KvTxn + '_>, StoreError> {
let inner_txn = self.inner.transaction()?;
let key = *self.key_provider.key32().map_err(StoreError::from)?;
let kind = if self.aead.nonce_len() == 12 {
AeadKind::AesGcmSiv256
} else {
AeadKind::XChaCha20Poly1305
};
Ok(Box::new(EncryptedTxn::new(inner_txn, key, kind)))
}
fn snapshot(&self) -> Result<Box<dyn KvSnapshot + '_>, StoreError> {
let inner_snap = self.inner.snapshot()?;
let key = *self.key_provider.key32().map_err(StoreError::from)?;
let kind = if self.aead.nonce_len() == 12 {
AeadKind::AesGcmSiv256
} else {
AeadKind::XChaCha20Poly1305
};
Ok(Box::new(EncryptedSnapshot::new(inner_snap, key, kind)))
}
fn iter<'a>(&'a self) -> Result<RangeIter<'a>, StoreError> {
let key_bytes = *self.key_provider.key32().map_err(StoreError::from)?;
let raw_items: Vec<_> = self.inner.iter()?.collect::<Vec<_>>();
let mut decrypted = Vec::with_capacity(raw_items.len());
for item in raw_items {
let (k, ct) = item?;
let aad = derive_cell_id(&k);
let pt =
decrypt_with_aead(&self.aead, &key_bytes, &aad, &ct).map_err(StoreError::from)?;
decrypted.push(Ok((k, pt)));
}
Ok(Box::new(decrypted.into_iter()))
}
fn flush(&self) -> Result<(), StoreError> {
self.inner.flush()
}
}