From e39eaa632db16c0d2abdd78710467639e74ddcf4 Mon Sep 17 00:00:00 2001 From: Padreug Date: Tue, 26 May 2026 00:32:39 +0200 Subject: [PATCH] startKey: decode bech32 nsec to hex before constructing NDKPrivateKeySigner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NDK 2.8.1's NDKPrivateKeySigner constructor forwards its arg straight to nostr-tools getPublicKey() which requires 32-byte hex/bytes/bigint and throws on bech32 input. Every key loaded through startKey (i.e. every key created via create_new_key, plus boot-time reloads of any plain-nsec entries in the config) was failing silently with the nostr-tools type error. The try/catch caught the throw and returned without loading the key, so the bunker would happily report create_new_key as successful, the key would persist encrypted on disk, but the runtime keystore would not have a signer for it. NIP-46 connect / sign_event against any admin-provisioned target therefore silently timed out from the client side — blocking essentially every signing flow. Sister bug to #5 (getKeys iterator) in a different code path. The fix matches the existing pattern in create_new_key.ts:16: hexpk = nip19.decode(nsec).data as string; Verified against the local spike harness: create_new_key now loads the target into runtime; get_keys returns the new entry (assuming #5 is patched separately for the iterator path). Fixes #8. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/daemon/run.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/daemon/run.ts b/src/daemon/run.ts index 262a150..6637986 100644 --- a/src/daemon/run.ts +++ b/src/daemon/run.ts @@ -230,8 +230,14 @@ class Daemon { if (nsec.startsWith('nsec1')) { try { - const key = new NDKPrivateKeySigner(nsec); - hexpk = key.privateKey!; + // NDK 2.8.1's NDKPrivateKeySigner constructor passes its + // arg straight to nostr-tools getPublicKey() which requires + // 32-byte hex / bytes / bigint, not bech32. Without this + // decode, every key created via create_new_key fails to + // load with the nostr-tools getPublicKey type error, so + // the bunker can never sign for any target it provisions. + // See aiolabs/nsecbunkerd#8. + hexpk = nip19.decode(nsec).data as string; } catch(e) { console.error(`Error loading key ${name}:`, e); return