Skip to content

NUT-XX: Deterministic Keypairs#384

Closed
robwoodgate wants to merge 1 commit into
cashubtc:mainfrom
robwoodgate:nut-xx-deterministic-keypairs
Closed

NUT-XX: Deterministic Keypairs#384
robwoodgate wants to merge 1 commit into
cashubtc:mainfrom
robwoodgate:nut-xx-deterministic-keypairs

Conversation

@robwoodgate

@robwoodgate robwoodgate commented May 29, 2026

Copy link
Copy Markdown
Collaborator

Supersedes

Summary

Adds a new NUT specifying HMAC-SHA256 derivation of secp256k1 keypairs from the wallet seed, for use as locking keys in spending conditions (NUT-11 P2PK) and as quote locking keys (NUT-20). Each application gets a distinct DST and an independent counter:

  • Cashu_KDF_HMAC_SHA256_NUT11 for NUT-11 P2PK keys
  • Cashu_KDF_HMAC_SHA256_NUT20 for NUT-20 quote locking keys

Test vectors use the canonical NUT-13 mnemonic and publish the first five compressed pubkeys per domain.

This PR supersedes #331 and #373. Both PRs bolt BIP-32 derivation guidance into existing NUTs; this consolidates them into one optional NUT using the HMAC-SHA256 KDF style that NUT-13 v2 already established for the secrets / blinding-factor case.

Why HMAC-SHA256 over BIP-32

  1. Performance. HMAC is faster in all scenarios, and BIP-32 needs careful handling to avoid performance tanking.
Pattern                                          Cost/key   vs HMAC
HMAC NUT-XX                                       ~165 µs    1.0×
BIP-32 parent-cached, HDKey.publicKey             ~172 µs    1.0×    natural restore-loop code
BIP-32 master-cached, full path per derive        ~862 µs    5.2×    natural single-derive code
BIP-32 cold, no caching                          ~1216 µs    7.4×    worst case
  1. Alignment with NUT-13 v2. The spec already chose HMAC-SHA256 with modular reduction for keyset-bound derivation. Using the same primitive for non-keyset-bound P2PK and quote keys keeps one KDF across the spec rather than mixing two (BIP-32 here, HMAC there) and lines up with the direction NUT-13 v2 was already moving.

  2. No BIP-32 features actually apply. P2PK and quote keys are derived wallet-side from a hot seed. BIP-32's design targets hardware-wallet path traversal, chain-code propagation, and non-hardened xpub export. None of these apply: there is no hardware wallet in the loop, no derivation tree to walk, no xpub-export workflow shipping anywhere in the ecosystem. The HD-tree structure pays complexity for benefits Cashu never collects.

  3. The BIP-32 xpub watch-only argument is inconsistent with Cashu's privacy model. BIP-32's non-hardened terminal step allows xpub-based enumeration in theory, but using it for P2PK / NUT-20 keys requires (a) a NUT-shaped query-by-pubkey API that does not exist, (b) wallet xpub-export workflows that no one ships, and (c) a lookup API that does not gain mint-side correlation info by linking a user's many candidate pubkeys into one query. Bitcoin tolerates the equivalent because the chain is already public; Cashu mints actively gain correlation info from each lookup, which the protocol's privacy guarantees specifically try to prevent.

  4. Smaller dependency surface. Wallets need BIP-39 (mnemonic → seed bytes) regardless of derivation choice. BIP-32 derivation adds a second library (@scure/bip32, python-bip32, similar) carrying path parsing, hardened vs non-hardened logic, and chain-code handling that the wallet never uses. HMAC-SHA256 derivation drops the need for that second dep once legacy keysets are removed.

Why separate Domains?

Simply because quotes can be churned and disposed of more often, so a restore based on P2PK locking keys would potentially face larger gaps in a mixed domain scenario. It also helps prevent key collisions (privacy leak) between quotes and locked proofs in cases where counter management goes askew (eg multiple wallets using same seed).

Implementations

  • cdk
  • nutmix
  • coco
  • cashu-ts
  • nutshell
  • macadamia

@robwoodgate

Copy link
Copy Markdown
Collaborator Author

Closing as:

a) there are live implementations using BIP-32 derivations for both use cases right now
b) the flexibility for future use of XPUBs in quote watching services (eg npub.cash) is desirable

@robwoodgate robwoodgate closed this Jun 9, 2026
@github-project-automation github-project-automation Bot moved this from Backlog to Done in nuts Jun 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants