mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
This moves both the Keyring and the fingerprints to the DcKey trait, unfortunately I was not able to disentangle these two changes. The Keyring now ensures only the right kind of key is added to it. The keyring now uses the DcKey::load_self method rather than re-implement the SQL to load keys from the database. This vastly simpliefies the use and fixes an error where a failed key load or unconfigured would result in the message being treated as plain text and benefits from the in-line key generation path. For the fingerprint a new type representing it is introduced. The aim is to replace more fingerpring uses with this type as now there are various string representations being passed around and converted between. The Display trait is used for the space-separated and multiline format, which is perhaps not the most obvious but seems right together with FromStr etc.
93 lines
2.4 KiB
Rust
93 lines
2.4 KiB
Rust
//! Keyring to perform rpgp operations with.
|
|
|
|
use anyhow::Result;
|
|
|
|
use crate::context::Context;
|
|
use crate::key::{self, DcKey};
|
|
|
|
/// An in-memory keyring.
|
|
///
|
|
/// Instances are usually constructed just for the rpgp operation and
|
|
/// short-lived.
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct Keyring<T>
|
|
where
|
|
T: DcKey,
|
|
{
|
|
keys: Vec<T>,
|
|
}
|
|
|
|
impl<T> Keyring<T>
|
|
where
|
|
T: DcKey<KeyType = T>,
|
|
{
|
|
/// New empty keyring.
|
|
pub fn new() -> Keyring<T> {
|
|
Keyring { keys: Vec::new() }
|
|
}
|
|
|
|
/// Create a new keyring with the the user's secret key loaded.
|
|
pub async fn new_self(context: &Context) -> Result<Keyring<T>, key::Error> {
|
|
let mut keyring: Keyring<T> = Keyring::new();
|
|
keyring.load_self(context).await?;
|
|
Ok(keyring)
|
|
}
|
|
|
|
/// Load the user's key into the keyring.
|
|
pub async fn load_self(&mut self, context: &Context) -> Result<(), key::Error> {
|
|
self.add(T::load_self(context).await?);
|
|
Ok(())
|
|
}
|
|
|
|
/// Add a key to the keyring.
|
|
pub fn add(&mut self, key: T) {
|
|
self.keys.push(key);
|
|
}
|
|
|
|
pub fn len(&self) -> usize {
|
|
self.keys.len()
|
|
}
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
self.keys.is_empty()
|
|
}
|
|
|
|
/// A vector with reference to all the keys in the keyring.
|
|
pub fn keys(&self) -> &[T] {
|
|
&self.keys
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::key::{SignedPublicKey, SignedSecretKey};
|
|
use crate::test_utils::*;
|
|
|
|
#[test]
|
|
fn test_keyring_add_keys() {
|
|
let alice = alice_keypair();
|
|
let mut pub_ring: Keyring<SignedPublicKey> = Keyring::new();
|
|
pub_ring.add(alice.public.clone());
|
|
assert_eq!(pub_ring.keys(), [alice.public]);
|
|
|
|
let mut sec_ring: Keyring<SignedSecretKey> = Keyring::new();
|
|
sec_ring.add(alice.secret.clone());
|
|
assert_eq!(sec_ring.keys(), [alice.secret]);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_keyring_load_self() {
|
|
// new_self() implies load_self()
|
|
let t = dummy_context().await;
|
|
configure_alice_keypair(&t.ctx).await;
|
|
let alice = alice_keypair();
|
|
|
|
let pub_ring: Keyring<SignedPublicKey> = Keyring::new_self(&t.ctx).await.unwrap();
|
|
assert_eq!(pub_ring.keys(), [alice.public]);
|
|
|
|
let sec_ring: Keyring<SignedSecretKey> = Keyring::new_self(&t.ctx).await.unwrap();
|
|
assert_eq!(sec_ring.keys(), [alice.secret]);
|
|
}
|
|
}
|