pub struct EncryptedStorage { /* private fields */ }Expand description
Transparent encryption wrapper around any StorageBackend.
All data written through this wrapper is encrypted before reaching the inner storage, and decrypted when read back. The encryption is completely transparent to the rest of the database engine.
Implementations§
Source§impl EncryptedStorage
impl EncryptedStorage
Sourcepub fn new(inner: Arc<dyn StorageBackend>, master_key: &[u8; 32]) -> Self
pub fn new(inner: Arc<dyn StorageBackend>, master_key: &[u8; 32]) -> Self
Create a new EncryptedStorage wrapping inner with the given 32-byte key.
Call derive_key() first to turn a human-readable password into a key.
The key must be exactly 32 bytes (256 bits) — the size XChaCha20 requires.
Sourcepub fn derive_key(password: &str, salt_context: &str) -> [u8; 32]
pub fn derive_key(password: &str, salt_context: &str) -> [u8; 32]
Derive a deterministic 32-byte encryption key from a password string using the Argon2id algorithm.
salt_context is typically the database file path — this ensures that
the same password produces different keys for different database files,
preventing cross-database attacks.
Argon2id is intentionally slow (memory-hard) to make brute-force attacks expensive. The default parameters require ~64 MB of RAM and ~0.5 s of CPU.
Trait Implementations§
Source§impl StorageBackend for EncryptedStorage
Implement the StorageBackend trait so EncryptedStorage can be used anywhere
a StorageBackend is expected — the rest of the engine doesn’t know or care
that encryption is happening.
impl StorageBackend for EncryptedStorage
Implement the StorageBackend trait so EncryptedStorage can be used anywhere a StorageBackend is expected — the rest of the engine doesn’t know or care that encryption is happening.
Source§fn write_entry(&self, entry: &LogEntry) -> Result<(), DbError>
fn write_entry(&self, entry: &LogEntry) -> Result<(), DbError>
Encrypt entry and write the resulting ENC entry to the inner backend.
Source§fn read_log(&self) -> Result<Vec<LogEntry>, DbError>
fn read_log(&self) -> Result<Vec<LogEntry>, DbError>
Read all ENC entries from the inner backend and decrypt them.
Entries that fail to decrypt are skipped with a warning (not a crash) so a single corrupt entry doesn’t bring down the whole database. Unencrypted entries (cmd != “ENC”) are passed through unchanged — this supports migrating an existing plaintext database to encrypted.
Source§fn compact(&self, entries: Vec<LogEntry>) -> Result<(), DbError>
fn compact(&self, entries: Vec<LogEntry>) -> Result<(), DbError>
Re-encrypt all entries during compaction so the compacted file is fully encrypted with no plaintext remnants from a migration.
Each entry gets a fresh random nonce — even if the plaintext is the same as before, the ciphertext will be different (this is correct and expected).
Source§fn read_at(&self, offset: u64, length: u32) -> Result<Vec<u8>, DbError>
fn read_at(&self, offset: u64, length: u32) -> Result<Vec<u8>, DbError>
Read exactly length bytes from the inner backend and decrypt the entry.
Note: in the encrypted Bitcask model, the pointer refers to the offset and length of the ENCRYPTED entry in the log.