use std::{collections::HashMap, io::Write, path::PathBuf}; use crate::{ error::Error, key::{Key, symmetric::SymmetricKey}, }; /// Magic value used as header in decrypted keyspace files. const KEYSPACE_MAGIC: [u8; 14] = [ 118, 97, 117, 108, 116, 95, 107, 101, 121, 115, 112, 97, 99, 101, ]; //"vault_keyspace" /// A KeySpace using the filesystem as storage pub struct KeySpace { /// Path to file on disk path: PathBuf, /// Decrypted keys held in the store keystore: HashMap, /// The encryption key used to encrypt/decrypt the storage. encryption_key: SymmetricKey, } impl KeySpace { /// Opens the `KeySpace`. If it does not exist, it will be created. The provided encryption key /// will be used for Encrypting and Decrypting the content of the KeySpace. async fn open(path: PathBuf, encryption_key: SymmetricKey) -> Result { /// If the path does not exist, create it first and write the encrypted magic header if !path.exists() { // Since we checked path does not exist, the only errors here can be actual IO errors // (unless something else creates the same file at the same time). let mut file = std::fs::File::create_new(path)?; let content = encryption_key.encrypt(&KEYSPACE_MAGIC)?; file.write_all(&content)?; } // Load file, try to decrypt, verify magic header, deserialize keystore let mut file = std::fs::File::open(path)?; let mut buffer = Vec::new(); file.read_to_end(&mut buffer)?; if buffer.len() < KEYSPACE_MAGIC.len() { return Err(Error::CorruptKeyspace); } if buffer[..KEYSPACE_MAGIC.len()] != KEYSPACE_MAGIC { return Err(Error::CorruptKeyspace); } // TODO: Actual deserialization todo!(); } /// Get a [`Key`] previously stored under the provided name. async fn get(&self, key: &str) -> Result, Error> { todo!(); } /// Store a [`Key`] under the provided name. async fn set(&self, key: &str, value: Key) -> Result<(), Error> { todo!(); } /// Delete the [`Key`] stored under the provided name. async fn delete(&self, key: &str) -> Result<(), Error> { todo!(); } /// Iterate over all stored [`keys`](Key) in the KeySpace async fn iter(&self) -> Result, Error> { todo!() } }