132 lines
3.9 KiB
Rust
132 lines
3.9 KiB
Rust
// #[cfg(not(target_arch = "wasm32"))]
|
|
// mod fallback;
|
|
// #[cfg(target_arch = "wasm32")]
|
|
// mod wasm;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
use std::path::Path;
|
|
|
|
use crate::{
|
|
error::Error,
|
|
key::{Key, symmetric::SymmetricKey},
|
|
};
|
|
|
|
use kv::KVStore;
|
|
|
|
/// Configuration to use for bincode en/decoding.
|
|
const BINCODE_CONFIG: bincode::config::Configuration = bincode::config::standard();
|
|
|
|
// #[cfg(not(target_arch = "wasm32"))]
|
|
// use fallback::KeySpace as Ks;
|
|
// #[cfg(target_arch = "wasm32")]
|
|
// use wasm::KeySpace as Ks;
|
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
use kv::native::NativeStore;
|
|
#[cfg(target_arch = "wasm32")]
|
|
use kv::wasm::WasmStore;
|
|
|
|
const KEYSPACE_NAME: &str = "vault_keyspace";
|
|
|
|
/// A keyspace represents a group of stored cryptographic keys. The storage is encrypted, a
|
|
/// password must be provided when opening the KeySpace to decrypt the keys.
|
|
pub struct KeySpace {
|
|
// store: Ks,
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
store: NativeStore,
|
|
#[cfg(target_arch = "wasm32")]
|
|
store: WasmStore,
|
|
/// A collection of all keys stored in the KeySpace, in decrypted form.
|
|
keys: HashMap<String, Key>,
|
|
/// The encryption key used to encrypt/decrypt this keyspace.
|
|
encryption_key: SymmetricKey,
|
|
}
|
|
|
|
/// Wasm32 constructor
|
|
#[cfg(target_arch = "wasm32")]
|
|
impl KeySpace {}
|
|
|
|
/// Non-wasm constructor
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
impl KeySpace {
|
|
/// Open the keyspace at the provided path using the given key for encryption.
|
|
pub async fn open(path: &Path, encryption_key: SymmetricKey) -> Result<Self, Error> {
|
|
let store = NativeStore::open(&path.display().to_string())?;
|
|
let mut ks = Self {
|
|
store,
|
|
keys: HashMap::new(),
|
|
encryption_key,
|
|
};
|
|
ks.load_keyspace().await?;
|
|
Ok(ks)
|
|
}
|
|
}
|
|
|
|
#[cfg(target_arch = "wasm32")]
|
|
impl KeySpace {
|
|
pub async fn open(name: &str, encryption_key: SymmetricKey) -> Result<Self, Error> {
|
|
let store = WasmStore::open(name).await?;
|
|
let mut ks = Self {
|
|
store,
|
|
keys: HashMap::new(),
|
|
encryption_key,
|
|
};
|
|
ks.load_keyspace().await?;
|
|
Ok(ks)
|
|
}
|
|
}
|
|
|
|
/// Exposed methods, platform independant
|
|
impl KeySpace {
|
|
/// Get a [`Key`] previously stored under the provided name.
|
|
pub async fn get(&self, key: &str) -> Result<Option<Key>, Error> {
|
|
Ok(self.keys.get(key).cloned())
|
|
}
|
|
|
|
/// Store a [`Key`] under the provided name.
|
|
///
|
|
/// This overwrites the existing key if one is already stored with the same name.
|
|
pub async fn set(&mut self, key: String, value: Key) -> Result<(), Error> {
|
|
self.keys.insert(key, value);
|
|
self.save_keyspace().await
|
|
}
|
|
|
|
/// Delete the [`Key`] stored under the provided name.
|
|
pub async fn delete(&mut self, key: &str) -> Result<(), Error> {
|
|
self.keys.remove(key);
|
|
self.save_keyspace().await
|
|
}
|
|
|
|
/// Iterate over all stored [`keys`](Key) in the KeySpace
|
|
pub async fn iter(&self) -> Result<impl Iterator<Item = (&String, &Key)>, Error> {
|
|
Ok(self.keys.iter())
|
|
}
|
|
|
|
/// Encrypt all keys and save them to the underlying store
|
|
async fn save_keyspace(&self) -> Result<(), Error> {
|
|
let encoded_keys = bincode::serde::encode_to_vec(&self.keys, BINCODE_CONFIG)?;
|
|
let value = self.encryption_key.encrypt(&encoded_keys)?;
|
|
// Put in store
|
|
Ok(self.store.set(KEYSPACE_NAME, &value).await?)
|
|
}
|
|
|
|
/// Loads the encrypted keyspace from the underlying storage
|
|
async fn load_keyspace(&mut self) -> Result<(), Error> {
|
|
let Some(ks) = self.store.get(KEYSPACE_NAME).await? else {
|
|
// Keyspace doesn't exist yet, nothing to do here
|
|
return Ok(());
|
|
};
|
|
|
|
let raw = self.encryption_key.decrypt(&ks)?;
|
|
|
|
let (decoded_keys, _): (HashMap<String, Key>, _) =
|
|
bincode::serde::decode_from_slice(&raw, BINCODE_CONFIG)?;
|
|
|
|
self.keys = decoded_keys;
|
|
|
|
Ok(())
|
|
}
|
|
}
|