mirror of
https://github.com/mikedilger/gossip.git
synced 2024-09-19 03:33:53 +00:00
Rewrite of Signer
This commit is contained in:
parent
aa757bd9bd
commit
6b7be372da
@ -78,17 +78,8 @@ impl Overlord {
|
||||
}
|
||||
|
||||
pub async fn run_inner(&mut self) -> Result<(), Error> {
|
||||
// Load Signer (we cannot unlock yet, UI will have to drive that after
|
||||
// prompting for a password)
|
||||
if let Some(epk) = GLOBALS
|
||||
.settings
|
||||
.read()
|
||||
.await
|
||||
.encrypted_private_key
|
||||
.to_owned()
|
||||
{
|
||||
GLOBALS.signer.write().await.load_encrypted_private_key(epk);
|
||||
}
|
||||
// Load signer from settings
|
||||
GLOBALS.signer.write().await.load_from_settings().await;
|
||||
|
||||
// FIXME - if this needs doing, it should be done dynamically as
|
||||
// new people are encountered, not batch-style on startup.
|
||||
@ -417,65 +408,27 @@ impl Overlord {
|
||||
}
|
||||
"generate_private_key" => {
|
||||
let mut password: String = serde_json::from_str(&bus_message.json_payload)?;
|
||||
let epk = GLOBALS
|
||||
.signer
|
||||
.write()
|
||||
.await
|
||||
.generate_private_key(&password)?;
|
||||
GLOBALS.signer.write().await.generate_private_key(&password)?;
|
||||
password.zeroize();
|
||||
|
||||
// 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?;
|
||||
}
|
||||
GLOBALS.signer.read().await.save_through_settings().await?;
|
||||
}
|
||||
"import_bech32" => {
|
||||
let (mut import_bech32, mut password): (String, String) =
|
||||
serde_json::from_str(&bus_message.json_payload)?;
|
||||
let pk = PrivateKey::try_from_bech32_string(&import_bech32)?;
|
||||
import_bech32.zeroize();
|
||||
let epk = pk.export_encrypted(&password)?;
|
||||
{
|
||||
let mut signer = GLOBALS.signer.write().await;
|
||||
signer.load_encrypted_private_key(epk.clone());
|
||||
signer.unlock_encrypted_private_key(&password)?;
|
||||
}
|
||||
GLOBALS.signer.write().await.set_private_key(pk, &password)?;
|
||||
password.zeroize();
|
||||
|
||||
// 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?;
|
||||
}
|
||||
GLOBALS.signer.read().await.save_through_settings().await?;
|
||||
}
|
||||
"import_hex" => {
|
||||
let (mut import_hex, mut password): (String, String) =
|
||||
serde_json::from_str(&bus_message.json_payload)?;
|
||||
let pk = PrivateKey::try_from_hex_string(&import_hex)?;
|
||||
import_hex.zeroize();
|
||||
let epk = pk.export_encrypted(&password)?;
|
||||
{
|
||||
let mut signer = GLOBALS.signer.write().await;
|
||||
signer.load_encrypted_private_key(epk.clone());
|
||||
signer.unlock_encrypted_private_key(&password)?;
|
||||
}
|
||||
GLOBALS.signer.write().await.set_private_key(pk, &password)?;
|
||||
password.zeroize();
|
||||
|
||||
// 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?;
|
||||
}
|
||||
GLOBALS.signer.read().await.save_through_settings().await?;
|
||||
}
|
||||
"save_relays" => {
|
||||
let dirty_relays: Vec<DbRelay> = GLOBALS
|
||||
|
147
src/signer.rs
147
src/signer.rs
@ -3,65 +3,103 @@ use crate::globals::GLOBALS;
|
||||
use nostr_types::{EncryptedPrivateKey, Event, KeySecurity, PreEvent, PrivateKey, PublicKey};
|
||||
use tokio::task;
|
||||
|
||||
pub enum Signer {
|
||||
Fresh,
|
||||
Encrypted(EncryptedPrivateKey),
|
||||
Ready(PrivateKey, EncryptedPrivateKey),
|
||||
pub struct Signer {
|
||||
public: Option<PublicKey>,
|
||||
encrypted: Option<EncryptedPrivateKey>,
|
||||
private: Option<PrivateKey>,
|
||||
}
|
||||
|
||||
impl Default for Signer {
|
||||
fn default() -> Signer {
|
||||
Signer::Fresh
|
||||
Signer {
|
||||
public: None,
|
||||
encrypted: None,
|
||||
private: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Signer {
|
||||
pub fn load_encrypted_private_key(&mut self, epk: EncryptedPrivateKey) {
|
||||
*self = Signer::Encrypted(epk);
|
||||
pub async fn load_from_settings(&mut self) {
|
||||
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> {
|
||||
if let Signer::Encrypted(epk) = self {
|
||||
*self = Signer::Ready(epk.decrypt(pass)?, epk.clone());
|
||||
if self.private.is_some() {
|
||||
// ignore, already unlocked
|
||||
Ok(())
|
||||
}
|
||||
else if let Some(epk) = &self.encrypted {
|
||||
self.private = Some(epk.decrypt(pass)?);
|
||||
Ok(())
|
||||
} else {
|
||||
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 epk = pk.export_encrypted(pass)?;
|
||||
*self = Signer::Ready(pk, epk.clone());
|
||||
Ok(epk)
|
||||
self.encrypted = Some(pk.export_encrypted(pass)?);
|
||||
self.public = Some(pk.public_key());
|
||||
self.private = Some(pk);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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 {
|
||||
matches!(self, Signer::Ready(_, _))
|
||||
self.private.is_some()
|
||||
}
|
||||
|
||||
pub fn public_key(&self) -> Option<PublicKey> {
|
||||
if let Signer::Ready(pk, _) = self {
|
||||
Some(pk.public_key())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
self.public.clone()
|
||||
}
|
||||
|
||||
pub fn encrypted_private_key(&self) -> Option<EncryptedPrivateKey> {
|
||||
if let Signer::Ready(_, epk) = self {
|
||||
Some(epk.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
self.encrypted.clone()
|
||||
}
|
||||
|
||||
pub fn key_security(&self) -> Option<KeySecurity> {
|
||||
if let Signer::Ready(pk, _) = self {
|
||||
if let Some(pk) = &self.private {
|
||||
Some(pk.key_security())
|
||||
} else {
|
||||
None
|
||||
@ -69,35 +107,33 @@ impl Signer {
|
||||
}
|
||||
|
||||
pub fn sign_preevent(&self, preevent: PreEvent, pow: Option<u8>) -> Result<Event, Error> {
|
||||
match self {
|
||||
Signer::Ready(pk, _) => match pow {
|
||||
Some(pow) => Ok(Event::new_with_pow(preevent, pk, pow)?),
|
||||
None => Ok(Event::new(preevent, pk)?),
|
||||
match &self.private {
|
||||
Some(pk) => match pow {
|
||||
Some(pow) => Ok(Event::new_with_pow(preevent, &pk, pow)?),
|
||||
None => Ok(Event::new(preevent, &pk)?),
|
||||
},
|
||||
_ => Err(Error::NoPrivateKey),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn export_private_key_bech32(&mut self, pass: &str) -> Result<String, Error> {
|
||||
match self {
|
||||
Signer::Ready(_, epk) => {
|
||||
match &self.encrypted {
|
||||
Some(epk) => {
|
||||
// Test password
|
||||
let mut pk = epk.decrypt(pass)?;
|
||||
|
||||
let output = pk.try_as_bech32_string()?;
|
||||
|
||||
// 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)?;
|
||||
|
||||
// And then we have to save that
|
||||
let mut settings = GLOBALS.settings.blocking_write();
|
||||
settings.encrypted_private_key = Some(epk.clone());
|
||||
self.encrypted = Some(epk);
|
||||
self.private = Some(pk);
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
*self = Signer::Ready(pk, epk);
|
||||
Ok(output)
|
||||
}
|
||||
_ => Err(Error::NoPrivateKey),
|
||||
@ -105,25 +141,23 @@ impl Signer {
|
||||
}
|
||||
|
||||
pub fn export_private_key_hex(&mut self, pass: &str) -> Result<String, Error> {
|
||||
match self {
|
||||
Signer::Ready(_, epk) => {
|
||||
match &self.encrypted {
|
||||
Some(epk) => {
|
||||
// Test password
|
||||
let mut pk = epk.decrypt(pass)?;
|
||||
|
||||
let output = pk.as_hex_string();
|
||||
|
||||
// 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)?;
|
||||
|
||||
// And then we have to save that
|
||||
let mut settings = GLOBALS.settings.blocking_write();
|
||||
settings.encrypted_private_key = Some(epk.clone());
|
||||
self.encrypted = Some(epk);
|
||||
self.private = Some(pk);
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
*self = Signer::Ready(pk, epk);
|
||||
Ok(output)
|
||||
}
|
||||
_ => Err(Error::NoPrivateKey),
|
||||
@ -131,20 +165,19 @@ impl Signer {
|
||||
}
|
||||
|
||||
pub fn delete_identity(&mut self, pass: &str) -> Result<(), Error> {
|
||||
match self {
|
||||
Signer::Ready(_, epk) => {
|
||||
match &self.encrypted {
|
||||
Some(epk) => {
|
||||
// Verify their password
|
||||
let _pk = epk.decrypt(pass)?;
|
||||
|
||||
// Delete from database
|
||||
let mut settings = GLOBALS.settings.blocking_write();
|
||||
settings.encrypted_private_key = None;
|
||||
self.private = None;
|
||||
self.encrypted = None;
|
||||
self.public = None;
|
||||
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);
|
||||
}
|
||||
});
|
||||
*self = Signer::Fresh;
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(Error::NoPrivateKey),
|
||||
|
Loading…
Reference in New Issue
Block a user