diff --git a/src/error.rs b/src/error.rs index e3de79dc..f9c95522 100644 --- a/src/error.rs +++ b/src/error.rs @@ -30,6 +30,9 @@ pub enum Error { #[error("Nostr: {0}")] Nostr(#[from] nostr_types::Error), + #[error("No private key available.")] + NoPrivateKey, + #[error("Image: {0}")] Image(#[from] image::error::ImageError), diff --git a/src/globals.rs b/src/globals.rs index e5090972..aa410d8c 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -3,6 +3,7 @@ use crate::db::{DbEvent, DbPerson, DbPersonRelay, DbRelay}; use crate::error::Error; use crate::relationship::Relationship; use crate::settings::Settings; +use crate::signer::Signer; use async_recursion::async_recursion; use nostr_types::{Event, EventKind, Id, IdHex, PublicKey, PublicKeyHex, Unixtime, Url}; use rusqlite::Connection; @@ -55,6 +56,9 @@ pub struct Globals { /// Settings pub settings: RwLock, + + /// Signer + pub signer: RwLock, } lazy_static! { @@ -79,6 +83,7 @@ lazy_static! { relays: RwLock::new(HashMap::new()), shutting_down: AtomicBool::new(false), settings: RwLock::new(Settings::default()), + signer: RwLock::new(Signer::default()), } }; } diff --git a/src/main.rs b/src/main.rs index 253f64e5..0c8c09ef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ mod overlord; mod process; mod relationship; mod settings; +mod signer; mod ui; use crate::comms::BusMessage; diff --git a/src/signer.rs b/src/signer.rs new file mode 100644 index 00000000..65b52710 --- /dev/null +++ b/src/signer.rs @@ -0,0 +1,67 @@ +use crate::error::Error; +use nostr_types::{EncryptedPrivateKey, Event, KeySecurity, PreEvent, PrivateKey, PublicKey}; + +pub enum Signer { + Fresh, + Encrypted(EncryptedPrivateKey), + Ready(PrivateKey), +} + +impl Default for Signer { + fn default() -> Signer { + Signer::Fresh + } +} + +impl Signer { + #[allow(dead_code)] + pub fn load_encrypted_private_key(&mut self, epk: EncryptedPrivateKey) { + *self = Signer::Encrypted(epk); + } + + #[allow(dead_code)] + pub fn unlock_encrypted_private_key(&mut self, pass: &str) -> Result<(), Error> { + if let Signer::Encrypted(epk) = self { + *self = Signer::Ready(epk.decrypt(pass)?); + Ok(()) + } else { + Err(Error::NoPrivateKey) + } + } + + #[allow(dead_code)] + pub fn is_loaded(&self) -> bool { + matches!(self, Signer::Encrypted(_)) || matches!(self, Signer::Ready(_)) + } + + #[allow(dead_code)] + pub fn is_ready(&self) -> bool { + matches!(self, Signer::Ready(_)) + } + + #[allow(dead_code)] + pub fn public_key(&self) -> Option { + if let Signer::Ready(pk) = self { + Some(pk.public_key()) + } else { + None + } + } + + #[allow(dead_code)] + pub fn key_security(&self) -> Option { + if let Signer::Ready(pk) = self { + Some(pk.key_security()) + } else { + None + } + } + + #[allow(dead_code)] + pub fn sign_preevent(&self, preevent: PreEvent) -> Result { + match self { + Signer::Ready(pk) => Ok(Event::new(preevent, pk)?), + _ => Err(Error::NoPrivateKey), + } + } +}