Individiual methods for keystores
Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
		@@ -3,12 +3,18 @@
 | 
			
		||||
pub enum Error {
 | 
			
		||||
    /// An error during cryptographic operations
 | 
			
		||||
    Crypto(CryptoError),
 | 
			
		||||
    /// An error while performing an I/O operation
 | 
			
		||||
    IOError(std::io::Error),
 | 
			
		||||
    /// A corrupt keyspace is returned if a keyspace can't be decrypted
 | 
			
		||||
    CorruptKeyspace,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl core::fmt::Display for Error {
 | 
			
		||||
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
 | 
			
		||||
        match self {
 | 
			
		||||
            Error::Crypto(e) => f.write_fmt(format_args!("crypto: {e}")),
 | 
			
		||||
            Error::IOError(e) => f.write_fmt(format_args!("io: {e}")),
 | 
			
		||||
            Error::CorruptKeyspace => f.write_str("corrupt keyspace"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -56,3 +62,9 @@ impl From<CryptoError> for Error {
 | 
			
		||||
        Self::Crypto(value)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<std::io::Error> for Error {
 | 
			
		||||
    fn from(value: std::io::Error) -> Self {
 | 
			
		||||
        Self::IOError(value)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,17 +5,17 @@ mod wasm;
 | 
			
		||||
mod fallback;
 | 
			
		||||
 | 
			
		||||
#[cfg(target_arch = "wasm32")]
 | 
			
		||||
use wasm::KeySpace as KS;
 | 
			
		||||
use wasm::KeySpace as Ks;
 | 
			
		||||
 | 
			
		||||
#[cfg(not(target_arch = "wasm32"))]
 | 
			
		||||
use fallback::KeySpace as KS;
 | 
			
		||||
use fallback::KeySpace as Ks;
 | 
			
		||||
 | 
			
		||||
use crate::{error::Error, key::Key};
 | 
			
		||||
 | 
			
		||||
/// 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,
 | 
			
		||||
    store: Ks,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Wasm32 constructor
 | 
			
		||||
 
 | 
			
		||||
@@ -1,2 +1,72 @@
 | 
			
		||||
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 mod KeySpace {}
 | 
			
		||||
pub struct KeySpace {
 | 
			
		||||
    /// Path to file on disk
 | 
			
		||||
    path: PathBuf,
 | 
			
		||||
    /// Decrypted keys held in the store
 | 
			
		||||
    keystore: HashMap<String, Key>,
 | 
			
		||||
    /// 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<Self, Error> {
 | 
			
		||||
        /// 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<Option<Key>, 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<impl Iterator<Item = (String, Key)>, Error> {
 | 
			
		||||
        todo!()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,2 +1,26 @@
 | 
			
		||||
use crate::{error::Error, key::Key};
 | 
			
		||||
 | 
			
		||||
/// KeySpace represents an IndexDB keyspace
 | 
			
		||||
pub struct KeySpace {}
 | 
			
		||||
 | 
			
		||||
impl KeySpace {
 | 
			
		||||
    /// Get a [`Key`] previously stored under the provided name.
 | 
			
		||||
    async fn get(&self, key: &str) -> Result<Option<Key>, 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<impl Iterator<Item = (String, Key)>, Error> {
 | 
			
		||||
        todo!()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user