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]]
|
[[package]]
|
||||||
name = "nostr-core"
|
name = "nostr-core"
|
||||||
version = "0.0.2"
|
version = "0.0.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"base64",
|
"base64",
|
||||||
@@ -1468,7 +1468,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-nips"
|
name = "nostr-nips"
|
||||||
version = "0.0.2"
|
version = "0.0.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"block-modes",
|
"block-modes",
|
||||||
@@ -1490,7 +1490,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nsigner"
|
name = "nsigner"
|
||||||
version = "0.0.8"
|
version = "0.0.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"chacha20poly1305",
|
"chacha20poly1305",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nsigner"
|
name = "nsigner"
|
||||||
version = "0.0.9"
|
version = "0.0.10"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "Attended Nostr signing daemon — Rust port of n_signer"
|
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);
|
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 !role.derived {
|
||||||
if let Err(_) = ctx
|
let has_variable = role.has_variable_path();
|
||||||
.key_store
|
let result = if has_variable && sel.has_role_path {
|
||||||
.derive_one(ctx.role_table, ctx.mnemonic, role_index)
|
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(
|
return make_error_response(
|
||||||
id,
|
id,
|
||||||
RpcError {
|
RpcError {
|
||||||
|
|||||||
@@ -111,6 +111,40 @@ impl KeyStore {
|
|||||||
Ok(())
|
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).
|
/// Get the derived private key for a role (by table index).
|
||||||
pub fn get_private_key(&self, role_index: usize) -> Option<&[u8]> {
|
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())
|
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;
|
pub use error::NsignerError;
|
||||||
|
|
||||||
/// Version string (matches C NSIGNER_VERSION).
|
/// 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