v0.0.18 - Fix sign-event JSON escaping and variable-path role key caching (per-path re-derivation)
This commit is contained in:
Generated
+1
-1
@@ -2207,7 +2207,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signer"
|
name = "signer"
|
||||||
version = "0.0.17"
|
version = "0.0.18"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"chacha20poly1305",
|
"chacha20poly1305",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "signer"
|
name = "signer"
|
||||||
version = "0.0.17"
|
version = "0.0.18"
|
||||||
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"
|
||||||
|
|||||||
+16
-4
@@ -359,9 +359,16 @@ fn handle_nostr_verb(
|
|||||||
|
|
||||||
// Ensure key is derived. For variable-path roles, use the concrete
|
// Ensure key is derived. For variable-path roles, use the concrete
|
||||||
// path supplied by the client; for fixed-path roles, use the stored
|
// path supplied by the client; for fixed-path roles, use the stored
|
||||||
// template.
|
// template. Variable-path roles are re-derived whenever the requested
|
||||||
if !role.derived {
|
// path differs from the currently-derived one (the cache is per-path,
|
||||||
let has_variable = role.has_variable_path();
|
// not per-role).
|
||||||
|
let has_variable = role.has_variable_path();
|
||||||
|
let needs_derive = if has_variable && sel.has_role_path {
|
||||||
|
role.derived_path.as_deref() != Some(sel.role_path.as_str())
|
||||||
|
} else {
|
||||||
|
!role.derived
|
||||||
|
};
|
||||||
|
if needs_derive {
|
||||||
let result = if has_variable && sel.has_role_path {
|
let result = if has_variable && sel.has_role_path {
|
||||||
ctx.key_store
|
ctx.key_store
|
||||||
.derive_one_with_path(ctx.role_table, ctx.mnemonic, role_index, &sel.role_path)
|
.derive_one_with_path(ctx.role_table, ctx.mnemonic, role_index, &sel.role_path)
|
||||||
@@ -414,7 +421,12 @@ fn handle_nostr_verb(
|
|||||||
None => return make_error_response(id, RpcError::INVALID_PARAMS),
|
None => return make_error_response(id, RpcError::INVALID_PARAMS),
|
||||||
};
|
};
|
||||||
match ctx.key_store.sign_event(role_index, event_json) {
|
match ctx.key_store.sign_event(role_index, event_json) {
|
||||||
Ok(signed) => make_success_response(id, &format!("\"{}\"", signed)),
|
// The signed event is itself JSON; serialize it as a proper
|
||||||
|
// JSON string value so embedded quotes are escaped.
|
||||||
|
Ok(signed) => {
|
||||||
|
let wrapped = serde_json::to_string(&signed).unwrap_or_else(|_| "\"\"".into());
|
||||||
|
make_success_response(id, &wrapped)
|
||||||
|
}
|
||||||
Err(_) => make_error_response(id, RpcError::INVALID_PARAMS),
|
Err(_) => make_error_response(id, RpcError::INVALID_PARAMS),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,10 +133,12 @@ impl KeyStore {
|
|||||||
|
|
||||||
role.derived = false;
|
role.derived = false;
|
||||||
role.pubkey_hex.clear();
|
role.pubkey_hex.clear();
|
||||||
|
role.derived_path = None;
|
||||||
|
|
||||||
let dk = derive_for_role(concrete_path, role, phrase)?;
|
let dk = derive_for_role(concrete_path, role, phrase)?;
|
||||||
role.pubkey_hex = dk.pubkey_hex.clone();
|
role.pubkey_hex = dk.pubkey_hex.clone();
|
||||||
role.derived = true;
|
role.derived = true;
|
||||||
|
role.derived_path = Some(concrete_path.to_string());
|
||||||
|
|
||||||
if self.keys.len() <= role_index {
|
if self.keys.len() <= role_index {
|
||||||
self.keys.resize_with(role_index + 1, || None);
|
self.keys.resize_with(role_index + 1, || None);
|
||||||
|
|||||||
+1
-1
@@ -31,4 +31,4 @@ pub mod error;
|
|||||||
pub use error::SignerError;
|
pub use error::SignerError;
|
||||||
|
|
||||||
/// Version string (matches C NSIGNER_VERSION).
|
/// Version string (matches C NSIGNER_VERSION).
|
||||||
pub const VERSION: &str = "v0.0.17";
|
pub const VERSION: &str = "v0.0.18";
|
||||||
|
|||||||
@@ -137,6 +137,8 @@ pub struct RoleEntry {
|
|||||||
pub pubkey_hex: String,
|
pub pubkey_hex: String,
|
||||||
/// 1 if pubkey_hex has been populated.
|
/// 1 if pubkey_hex has been populated.
|
||||||
pub derived: bool,
|
pub derived: bool,
|
||||||
|
/// The concrete path the key was last derived for (variable-path roles).
|
||||||
|
pub derived_path: Option<String>,
|
||||||
/// Inclusive lower bound for %d; -1 = fixed path (no variable).
|
/// Inclusive lower bound for %d; -1 = fixed path (no variable).
|
||||||
pub path_range_lo: i32,
|
pub path_range_lo: i32,
|
||||||
/// Inclusive upper bound; == path_range_lo for single.
|
/// Inclusive upper bound; == path_range_lo for single.
|
||||||
@@ -162,6 +164,7 @@ impl Default for RoleEntry {
|
|||||||
role_path: String::new(),
|
role_path: String::new(),
|
||||||
pubkey_hex: String::new(),
|
pubkey_hex: String::new(),
|
||||||
derived: false,
|
derived: false,
|
||||||
|
derived_path: None,
|
||||||
path_range_lo: -1,
|
path_range_lo: -1,
|
||||||
path_range_hi: -1,
|
path_range_hi: -1,
|
||||||
path_default_index: -1,
|
path_default_index: -1,
|
||||||
|
|||||||
Reference in New Issue
Block a user