2023-04-24 06:27:56 +00:00
|
|
|
use std::sync::mpsc::Sender;
|
|
|
|
|
2023-03-29 03:51:56 +00:00
|
|
|
use crate::error::{Error, ErrorKind};
|
2023-01-04 02:23:17 +00:00
|
|
|
use crate::globals::GLOBALS;
|
2023-07-06 02:21:13 +00:00
|
|
|
use nostr_types::{
|
2023-08-21 20:17:27 +00:00
|
|
|
EncryptedPrivateKey, Event, EventKind, Id, KeySecurity, PreEvent, PrivateKey, PublicKey, Rumor,
|
2023-07-06 02:21:13 +00:00
|
|
|
};
|
2023-02-03 21:35:13 +00:00
|
|
|
use parking_lot::RwLock;
|
2023-01-04 02:23:17 +00:00
|
|
|
use tokio::task;
|
2022-12-27 06:45:57 +00:00
|
|
|
|
2023-01-05 13:29:13 +00:00
|
|
|
#[derive(Default)]
|
2023-01-05 08:43:16 +00:00
|
|
|
pub struct Signer {
|
2023-02-03 21:35:13 +00:00
|
|
|
public: RwLock<Option<PublicKey>>,
|
|
|
|
encrypted: RwLock<Option<EncryptedPrivateKey>>,
|
|
|
|
private: RwLock<Option<PrivateKey>>,
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Signer {
|
2023-07-18 00:08:10 +00:00
|
|
|
pub fn load_from_settings(&self) -> Result<(), Error> {
|
2023-08-22 22:13:59 +00:00
|
|
|
if self.public.read().is_none() {
|
|
|
|
*self.public.write() = GLOBALS.storage.read_setting_public_key();
|
|
|
|
}
|
|
|
|
if self.encrypted.read().is_none() {
|
|
|
|
let epk = GLOBALS.storage.read_encrypted_private_key()?;
|
|
|
|
*self.encrypted.write() = epk;
|
|
|
|
}
|
2023-07-18 00:08:10 +00:00
|
|
|
|
|
|
|
Ok(())
|
2023-01-05 08:43:16 +00:00
|
|
|
}
|
|
|
|
|
2023-08-18 22:32:56 +00:00
|
|
|
pub async fn save(&self) -> Result<(), Error> {
|
2023-08-18 22:22:48 +00:00
|
|
|
GLOBALS
|
|
|
|
.storage
|
|
|
|
.write_setting_public_key(&self.public.read(), None)?;
|
2023-02-18 04:22:59 +00:00
|
|
|
|
|
|
|
let epk = self.encrypted.read().clone();
|
2023-08-03 23:55:08 +00:00
|
|
|
GLOBALS.storage.write_encrypted_private_key(&epk, None)?;
|
2023-07-18 00:08:10 +00:00
|
|
|
|
2023-02-18 04:22:59 +00:00
|
|
|
Ok(())
|
2023-01-05 08:43:16 +00:00
|
|
|
}
|
|
|
|
|
2023-02-03 21:35:13 +00:00
|
|
|
pub fn set_public_key(&self, pk: PublicKey) {
|
|
|
|
if self.private.read().is_some() {
|
2023-06-24 23:01:55 +00:00
|
|
|
GLOBALS
|
|
|
|
.status_queue
|
|
|
|
.write()
|
|
|
|
.write("Ignored setting of public key (private key supercedes)".to_string());
|
2023-01-05 08:43:16 +00:00
|
|
|
} else {
|
2023-02-03 21:35:13 +00:00
|
|
|
*self.public.write() = Some(pk);
|
2023-01-05 08:43:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-03 21:35:13 +00:00
|
|
|
pub fn clear_public_key(&self) {
|
|
|
|
if self.private.read().is_some() {
|
2023-06-24 23:01:55 +00:00
|
|
|
GLOBALS
|
|
|
|
.status_queue
|
|
|
|
.write()
|
|
|
|
.write("Ignored clearing of public key (private key supercedes)".to_string());
|
2023-01-05 13:29:13 +00:00
|
|
|
} else {
|
2023-02-03 21:35:13 +00:00
|
|
|
*self.public.write() = None;
|
2023-01-05 13:29:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-03 21:35:13 +00:00
|
|
|
pub fn set_encrypted_private_key(&self, epk: EncryptedPrivateKey) {
|
|
|
|
if self.private.read().is_some() && self.encrypted.read().is_some() {
|
2023-01-05 08:43:16 +00:00
|
|
|
// ignore, epk supercedes
|
|
|
|
} else {
|
2023-02-03 21:35:13 +00:00
|
|
|
*self.encrypted.write() = Some(epk);
|
2023-01-05 08:43:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-03 21:35:13 +00:00
|
|
|
pub fn set_private_key(&self, pk: PrivateKey, pass: &str) -> Result<(), Error> {
|
2023-08-17 21:55:51 +00:00
|
|
|
*self.encrypted.write() =
|
|
|
|
Some(pk.export_encrypted(pass, GLOBALS.storage.read_setting_log_n())?);
|
2023-02-03 21:35:13 +00:00
|
|
|
*self.public.write() = Some(pk.public_key());
|
|
|
|
*self.private.write() = Some(pk);
|
2023-01-05 08:43:16 +00:00
|
|
|
Ok(())
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|
|
|
|
|
2023-02-03 21:35:13 +00:00
|
|
|
pub fn unlock_encrypted_private_key(&self, pass: &str) -> Result<(), Error> {
|
|
|
|
if self.private.read().is_some() {
|
2023-01-05 08:43:16 +00:00
|
|
|
// ignore, already unlocked
|
|
|
|
Ok(())
|
2023-02-03 21:35:13 +00:00
|
|
|
} else if let Some(epk) = &*self.encrypted.read() {
|
|
|
|
*self.private.write() = Some(epk.decrypt(pass)?);
|
2023-01-20 04:43:13 +00:00
|
|
|
|
2023-02-03 21:35:13 +00:00
|
|
|
if let Some(private) = &*self.private.read() {
|
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 {
|
2023-08-11 06:14:25 +00:00
|
|
|
*self.encrypted.write() =
|
2023-08-17 21:55:51 +00:00
|
|
|
Some(private.export_encrypted(pass, GLOBALS.storage.read_setting_log_n())?);
|
2023-01-20 04:43:13 +00:00
|
|
|
// and eventually save
|
|
|
|
task::spawn(async move {
|
2023-08-18 22:32:56 +00:00
|
|
|
if let Err(e) = GLOBALS.signer.save().await {
|
2023-01-20 04:43:13 +00:00
|
|
|
tracing::error!("{}", e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2023-01-20 05:16:04 +00:00
|
|
|
|
2023-02-03 21:35:13 +00:00
|
|
|
if self.public.read().is_none() {
|
|
|
|
*self.public.write() = Some(private.public_key());
|
2023-01-20 05:16:04 +00:00
|
|
|
}
|
2023-07-03 06:45:09 +00:00
|
|
|
|
|
|
|
// Invalidate DMs so they rerender decrypted
|
2023-07-06 02:21:13 +00:00
|
|
|
let dms: Vec<Id> = GLOBALS
|
2023-07-23 07:57:26 +00:00
|
|
|
.storage
|
|
|
|
.find_events(
|
2023-08-21 20:17:27 +00:00
|
|
|
&[EventKind::EncryptedDirectMessage, EventKind::GiftWrap],
|
2023-07-26 07:43:31 +00:00
|
|
|
&[],
|
2023-07-23 07:57:26 +00:00
|
|
|
None,
|
|
|
|
|_| true,
|
|
|
|
false,
|
|
|
|
)?
|
2023-07-06 02:21:13 +00:00
|
|
|
.iter()
|
2023-07-23 07:57:26 +00:00
|
|
|
.map(|e| e.id)
|
2023-07-03 06:45:09 +00:00
|
|
|
.collect();
|
2023-07-23 07:57:26 +00:00
|
|
|
|
2023-07-03 06:45:09 +00:00
|
|
|
GLOBALS.ui_notes_to_invalidate.write().extend(dms);
|
2023-01-20 04:43:13 +00:00
|
|
|
}
|
|
|
|
|
2022-12-27 06:45:57 +00:00
|
|
|
Ok(())
|
|
|
|
} else {
|
2023-03-29 03:51:56 +00:00
|
|
|
Err((ErrorKind::NoPrivateKey, file!(), line!()).into())
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-10 22:32:37 +00:00
|
|
|
pub fn change_passphrase(&self, old: &str, new: &str) -> Result<(), Error> {
|
|
|
|
let maybe_encrypted = self.encrypted.read().to_owned();
|
|
|
|
match maybe_encrypted {
|
|
|
|
Some(epk) => {
|
|
|
|
// Test password
|
|
|
|
let pk = epk.decrypt(old)?;
|
2023-08-17 21:55:51 +00:00
|
|
|
let epk = pk.export_encrypted(new, GLOBALS.storage.read_setting_log_n())?;
|
2023-02-10 22:32:37 +00:00
|
|
|
*self.encrypted.write() = Some(epk);
|
|
|
|
task::spawn(async move {
|
2023-08-18 22:32:56 +00:00
|
|
|
if let Err(e) = GLOBALS.signer.save().await {
|
2023-02-10 22:32:37 +00:00
|
|
|
tracing::error!("{}", e);
|
|
|
|
}
|
2023-06-24 23:01:55 +00:00
|
|
|
GLOBALS
|
|
|
|
.status_queue
|
|
|
|
.write()
|
|
|
|
.write("Passphrase changed.".to_owned())
|
2023-02-10 22:32:37 +00:00
|
|
|
});
|
|
|
|
Ok(())
|
|
|
|
}
|
2023-03-29 03:51:56 +00:00
|
|
|
_ => Err((ErrorKind::NoPrivateKey, file!(), line!()).into()),
|
2023-02-10 22:32:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-03 21:35:13 +00:00
|
|
|
pub fn generate_private_key(&self, pass: &str) -> Result<(), Error> {
|
2023-01-04 02:23:17 +00:00
|
|
|
let pk = PrivateKey::generate();
|
2023-08-17 21:55:51 +00:00
|
|
|
*self.encrypted.write() =
|
|
|
|
Some(pk.export_encrypted(pass, GLOBALS.storage.read_setting_log_n())?);
|
2023-02-03 21:35:13 +00:00
|
|
|
*self.public.write() = Some(pk.public_key());
|
|
|
|
*self.private.write() = Some(pk);
|
2023-01-05 08:43:16 +00:00
|
|
|
Ok(())
|
2022-12-30 02:13:34 +00:00
|
|
|
}
|
|
|
|
|
2022-12-27 06:45:57 +00:00
|
|
|
pub fn is_loaded(&self) -> bool {
|
2023-02-03 21:35:13 +00:00
|
|
|
self.encrypted.read().is_some() || self.private.read().is_some()
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_ready(&self) -> bool {
|
2023-02-03 21:35:13 +00:00
|
|
|
self.private.read().is_some()
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn public_key(&self) -> Option<PublicKey> {
|
2023-02-03 21:35:13 +00:00
|
|
|
*self.public.read()
|
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-02-03 21:35:13 +00:00
|
|
|
self.encrypted.read().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-02-03 21:35:13 +00:00
|
|
|
self.private.read().as_ref().map(|pk| pk.key_security())
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|
|
|
|
|
2023-04-24 06:27:56 +00:00
|
|
|
pub fn sign_preevent(
|
|
|
|
&self,
|
|
|
|
preevent: PreEvent,
|
|
|
|
pow: Option<u8>,
|
|
|
|
work_sender: Option<Sender<u8>>,
|
|
|
|
) -> Result<Event, Error> {
|
2023-02-03 21:35:13 +00:00
|
|
|
match &*self.private.read() {
|
2023-01-05 08:43:16 +00:00
|
|
|
Some(pk) => match pow {
|
2023-04-24 06:27:56 +00:00
|
|
|
Some(pow) => Ok(Event::new_with_pow(preevent, pk, pow, work_sender)?),
|
2023-01-05 13:29:13 +00:00
|
|
|
None => Ok(Event::new(preevent, pk)?),
|
2022-12-29 18:56:59 +00:00
|
|
|
},
|
2023-03-29 03:51:56 +00:00
|
|
|
_ => Err((ErrorKind::NoPrivateKey, file!(), line!()).into()),
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-04 02:23:17 +00:00
|
|
|
|
2023-02-03 21:35:13 +00:00
|
|
|
pub fn export_private_key_bech32(&self, pass: &str) -> Result<String, Error> {
|
2023-02-10 22:32:37 +00:00
|
|
|
let maybe_encrypted = self.encrypted.read().to_owned();
|
|
|
|
match maybe_encrypted {
|
2023-01-05 08:43:16 +00:00
|
|
|
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-03-30 21:37:07 +00:00
|
|
|
let output = pk.as_bech32_string();
|
2023-01-04 02:23:17 +00:00
|
|
|
|
|
|
|
// 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-08-17 21:55:51 +00:00
|
|
|
let epk = pk.export_encrypted(pass, GLOBALS.storage.read_setting_log_n())?;
|
2023-02-03 21:35:13 +00:00
|
|
|
*self.encrypted.write() = Some(epk);
|
|
|
|
*self.private.write() = Some(pk);
|
2023-01-04 02:23:17 +00:00
|
|
|
task::spawn(async move {
|
2023-08-18 22:32:56 +00:00
|
|
|
if let Err(e) = GLOBALS.signer.save().await {
|
2023-01-04 02:23:17 +00:00
|
|
|
tracing::error!("{}", e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Ok(output)
|
|
|
|
}
|
2023-03-29 03:51:56 +00:00
|
|
|
_ => Err((ErrorKind::NoPrivateKey, file!(), line!()).into()),
|
2023-01-04 02:23:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-03 21:35:13 +00:00
|
|
|
pub fn export_private_key_hex(&self, pass: &str) -> Result<String, Error> {
|
2023-02-10 22:32:37 +00:00
|
|
|
let maybe_encrypted = self.encrypted.read().to_owned();
|
|
|
|
match maybe_encrypted {
|
2023-01-05 08:43:16 +00:00
|
|
|
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-08-17 21:55:51 +00:00
|
|
|
let epk = pk.export_encrypted(pass, GLOBALS.storage.read_setting_log_n())?;
|
2023-02-03 21:35:13 +00:00
|
|
|
*self.encrypted.write() = Some(epk);
|
|
|
|
*self.private.write() = Some(pk);
|
2023-01-04 02:23:17 +00:00
|
|
|
task::spawn(async move {
|
2023-08-18 22:32:56 +00:00
|
|
|
if let Err(e) = GLOBALS.signer.save().await {
|
2023-01-04 02:23:17 +00:00
|
|
|
tracing::error!("{}", e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Ok(output)
|
|
|
|
}
|
2023-03-29 03:51:56 +00:00
|
|
|
_ => Err((ErrorKind::NoPrivateKey, file!(), line!()).into()),
|
2023-01-04 02:23:17 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-04 03:35:54 +00:00
|
|
|
|
2023-02-24 20:22:52 +00:00
|
|
|
pub fn delete_identity(&self) {
|
2023-02-03 22:38:02 +00:00
|
|
|
*self.private.write() = None;
|
|
|
|
*self.encrypted.write() = None;
|
|
|
|
*self.public.write() = None;
|
|
|
|
|
|
|
|
task::spawn(async move {
|
2023-08-18 22:32:56 +00:00
|
|
|
if let Err(e) = GLOBALS.signer.save().await {
|
2023-02-03 22:38:02 +00:00
|
|
|
tracing::error!("{}", e);
|
2023-01-04 03:35:54 +00:00
|
|
|
}
|
2023-02-03 22:38:02 +00:00
|
|
|
});
|
2023-01-04 03:35:54 +00:00
|
|
|
}
|
2023-02-22 23:44:36 +00:00
|
|
|
|
|
|
|
pub fn decrypt_message(&self, event: &Event) -> Result<String, Error> {
|
|
|
|
match &*self.private.read() {
|
|
|
|
Some(private) => Ok(event.decrypted_contents(private)?),
|
2023-03-29 03:51:56 +00:00
|
|
|
_ => Err((ErrorKind::NoPrivateKey, file!(), line!()).into()),
|
2023-02-22 23:44:36 +00:00
|
|
|
}
|
|
|
|
}
|
2023-08-21 20:17:27 +00:00
|
|
|
|
|
|
|
pub fn unwrap_giftwrap(&self, event: &Event) -> Result<Rumor, Error> {
|
|
|
|
match &*self.private.read() {
|
|
|
|
Some(private) => Ok(event.giftwrap_unwrap(private, false)?),
|
|
|
|
_ => Err((ErrorKind::NoPrivateKey, file!(), line!()).into()),
|
|
|
|
}
|
|
|
|
}
|
2023-08-22 21:41:54 +00:00
|
|
|
|
|
|
|
pub fn nip44_decrypt(
|
|
|
|
&self,
|
|
|
|
other: &PublicKey,
|
|
|
|
ciphertext: &str,
|
|
|
|
padded: bool,
|
|
|
|
) -> Result<Vec<u8>, Error> {
|
|
|
|
match &*self.private.read() {
|
|
|
|
Some(private) => Ok(private.nip44_decrypt(other, ciphertext, padded)?),
|
|
|
|
_ => Err((ErrorKind::NoPrivateKey, file!(), line!()).into()),
|
|
|
|
}
|
|
|
|
}
|
2022-12-27 06:45:57 +00:00
|
|
|
}
|