Rewrite of Signer

This commit is contained in:
Mike Dilger 2023-01-05 21:43:16 +13:00
parent aa757bd9bd
commit 6b7be372da
2 changed files with 98 additions and 112 deletions

View File

@ -78,17 +78,8 @@ impl Overlord {
} }
pub async fn run_inner(&mut self) -> Result<(), Error> { pub async fn run_inner(&mut self) -> Result<(), Error> {
// Load Signer (we cannot unlock yet, UI will have to drive that after // Load signer from settings
// prompting for a password) GLOBALS.signer.write().await.load_from_settings().await;
if let Some(epk) = GLOBALS
.settings
.read()
.await
.encrypted_private_key
.to_owned()
{
GLOBALS.signer.write().await.load_encrypted_private_key(epk);
}
// FIXME - if this needs doing, it should be done dynamically as // FIXME - if this needs doing, it should be done dynamically as
// new people are encountered, not batch-style on startup. // new people are encountered, not batch-style on startup.
@ -417,65 +408,27 @@ impl Overlord {
} }
"generate_private_key" => { "generate_private_key" => {
let mut password: String = serde_json::from_str(&bus_message.json_payload)?; let mut password: String = serde_json::from_str(&bus_message.json_payload)?;
let epk = GLOBALS GLOBALS.signer.write().await.generate_private_key(&password)?;
.signer
.write()
.await
.generate_private_key(&password)?;
password.zeroize(); password.zeroize();
GLOBALS.signer.read().await.save_through_settings().await?;
// Export and save private key
let public_key = GLOBALS.signer.read().await.public_key().unwrap();
{
let mut settings = GLOBALS.settings.write().await;
settings.encrypted_private_key = Some(epk);
settings.public_key = Some(public_key);
settings.save().await?;
}
} }
"import_bech32" => { "import_bech32" => {
let (mut import_bech32, mut password): (String, String) = let (mut import_bech32, mut password): (String, String) =
serde_json::from_str(&bus_message.json_payload)?; serde_json::from_str(&bus_message.json_payload)?;
let pk = PrivateKey::try_from_bech32_string(&import_bech32)?; let pk = PrivateKey::try_from_bech32_string(&import_bech32)?;
import_bech32.zeroize(); import_bech32.zeroize();
let epk = pk.export_encrypted(&password)?; GLOBALS.signer.write().await.set_private_key(pk, &password)?;
{
let mut signer = GLOBALS.signer.write().await;
signer.load_encrypted_private_key(epk.clone());
signer.unlock_encrypted_private_key(&password)?;
}
password.zeroize(); password.zeroize();
GLOBALS.signer.read().await.save_through_settings().await?;
// Save
let public_key = GLOBALS.signer.read().await.public_key().unwrap();
{
let mut settings = GLOBALS.settings.write().await;
settings.encrypted_private_key = Some(epk);
settings.public_key = Some(public_key);
settings.save().await?;
}
} }
"import_hex" => { "import_hex" => {
let (mut import_hex, mut password): (String, String) = let (mut import_hex, mut password): (String, String) =
serde_json::from_str(&bus_message.json_payload)?; serde_json::from_str(&bus_message.json_payload)?;
let pk = PrivateKey::try_from_hex_string(&import_hex)?; let pk = PrivateKey::try_from_hex_string(&import_hex)?;
import_hex.zeroize(); import_hex.zeroize();
let epk = pk.export_encrypted(&password)?; GLOBALS.signer.write().await.set_private_key(pk, &password)?;
{
let mut signer = GLOBALS.signer.write().await;
signer.load_encrypted_private_key(epk.clone());
signer.unlock_encrypted_private_key(&password)?;
}
password.zeroize(); password.zeroize();
GLOBALS.signer.read().await.save_through_settings().await?;
// Save
let public_key = GLOBALS.signer.read().await.public_key().unwrap();
{
let mut settings = GLOBALS.settings.write().await;
settings.encrypted_private_key = Some(epk);
settings.public_key = Some(public_key);
settings.save().await?;
}
} }
"save_relays" => { "save_relays" => {
let dirty_relays: Vec<DbRelay> = GLOBALS let dirty_relays: Vec<DbRelay> = GLOBALS

View File

@ -3,65 +3,103 @@ use crate::globals::GLOBALS;
use nostr_types::{EncryptedPrivateKey, Event, KeySecurity, PreEvent, PrivateKey, PublicKey}; use nostr_types::{EncryptedPrivateKey, Event, KeySecurity, PreEvent, PrivateKey, PublicKey};
use tokio::task; use tokio::task;
pub enum Signer { pub struct Signer {
Fresh, public: Option<PublicKey>,
Encrypted(EncryptedPrivateKey), encrypted: Option<EncryptedPrivateKey>,
Ready(PrivateKey, EncryptedPrivateKey), private: Option<PrivateKey>,
} }
impl Default for Signer { impl Default for Signer {
fn default() -> Signer { fn default() -> Signer {
Signer::Fresh Signer {
public: None,
encrypted: None,
private: None,
}
} }
} }
impl Signer { impl Signer {
pub fn load_encrypted_private_key(&mut self, epk: EncryptedPrivateKey) { pub async fn load_from_settings(&mut self) {
*self = Signer::Encrypted(epk); let settings = GLOBALS.settings.read().await;
*self = Signer {
public: settings.public_key,
encrypted: settings.encrypted_private_key.clone(),
private: None
};
}
pub async fn save_through_settings(&self) -> Result<(), Error> {
let mut settings = GLOBALS.settings.write().await;
settings.public_key = self.public.clone();
settings.encrypted_private_key = self.encrypted.clone();
settings.save().await
}
#[allow(dead_code)]
pub fn set_public_key(&mut self, pk: PublicKey) {
if self.private.is_some() {
*GLOBALS.status_message.blocking_write() = "Ignored setting of public key (private key supercedes)".to_string();
} else {
self.public = Some(pk);
}
}
#[allow(dead_code)]
pub fn set_encrypted_private_key(&mut self, epk: EncryptedPrivateKey) {
if self.private.is_some() && self.encrypted.is_some() {
// ignore, epk supercedes
} else {
self.encrypted = Some(epk);
}
}
pub fn set_private_key(&mut self, pk: PrivateKey, pass: &str) -> Result<(), Error> {
self.encrypted = Some(pk.export_encrypted(&pass)?);
self.public = Some(pk.public_key());
self.private = Some(pk);
Ok(())
} }
pub fn unlock_encrypted_private_key(&mut self, pass: &str) -> Result<(), Error> { pub fn unlock_encrypted_private_key(&mut self, pass: &str) -> Result<(), Error> {
if let Signer::Encrypted(epk) = self { if self.private.is_some() {
*self = Signer::Ready(epk.decrypt(pass)?, epk.clone()); // ignore, already unlocked
Ok(())
}
else if let Some(epk) = &self.encrypted {
self.private = Some(epk.decrypt(pass)?);
Ok(()) Ok(())
} else { } else {
Err(Error::NoPrivateKey) Err(Error::NoPrivateKey)
} }
} }
pub fn generate_private_key(&mut self, pass: &str) -> Result<EncryptedPrivateKey, Error> { pub fn generate_private_key(&mut self, pass: &str) -> Result<(), Error> {
let pk = PrivateKey::generate(); let pk = PrivateKey::generate();
let epk = pk.export_encrypted(pass)?; self.encrypted = Some(pk.export_encrypted(pass)?);
*self = Signer::Ready(pk, epk.clone()); self.public = Some(pk.public_key());
Ok(epk) self.private = Some(pk);
Ok(())
} }
pub fn is_loaded(&self) -> bool { pub fn is_loaded(&self) -> bool {
matches!(self, Signer::Encrypted(_)) || matches!(self, Signer::Ready(_, _)) self.encrypted.is_some() || self.private.is_some()
} }
pub fn is_ready(&self) -> bool { pub fn is_ready(&self) -> bool {
matches!(self, Signer::Ready(_, _)) self.private.is_some()
} }
pub fn public_key(&self) -> Option<PublicKey> { pub fn public_key(&self) -> Option<PublicKey> {
if let Signer::Ready(pk, _) = self { self.public.clone()
Some(pk.public_key())
} else {
None
}
} }
pub fn encrypted_private_key(&self) -> Option<EncryptedPrivateKey> { pub fn encrypted_private_key(&self) -> Option<EncryptedPrivateKey> {
if let Signer::Ready(_, epk) = self { self.encrypted.clone()
Some(epk.clone())
} else {
None
}
} }
pub fn key_security(&self) -> Option<KeySecurity> { pub fn key_security(&self) -> Option<KeySecurity> {
if let Signer::Ready(pk, _) = self { if let Some(pk) = &self.private {
Some(pk.key_security()) Some(pk.key_security())
} else { } else {
None None
@ -69,35 +107,33 @@ impl Signer {
} }
pub fn sign_preevent(&self, preevent: PreEvent, pow: Option<u8>) -> Result<Event, Error> { pub fn sign_preevent(&self, preevent: PreEvent, pow: Option<u8>) -> Result<Event, Error> {
match self { match &self.private {
Signer::Ready(pk, _) => match pow { Some(pk) => match pow {
Some(pow) => Ok(Event::new_with_pow(preevent, pk, pow)?), Some(pow) => Ok(Event::new_with_pow(preevent, &pk, pow)?),
None => Ok(Event::new(preevent, pk)?), None => Ok(Event::new(preevent, &pk)?),
}, },
_ => Err(Error::NoPrivateKey), _ => Err(Error::NoPrivateKey),
} }
} }
pub fn export_private_key_bech32(&mut self, pass: &str) -> Result<String, Error> { pub fn export_private_key_bech32(&mut self, pass: &str) -> Result<String, Error> {
match self { match &self.encrypted {
Signer::Ready(_, epk) => { Some(epk) => {
// Test password
let mut pk = epk.decrypt(pass)?; let mut pk = epk.decrypt(pass)?;
let output = pk.try_as_bech32_string()?; let output = pk.try_as_bech32_string()?;
// We have to regenerate encrypted private key because it may have fallen from // We have to regenerate encrypted private key because it may have fallen from
// medium to weak security. // medium to weak security. And then we need to save that
let epk = pk.export_encrypted(pass)?; let epk = pk.export_encrypted(pass)?;
self.encrypted = Some(epk);
// And then we have to save that self.private = Some(pk);
let mut settings = GLOBALS.settings.blocking_write();
settings.encrypted_private_key = Some(epk.clone());
task::spawn(async move { task::spawn(async move {
if let Err(e) = settings.save().await { if let Err(e) = GLOBALS.signer.read().await.save_through_settings().await {
tracing::error!("{}", e); tracing::error!("{}", e);
} }
}); });
*self = Signer::Ready(pk, epk);
Ok(output) Ok(output)
} }
_ => Err(Error::NoPrivateKey), _ => Err(Error::NoPrivateKey),
@ -105,25 +141,23 @@ impl Signer {
} }
pub fn export_private_key_hex(&mut self, pass: &str) -> Result<String, Error> { pub fn export_private_key_hex(&mut self, pass: &str) -> Result<String, Error> {
match self { match &self.encrypted {
Signer::Ready(_, epk) => { Some(epk) => {
// Test password
let mut pk = epk.decrypt(pass)?; let mut pk = epk.decrypt(pass)?;
let output = pk.as_hex_string(); let output = pk.as_hex_string();
// We have to regenerate encrypted private key because it may have fallen from // We have to regenerate encrypted private key because it may have fallen from
// medium to weak security. // medium to weak security. And then we need to save that
let epk = pk.export_encrypted(pass)?; let epk = pk.export_encrypted(pass)?;
self.encrypted = Some(epk);
// And then we have to save that self.private = Some(pk);
let mut settings = GLOBALS.settings.blocking_write();
settings.encrypted_private_key = Some(epk.clone());
task::spawn(async move { task::spawn(async move {
if let Err(e) = settings.save().await { if let Err(e) = GLOBALS.signer.read().await.save_through_settings().await {
tracing::error!("{}", e); tracing::error!("{}", e);
} }
}); });
*self = Signer::Ready(pk, epk);
Ok(output) Ok(output)
} }
_ => Err(Error::NoPrivateKey), _ => Err(Error::NoPrivateKey),
@ -131,20 +165,19 @@ impl Signer {
} }
pub fn delete_identity(&mut self, pass: &str) -> Result<(), Error> { pub fn delete_identity(&mut self, pass: &str) -> Result<(), Error> {
match self { match &self.encrypted {
Signer::Ready(_, epk) => { Some(epk) => {
// Verify their password // Verify their password
let _pk = epk.decrypt(pass)?; let _pk = epk.decrypt(pass)?;
// Delete from database self.private = None;
let mut settings = GLOBALS.settings.blocking_write(); self.encrypted = None;
settings.encrypted_private_key = None; self.public = None;
task::spawn(async move { task::spawn(async move {
if let Err(e) = settings.save().await { if let Err(e) = GLOBALS.signer.read().await.save_through_settings().await {
tracing::error!("{}", e); tracing::error!("{}", e);
} }
}); });
*self = Signer::Fresh;
Ok(()) Ok(())
} }
_ => Err(Error::NoPrivateKey), _ => Err(Error::NoPrivateKey),