pub struct KeyStore<Ids: KeyIds> {
inner: Arc<RwLock<KeyStoreInner<Ids>>>,
}
Expand description
An in-memory key store that provides a safe and secure way to store keys and use them for encryption/decryption operations. The store API is designed to work only on key identifiers (KeyId). These identifiers are user-defined types that contain no key material, which means the API users don’t have to worry about accidentally leaking keys.
Each store is designed to be used by a single user and should not be shared between users, but the store itself is thread safe and can be cloned to share between threads.
// We need to define our own key identifier types. We provide a macro to make this easier.
key_ids! {
#[symmetric]
pub enum SymmKeyId {
User,
#[local]
Local(&'static str)
}
#[asymmetric]
pub enum AsymmKeyId {
UserPrivate,
}
pub Ids => SymmKeyId, AsymmKeyId;
}
// Initialize the store and insert a test key
let store: KeyStore<Ids> = KeyStore::default();
#[allow(deprecated)]
store.context_mut().set_symmetric_key(SymmKeyId::User, SymmetricCryptoKey::generate(rand::thread_rng()));
// Define some data that needs to be encrypted
struct Data(String);
impl IdentifyKey<SymmKeyId> for Data {
fn key_identifier(&self) -> SymmKeyId {
SymmKeyId::User
}
}
impl Encryptable<Ids, SymmKeyId, EncString> for Data {
fn encrypt(&self, ctx: &mut KeyStoreContext<Ids>, key: SymmKeyId) -> Result<EncString, CryptoError> {
self.0.encrypt(ctx, key)
}
}
// Encrypt the data
let decrypted = Data("Hello, World!".to_string());
let encrypted = store.encrypt(decrypted).unwrap();
Fields§
§inner: Arc<RwLock<KeyStoreInner<Ids>>>
Implementations§
Source§impl<Ids: KeyIds> KeyStore<Ids>
impl<Ids: KeyIds> KeyStore<Ids>
Sourcepub fn clear(&self)
pub fn clear(&self)
Clear all keys from the store. This can be used to clear all keys from memory in case of lock/logout, and is equivalent to destroying the store and creating a new one.
Sourcepub fn context(&self) -> KeyStoreContext<'_, Ids>
pub fn context(&self) -> KeyStoreContext<'_, Ids>
Initiate an encryption/decryption context. This context will have read only access to the global keys, and will have its own local key stores with read/write access. This context-local store will be cleared up when the context is dropped.
Some possible use cases for this API and alternative recommendations are:
- Decrypting one or more crate::EncStrings directly. This was the pattern before the introduction of the Encryptable and Decryptable traits, but is now considered obsolete. We recommend wrapping the values in a struct that implements these traits instead, and then using KeyStore::encrypt, KeyStore::decrypt, KeyStore::encrypt_list and KeyStore::decrypt_list.
- Decrypting or encrypting multiple Decryptable or Encryptable items while sharing any local keys. This is not recommended as it can lead to fragile and flaky decryption/encryption operations. We recommend any local keys to be used only in the context of a single Encryptable or Decryptable implementation. In the future we might enforce this.
- Obtaining the key material directly. We strongly recommend against doing this as it can lead to key material being leaked, but we need to support it for backwards compatibility. If you want to access the key material to encrypt it or derive a new key from it, we provide functions for that:
- Some other minor and safe operations, like checking if a key exists. This is not exposed in the KeyStore directly as we haven’t seen many use cases for it, but we can add it if needed.
One of the pitfalls of the current implementations is that keys stored in the context-local store only get cleared automatically when the context is dropped, and not between operations. This means that if you are using the same context for multiple operations, you may want to clear it manually between them.
Sourcepub fn context_mut(&self) -> KeyStoreContext<'_, Ids>
pub fn context_mut(&self) -> KeyStoreContext<'_, Ids>
The same pitfalls as Self::context apply here, but with the added risk of accidentally modifying the global keys and leaving the store in an inconsistent state. If you still need to use it, make sure you read this documentation to understand how to use it safely.
Initiate an encryption/decryption context. This context will have MUTABLE access to the global keys, and will have its own local key stores with read/write access. This context-local store will be cleared up when the context is dropped.
The only supported use case for this API is initializing the store with the user’s symetric
and private keys, and setting the organization keys. This method will be marked as
pub(crate)
in the future, once we have a safe API for key initialization and updating.
Sourcepub fn decrypt<Key: KeyId, Data: Decryptable<Ids, Key, Output> + IdentifyKey<Key>, Output>(
&self,
data: &Data,
) -> Result<Output, CryptoError>
pub fn decrypt<Key: KeyId, Data: Decryptable<Ids, Key, Output> + IdentifyKey<Key>, Output>( &self, data: &Data, ) -> Result<Output, CryptoError>
Decript a single item using this key store. The key returned by data.key_identifier()
must
already be present in the store, otherwise this will return an error.
This method is not parallelized, and is meant for single item decryption.
If you need to decrypt multiple items, use decrypt_list
instead.
Sourcepub fn encrypt<Key: KeyId, Data: Encryptable<Ids, Key, Output> + IdentifyKey<Key>, Output>(
&self,
data: Data,
) -> Result<Output, CryptoError>
pub fn encrypt<Key: KeyId, Data: Encryptable<Ids, Key, Output> + IdentifyKey<Key>, Output>( &self, data: Data, ) -> Result<Output, CryptoError>
Encrypt a single item using this key store. The key returned by data.key_identifier()
must
already be present in the store, otherwise this will return an error.
This method is not parallelized, and is meant for single item encryption.
If you need to encrypt multiple items, use encrypt_list
instead.
Sourcepub fn decrypt_list<Key: KeyId, Data: Decryptable<Ids, Key, Output> + IdentifyKey<Key> + Send + Sync, Output: Send + Sync>(
&self,
data: &[Data],
) -> Result<Vec<Output>, CryptoError>
pub fn decrypt_list<Key: KeyId, Data: Decryptable<Ids, Key, Output> + IdentifyKey<Key> + Send + Sync, Output: Send + Sync>( &self, data: &[Data], ) -> Result<Vec<Output>, CryptoError>
Decrypt a list of items using this key store. The keys returned by
data[i].key_identifier()
must already be present in the store, otherwise this will
return an error. This method will try to parallelize the decryption of the items, for
better performance on large lists.
Sourcepub fn encrypt_list<Key: KeyId, Data: Encryptable<Ids, Key, Output> + IdentifyKey<Key> + Send + Sync, Output: Send + Sync>(
&self,
data: &[Data],
) -> Result<Vec<Output>, CryptoError>
pub fn encrypt_list<Key: KeyId, Data: Encryptable<Ids, Key, Output> + IdentifyKey<Key> + Send + Sync, Output: Send + Sync>( &self, data: &[Data], ) -> Result<Vec<Output>, CryptoError>
Encrypt a list of items using this key store. The keys returned by
data[i].key_identifier()
must already be present in the store, otherwise this will
return an error. This method will try to parallelize the encryption of the items, for
better performance on large lists. This method is not parallelized, and is meant for
single item encryption.
Trait Implementations§
Auto Trait Implementations§
impl<Ids> Freeze for KeyStore<Ids>
impl<Ids> RefUnwindSafe for KeyStore<Ids>
impl<Ids> Send for KeyStore<Ids>
impl<Ids> Sync for KeyStore<Ids>
impl<Ids> Unpin for KeyStore<Ids>
impl<Ids> UnwindSafe for KeyStore<Ids>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> CompatExt for T
impl<T> CompatExt for T
§impl<T, UT> HandleAlloc<UT> for T
impl<T, UT> HandleAlloc<UT> for T
§fn new_handle(value: Arc<T>) -> Handle
fn new_handle(value: Arc<T>) -> Handle
§unsafe fn clone_handle(handle: Handle) -> Handle
unsafe fn clone_handle(handle: Handle) -> Handle
§unsafe fn consume_handle(handle: Handle) -> Arc<T>
unsafe fn consume_handle(handle: Handle) -> Arc<T>
Arc<>
Read moreSource§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more