Skip to content
This repository has been archived by the owner on Feb 3, 2025. It is now read-only.

Commit

Permalink
Allow overriding derived nsec
Browse files Browse the repository at this point in the history
  • Loading branch information
benthecarman committed Jan 16, 2024
1 parent 57592de commit c7eacd8
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 3 deletions.
8 changes: 8 additions & 0 deletions mutiny-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ use crate::{
};
use crate::{nostr::NostrManager, utils::sleep};
use ::nostr::key::XOnlyPublicKey;
use ::nostr::prelude::SecretKey;
use ::nostr::{Event, EventBuilder, JsonUtil, Keys, Kind, Metadata, Tag};
use async_lock::RwLock;
use bdk_chain::ConfirmationTime;
Expand Down Expand Up @@ -395,6 +396,7 @@ pub struct MutinyWalletConfig {

pub struct MutinyWalletBuilder<S: MutinyStorage> {
xprivkey: ExtendedPrivKey,
nsec_override: Option<SecretKey>,
storage: S,
glue_db: Option<GlueDB>,
config: Option<MutinyWalletConfig>,
Expand All @@ -413,6 +415,7 @@ impl<S: MutinyStorage> MutinyWalletBuilder<S> {
MutinyWalletBuilder::<S> {
xprivkey,
storage,
nsec_override: None,
glue_db: None,
config: None,
session_id: None,
Expand All @@ -438,6 +441,10 @@ impl<S: MutinyStorage> MutinyWalletBuilder<S> {
self
}

pub fn with_nsec(&mut self, nsec: SecretKey) {
self.nsec_override = Some(nsec)
}

pub fn with_glue_db(&mut self, glue_db: GlueDB) {
self.glue_db = Some(glue_db);
}
Expand Down Expand Up @@ -515,6 +522,7 @@ impl<S: MutinyStorage> MutinyWalletBuilder<S> {
// create nostr manager
let nostr = Arc::new(NostrManager::from_mnemonic(
self.xprivkey,
self.nsec_override,
self.storage.clone(),
logger.clone(),
stop.clone(),
Expand Down
17 changes: 14 additions & 3 deletions mutiny-core/src/nostr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,13 @@ impl<S: MutinyStorage> NostrManager<S> {
Ok(None)
}

/// Decrypts a DM using the primary key
pub fn decrypt_dm(&self, pubkey: XOnlyPublicKey, message: &str) -> Result<String, MutinyError> {
let secret = self.primary_key.secret_key().expect("must have");
let decrypted = decrypt(&secret, &pubkey, message)?;
Ok(decrypted)
}

/// Derives the client and server keys for Nostr Wallet Connect given a profile index
/// The left key is the client key and the right key is the server key
pub(crate) fn derive_nwc_keys<C: Signing>(
Expand Down Expand Up @@ -1135,14 +1142,18 @@ impl<S: MutinyStorage> NostrManager<S> {
/// Creates a new NostrManager
pub fn from_mnemonic(
xprivkey: ExtendedPrivKey,
nsec_override: Option<SecretKey>,
storage: S,
logger: Arc<MutinyLogger>,
stop: Arc<AtomicBool>,
) -> Result<Self, MutinyError> {
let context = Secp256k1::new();

// generate the default primary key
let primary_key = Self::derive_nostr_key(&context, xprivkey, 0, None, None)?;
// use provided nsec, otherwise generate it from seed
let primary_key = match nsec_override {
Some(nsec) => Keys::new(nsec),
None => Self::derive_nostr_key(&context, xprivkey, 0, None, None)?,
};

// get from storage
let profiles: Vec<Profile> = storage.get_data(NWC_STORAGE_KEY)?.unwrap_or_default();
Expand Down Expand Up @@ -1216,7 +1227,7 @@ mod test {

let stop = Arc::new(AtomicBool::new(false));

NostrManager::from_mnemonic(xprivkey, storage, logger, stop).unwrap()
NostrManager::from_mnemonic(xprivkey, None, storage, logger, stop).unwrap()
}

#[test]
Expand Down
2 changes: 2 additions & 0 deletions mutiny-core/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use uuid::Uuid;

pub const KEYCHAIN_STORE_KEY: &str = "bdk_keychain";
pub const MNEMONIC_KEY: &str = "mnemonic";
pub const NSEC_KEY: &str = "nsec";
pub(crate) const NEED_FULL_SYNC_KEY: &str = "needs_full_sync";
pub const NODES_KEY: &str = "nodes";
pub const FEDERATIONS_KEY: &str = "federations";
Expand All @@ -34,6 +35,7 @@ pub const LAST_DM_SYNC_TIME_KEY: &str = "last_dm_sync_time";
fn needs_encryption(key: &str) -> bool {
match key {
MNEMONIC_KEY => true,
NSEC_KEY => true,
str if str.starts_with(CHANNEL_MANAGER_KEY) => true,
_ => false,
}
Expand Down
7 changes: 7 additions & 0 deletions mutiny-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ impl MutinyWallet {
let mut mw_builder = MutinyWalletBuilder::new(xprivkey, storage).with_config(config);
mw_builder.with_session_id(logger.session_id.clone());
let inner = mw_builder.build().await?;

Ok(MutinyWallet { mnemonic, inner })
}

Expand Down Expand Up @@ -1567,6 +1568,12 @@ impl MutinyWallet {
Ok(())
}

/// Decrypts a DM using the primary key
pub fn decrypt_dm(&self, pubkey: String, message: String) -> Result<String, MutinyJsError> {
let pubkey = parse_npub(&pubkey)?;
Ok(self.inner.nostr.decrypt_dm(pubkey, &message)?)
}

/// Resets the scorer and network graph. This can be useful if you get stuck in a bad state.
#[wasm_bindgen]
pub async fn reset_router(&self) -> Result<(), MutinyJsError> {
Expand Down

0 comments on commit c7eacd8

Please sign in to comment.