NUT-XX: Deterministic Keypairs #384
No reviewers
Labels
No labels
breaking change
bug
documentation
enhancement
needs discussion
needs implementation
new nut
ready
wallet-only
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo-admin/nuts!384
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "robwoodgate/nut-xx-deterministic-keypairs"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
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_NUT11for NUT-11 P2PK keysCashu_KDF_HMAC_SHA256_NUT20for NUT-20 quote locking keysTest 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
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.
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.
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.
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
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.