v0.0.10 - Fix: derive variable-path roles using the concrete role_path from the request, not the template
This commit is contained in:
Generated
+3
-3
@@ -1446,7 +1446,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nostr-core"
|
||||
version = "0.0.2"
|
||||
version = "0.0.3"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"base64",
|
||||
@@ -1468,7 +1468,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nostr-nips"
|
||||
version = "0.0.2"
|
||||
version = "0.0.3"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"block-modes",
|
||||
@@ -1490,7 +1490,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nsigner"
|
||||
version = "0.0.8"
|
||||
version = "0.0.9"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"chacha20poly1305",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nsigner"
|
||||
version = "0.0.9"
|
||||
version = "0.0.10"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
description = "Attended Nostr signing daemon — Rust port of n_signer"
|
||||
|
||||
+12
-5
@@ -357,12 +357,19 @@ fn handle_nostr_verb(
|
||||
return make_error_response(id, RpcError::MNEMONIC_NOT_LOADED);
|
||||
}
|
||||
|
||||
// Ensure key is derived
|
||||
// Ensure key is derived. For variable-path roles, use the concrete
|
||||
// path supplied by the client; for fixed-path roles, use the stored
|
||||
// template.
|
||||
if !role.derived {
|
||||
if let Err(_) = ctx
|
||||
.key_store
|
||||
.derive_one(ctx.role_table, ctx.mnemonic, role_index)
|
||||
{
|
||||
let has_variable = role.has_variable_path();
|
||||
let result = if has_variable && sel.has_role_path {
|
||||
ctx.key_store
|
||||
.derive_one_with_path(ctx.role_table, ctx.mnemonic, role_index, &sel.role_path)
|
||||
} else {
|
||||
ctx.key_store
|
||||
.derive_one(ctx.role_table, ctx.mnemonic, role_index)
|
||||
};
|
||||
if let Err(_) = result {
|
||||
return make_error_response(
|
||||
id,
|
||||
RpcError {
|
||||
|
||||
@@ -111,6 +111,40 @@ impl KeyStore {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Derive key for a role using a concrete path (substituting the
|
||||
/// variable index into the template). Used for variable-path roles
|
||||
/// where the client supplies the full concrete `role_path`.
|
||||
pub fn derive_one_with_path(
|
||||
&mut self,
|
||||
table: &mut RoleTable,
|
||||
mnemonic: &MnemonicState,
|
||||
role_index: usize,
|
||||
concrete_path: &str,
|
||||
) -> Result<(), NsignerError> {
|
||||
if !mnemonic.is_loaded() {
|
||||
return Err(NsignerError::MnemonicNotLoaded);
|
||||
}
|
||||
|
||||
let phrase = mnemonic.phrase().ok_or(NsignerError::MnemonicNotLoaded)?;
|
||||
let role = table
|
||||
.entries
|
||||
.get_mut(role_index)
|
||||
.ok_or(NsignerError::InvalidInput)?;
|
||||
|
||||
role.derived = false;
|
||||
role.pubkey_hex.clear();
|
||||
|
||||
let dk = derive_for_role(concrete_path, role, phrase)?;
|
||||
role.pubkey_hex = dk.pubkey_hex.clone();
|
||||
role.derived = true;
|
||||
|
||||
if self.keys.len() <= role_index {
|
||||
self.keys.resize_with(role_index + 1, || None);
|
||||
}
|
||||
self.keys[role_index] = Some(dk);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get the derived private key for a role (by table index).
|
||||
pub fn get_private_key(&self, role_index: usize) -> Option<&[u8]> {
|
||||
self.keys.get(role_index)?.as_ref().map(|dk| dk.private_key.as_slice())
|
||||
|
||||
+1
-1
@@ -31,4 +31,4 @@ pub mod error;
|
||||
pub use error::NsignerError;
|
||||
|
||||
/// Version string (matches C NSIGNER_VERSION).
|
||||
pub const VERSION: &str = "v0.0.9";
|
||||
pub const VERSION: &str = "v0.0.10";
|
||||
|
||||
Reference in New Issue
Block a user