2022-12-27 06:45:57 +00:00
|
|
|
use crate::error::Error;
|
2023-01-04 02:23:17 +00:00
|
|
|
use crate::globals::GLOBALS;
|
2022-12-27 06:45:57 +00:00
|
|
|
use nostr_types::{EncryptedPrivateKey, Event, KeySecurity, PreEvent, PrivateKey, PublicKey};
|
2023-01-04 02:23:17 +00:00
|
|
|
use tokio::task;
|
2022-12-27 06:45:57 +00:00
|
|
|
|
2023-01-20 04:41:00 +00:00
|
|
|
const DEFAULT_LOG_N: u8 = 18;
|
|
|
|
|
2023-01-05 13:29:13 +00:00
|
|
|
#[derive(Default)]
|
2023-01-05 08:43:16 +00:00
|
|
|
pub struct Signer {
|
|
|
|
public: Option<PublicKey>,
|
|
|
|
encrypted: Option<EncryptedPrivateKey>,
|
|
|
|
private: Option<PrivateKey>,
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Signer {
|
2023-01-05 08:43:16 +00:00
|
|
|
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(),
|
2023-01-05 13:29:13 +00:00
|
|
|
private: None,
|
2023-01-05 08:43:16 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn save_through_settings(&self) -> Result<(), Error> {
|
|
|
|
let mut settings = GLOBALS.settings.write().await;
|
2023-01-05 13:29:13 +00:00
|
|
|
settings.public_key = self.public;
|
2023-01-05 08:43:16 +00:00
|
|
|
settings.encrypted_private_key = self.encrypted.clone();
|
|
|
|
settings.save().await
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_public_key(&mut self, pk: PublicKey) {
|
|
|
|
if self.private.is_some() {
|
2023-01-05 13:29:13 +00:00
|
|
|
*GLOBALS.status_message.blocking_write() =
|
|
|
|
"Ignored setting of public key (private key supercedes)".to_string();
|
2023-01-05 08:43:16 +00:00
|
|
|
} else {
|
|
|
|
self.public = Some(pk);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-05 13:29:13 +00:00
|
|
|
pub fn clear_public_key(&mut self) {
|
|
|
|
if self.private.is_some() {
|
|
|
|
*GLOBALS.status_message.blocking_write() =
|
|
|
|
"Ignored clearing of public key (private key supercedes)".to_string();
|
|
|
|
} else {
|
|
|
|
self.public = None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-05 08:43:16 +00:00
|
|
|
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> {
|
2023-01-20 04:41:00 +00:00
|
|
|
self.encrypted = Some(pk.export_encrypted(pass, DEFAULT_LOG_N)?);
|
2023-01-05 08:43:16 +00:00
|
|
|
self.public = Some(pk.public_key());
|
|
|
|
self.private = Some(pk);
|
|
|
|
Ok(())
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn unlock_encrypted_private_key(&mut self, pass: &str) -> Result<(), Error> {
|
2023-01-05 08:43:16 +00:00
|
|
|
if self.private.is_some() {
|
|
|
|
// ignore, already unlocked
|
|
|
|
Ok(())
|
2023-01-05 13:29:13 +00:00
|
|
|
} else if let Some(epk) = &self.encrypted {
|
2023-01-05 08:43:16 +00:00
|
|
|
self.private = Some(epk.decrypt(pass)?);
|
2023-01-20 04:43:13 +00:00
|
|
|
|
|
|
|
if let Some(private) = &self.private {
|
2023-01-20 05:16:04 +00:00
|
|
|
// it will be
|
|
|
|
|
|
|
|
// If older version, re-encrypt with new version at default 2^18 rounds
|
2023-01-20 04:43:13 +00:00
|
|
|
if epk.version()? < 2 {
|
|
|
|
self.encrypted = Some(private.export_encrypted(pass, DEFAULT_LOG_N)?);
|
|
|
|
// and eventually save
|
|
|
|
task::spawn(async move {
|
|
|
|
if let Err(e) = GLOBALS.signer.read().await.save_through_settings().await {
|
|
|
|
tracing::error!("{}", e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2023-01-20 05:16:04 +00:00
|
|
|
|
|
|
|
if self.public.is_none() {
|
|
|
|
self.public = Some(private.public_key());
|
|
|
|
}
|
2023-01-20 04:43:13 +00:00
|
|
|
}
|
|
|
|
|
2022-12-27 06:45:57 +00:00
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(Error::NoPrivateKey)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-05 08:43:16 +00:00
|
|
|
pub fn generate_private_key(&mut self, pass: &str) -> Result<(), Error> {
|
2023-01-04 02:23:17 +00:00
|
|
|
let pk = PrivateKey::generate();
|
2023-01-20 04:41:00 +00:00
|
|
|
self.encrypted = Some(pk.export_encrypted(pass, DEFAULT_LOG_N)?);
|
2023-01-05 08:43:16 +00:00
|
|
|
self.public = Some(pk.public_key());
|
|
|
|
self.private = Some(pk);
|
|
|
|
Ok(())
|
2022-12-30 02:13:34 +00:00
|
|
|
}
|
|
|
|
|
2022-12-27 06:45:57 +00:00
|
|
|
pub fn is_loaded(&self) -> bool {
|
2023-01-05 08:43:16 +00:00
|
|
|
self.encrypted.is_some() || self.private.is_some()
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_ready(&self) -> bool {
|
2023-01-05 08:43:16 +00:00
|
|
|
self.private.is_some()
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn public_key(&self) -> Option<PublicKey> {
|
2023-01-05 13:29:13 +00:00
|
|
|
self.public
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|
|
|
|
|
2023-01-04 02:23:17 +00:00
|
|
|
pub fn encrypted_private_key(&self) -> Option<EncryptedPrivateKey> {
|
2023-01-05 08:43:16 +00:00
|
|
|
self.encrypted.clone()
|
2023-01-04 02:23:17 +00:00
|
|
|
}
|
|
|
|
|
2022-12-27 06:45:57 +00:00
|
|
|
pub fn key_security(&self) -> Option<KeySecurity> {
|
2023-01-05 13:29:13 +00:00
|
|
|
self.private.as_ref().map(|pk| pk.key_security())
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|
|
|
|
|
2022-12-29 18:56:59 +00:00
|
|
|
pub fn sign_preevent(&self, preevent: PreEvent, pow: Option<u8>) -> Result<Event, Error> {
|
2023-01-05 08:43:16 +00:00
|
|
|
match &self.private {
|
|
|
|
Some(pk) => match pow {
|
2023-01-05 13:29:13 +00:00
|
|
|
Some(pow) => Ok(Event::new_with_pow(preevent, pk, pow)?),
|
|
|
|
None => Ok(Event::new(preevent, pk)?),
|
2022-12-29 18:56:59 +00:00
|
|
|
},
|
2022-12-27 06:45:57 +00:00
|
|
|
_ => Err(Error::NoPrivateKey),
|
|
|
|
}
|
|
|
|
}
|
2023-01-04 02:23:17 +00:00
|
|
|
|
|
|
|
pub fn export_private_key_bech32(&mut self, pass: &str) -> Result<String, Error> {
|
2023-01-05 08:43:16 +00:00
|
|
|
match &self.encrypted {
|
|
|
|
Some(epk) => {
|
|
|
|
// Test password
|
2023-01-04 02:23:17 +00:00
|
|
|
let mut pk = epk.decrypt(pass)?;
|
2023-01-05 08:43:16 +00:00
|
|
|
|
2023-01-04 02:23:17 +00:00
|
|
|
let output = pk.try_as_bech32_string()?;
|
|
|
|
|
|
|
|
// We have to regenerate encrypted private key because it may have fallen from
|
2023-01-05 08:43:16 +00:00
|
|
|
// medium to weak security. And then we need to save that
|
2023-01-20 04:41:00 +00:00
|
|
|
let epk = pk.export_encrypted(pass, DEFAULT_LOG_N)?;
|
2023-01-05 08:43:16 +00:00
|
|
|
self.encrypted = Some(epk);
|
|
|
|
self.private = Some(pk);
|
2023-01-04 02:23:17 +00:00
|
|
|
task::spawn(async move {
|
2023-01-05 08:43:16 +00:00
|
|
|
if let Err(e) = GLOBALS.signer.read().await.save_through_settings().await {
|
2023-01-04 02:23:17 +00:00
|
|
|
tracing::error!("{}", e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Ok(output)
|
|
|
|
}
|
|
|
|
_ => Err(Error::NoPrivateKey),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn export_private_key_hex(&mut self, pass: &str) -> Result<String, Error> {
|
2023-01-05 08:43:16 +00:00
|
|
|
match &self.encrypted {
|
|
|
|
Some(epk) => {
|
|
|
|
// Test password
|
2023-01-04 02:23:17 +00:00
|
|
|
let mut pk = epk.decrypt(pass)?;
|
2023-01-05 08:43:16 +00:00
|
|
|
|
2023-01-04 02:23:17 +00:00
|
|
|
let output = pk.as_hex_string();
|
|
|
|
|
|
|
|
// We have to regenerate encrypted private key because it may have fallen from
|
2023-01-05 08:43:16 +00:00
|
|
|
// medium to weak security. And then we need to save that
|
2023-01-20 04:41:00 +00:00
|
|
|
let epk = pk.export_encrypted(pass, DEFAULT_LOG_N)?;
|
2023-01-05 08:43:16 +00:00
|
|
|
self.encrypted = Some(epk);
|
|
|
|
self.private = Some(pk);
|
2023-01-04 02:23:17 +00:00
|
|
|
task::spawn(async move {
|
2023-01-05 08:43:16 +00:00
|
|
|
if let Err(e) = GLOBALS.signer.read().await.save_through_settings().await {
|
2023-01-04 02:23:17 +00:00
|
|
|
tracing::error!("{}", e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Ok(output)
|
|
|
|
}
|
|
|
|
_ => Err(Error::NoPrivateKey),
|
|
|
|
}
|
|
|
|
}
|
2023-01-04 03:35:54 +00:00
|
|
|
|
|
|
|
pub fn delete_identity(&mut self, pass: &str) -> Result<(), Error> {
|
2023-01-05 08:43:16 +00:00
|
|
|
match &self.encrypted {
|
|
|
|
Some(epk) => {
|
2023-01-04 03:35:54 +00:00
|
|
|
// Verify their password
|
|
|
|
let _pk = epk.decrypt(pass)?;
|
|
|
|
|
2023-01-05 08:43:16 +00:00
|
|
|
self.private = None;
|
|
|
|
self.encrypted = None;
|
|
|
|
self.public = None;
|
2023-01-04 03:35:54 +00:00
|
|
|
task::spawn(async move {
|
2023-01-05 08:43:16 +00:00
|
|
|
if let Err(e) = GLOBALS.signer.read().await.save_through_settings().await {
|
2023-01-04 03:35:54 +00:00
|
|
|
tracing::error!("{}", e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
_ => Err(Error::NoPrivateKey),
|
|
|
|
}
|
|
|
|
}
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|