Deterministic pay to public key generation #331
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!331
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "lescuer97/p2pk_recovery"
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?
Adds a standard way to generate keys for wallets to generate private keys for usage in P2PK operations.
@ -42,0 +47,4 @@- 129373': Purpose picked for P2PK derivation.- 10': Account for generating private keys for usage in P2PK.- {counter}: Incrementing counter encoded as an unsigned 64-bit integer in big-endian format.is this using BIP32? Should be more clear.
@ -39,6 +39,18 @@ The HMAC-SHA256 KDF is built as the following:2. `hmac_digest = HMAC_SHA256(seed, message)`, where `HMAC_SHA256` is the [hash-based message authentication code](https://en.wikipedia.org/wiki/HMAC) using SHA-256 as the hashing algorithm.not using per-keyset derivation. are we sure about this?
@ -39,6 +39,18 @@ The HMAC-SHA256 KDF is built as the following:2. `hmac_digest = HMAC_SHA256(seed, message)`, where `HMAC_SHA256` is the [hash-based message authentication code](https://en.wikipedia.org/wiki/HMAC) using SHA-256 as the hashing algorithm.yes, because it's for locking up proofs it should be more general
Keysets v2 is moving away from a BIP32 style derivation scheme, and using a KDF instead. Would it not be better to align with this approach, eg using a domain separator like
b"Cashu_KDF_HMAC_SHA256_P2PK"orb"Cashu_P2PK_v1"?Also, I assume the counter is separate to the one used for secrets/blinded messages. If so, this should be made clearer.
Finally, related to @a1denvalu3's comment - what happens if the derived key is out of range? Should it be discarded (as per BIP-32) or reduced modulo N?
@ -42,0 +47,4 @@- 129373': Purpose picked for P2PK derivation.- 10': Account for generating private keys for usage in P2PK.- {counter}: Incrementing counter encoded as an unsigned 64-bit integer in big-endian format.yes, I'll make it clearer
Good point 👍
@robwoodgate @a1denvalu3 just changed the wording around the NUT so it's a bit more clear.
Suggestion below to tighten the language, otherwise ACK.
Suggestion to tighten language, otherwise concept ACK
@ -42,0 +49,4 @@- 10': Account for generating private keys for usage in P2PK.- {counter}: Incrementing counter encoded as an unsigned 64-bit integer in big-endian format.This will allow wallets to swap proof that are still locked to a public key during a restore process.@ -39,6 +39,18 @@ The HMAC-SHA256 KDF is built as the following:2. `hmac_digest = HMAC_SHA256(seed, message)`, where `HMAC_SHA256` is the [hash-based message authentication code](https://en.wikipedia.org/wiki/HMAC) using SHA-256 as the hashing algorithm.Can you explain why the last element is not hardened?
Is the xpub of
m/129372'/10'/0'/0'ever shared anywhere?If it is not shared, then instead of hardening it, I propose we change the scheme to
Cashu_KDF_HMAC_SHA256(same as used in Keyset v2, since BIP32 used in Keyset v1 is deprecated).@ -39,6 +39,18 @@ The HMAC-SHA256 KDF is built as the following:2. `hmac_digest = HMAC_SHA256(seed, message)`, where `HMAC_SHA256` is the [hash-based message authentication code](https://en.wikipedia.org/wiki/HMAC) using SHA-256 as the hashing algorithm.We are following what Bitcoin does when it comes to key derivation for locking.
there is no reason right now for sharing an XPUB but can't guarantee that in the future.
The reason we want to use bip32 is because Bip32 is specifically made for this case.The
Cashu_KDF_HMAC_SHA256scheme is used because of aggregation to avoid certain issues when generating the keyset id.This keys are never aggregated and are use individually.
@ -39,6 +39,18 @@ The HMAC-SHA256 KDF is built as the following:2. `hmac_digest = HMAC_SHA256(seed, message)`, where `HMAC_SHA256` is the [hash-based message authentication code](https://en.wikipedia.org/wiki/HMAC) using SHA-256 as the hashing algorithm.No, it's not. BIP32 usecase is when you need to share a pubkey for a certain key subtree. Unless you need this requirement, going with
Cashu_KDF_HMAC_SHA256is simply faster and easier.@ -39,6 +39,18 @@ The HMAC-SHA256 KDF is built as the following:2. `hmac_digest = HMAC_SHA256(seed, message)`, where `HMAC_SHA256` is the [hash-based message authentication code](https://en.wikipedia.org/wiki/HMAC) using SHA-256 as the hashing algorithm.@prusnak if we get the option to query the mint for quotes connected to a pubkey via NUT-20, public key derivation would become more meaningful than it currently is. I can not think of a usecase right now, but with this, extended keys would be able to essentially create a watch-only wallet of a wallets quotes, without spending from it.
So either we think about proper usecases for this for 2 weeks and go with HMAC if we can't find any, or we take the performance L, go with BIP32 and hope someone finds a usecase some day in the future
@ -39,6 +39,18 @@ The HMAC-SHA256 KDF is built as the following:2. `hmac_digest = HMAC_SHA256(seed, message)`, where `HMAC_SHA256` is the [hash-based message authentication code](https://en.wikipedia.org/wiki/HMAC) using SHA-256 as the hashing algorithm.if we want to have a watch-only wallet eventually which should show p2pk tokens too, this seems like a good use-case. ACK
@ -39,6 +39,18 @@ The HMAC-SHA256 KDF is built as the following:2. `hmac_digest = HMAC_SHA256(seed, message)`, where `HMAC_SHA256` is the [hash-based message authentication code](https://en.wikipedia.org/wiki/HMAC) using SHA-256 as the hashing algorithm.Think coco and cdk are not using 129372
@ -39,6 +39,18 @@ The HMAC-SHA256 KDF is built as the following:2. `hmac_digest = HMAC_SHA256(seed, message)`, where `HMAC_SHA256` is the [hash-based message authentication code](https://en.wikipedia.org/wiki/HMAC) using SHA-256 as the hashing algorithm.3. `secret = hmac_digest` and `blinding_factor = hmac_digest % N`.#### P2PK DerivationI wonder of this should just be a new nut would be easier to track who supports it and think we should avoid changing existing nuts where we can especially widely supported ones like nut13. Though it would be a very small nut.
@ -39,6 +39,18 @@ The HMAC-SHA256 KDF is built as the following:2. `hmac_digest = HMAC_SHA256(seed, message)`, where `HMAC_SHA256` is the [hash-based message authentication code](https://en.wikipedia.org/wiki/HMAC) using SHA-256 as the hashing algorithm.3. `secret = hmac_digest` and `blinding_factor = hmac_digest % N`.#### P2PK DerivationI thought about the same but I don't think it's needed in this case. Maybe if we start making more deterministic generation we would move it there.
@ -39,6 +39,18 @@ The HMAC-SHA256 KDF is built as the following:2. `hmac_digest = HMAC_SHA256(seed, message)`, where `HMAC_SHA256` is the [hash-based message authentication code](https://en.wikipedia.org/wiki/HMAC) using SHA-256 as the hashing algorithm.Thank you, I forgot about changing this I also changed the tests to the correct ones.
Honestly, I think we should use NUT-13's v2 HMAC-SHA256 KDF rather than introducing a new BIP32 path.
The KDF defined for v2 exists precisely because BIP32 path traversal is really expensive, and a P2PK private key only needs a uniform secp256k1 scalar, which the same single-HMAC + single-subtraction reduction (bias ~2⁻¹²⁸) gives you directly.
Quick numbers from a pure-JS noble benchmark (cashu-ts, per counter):
In a restore situation, the wallet can cache the parent path derivation and get close to parity with HMAC, but if using just a cached master key (for regular wallet ops), the slowdown is 5x. In other words, BIP-32 needs careful handling to avoid performance tanking.
There is also no special need for BIP32 here: P2PK keys are derived wallet-side from a hot seed, so there's no hardware-wallet or chain-code benefit.
Mirroring the v2 construction — something like:
would keep a single KDF across all of NUT-13 and lines up with the direction v2 was already moving.
@ -39,6 +39,18 @@ The HMAC-SHA256 KDF is built as the following:2. `hmac_digest = HMAC_SHA256(seed, message)`, where `HMAC_SHA256` is the [hash-based message authentication code](https://en.wikipedia.org/wiki/HMAC) using SHA-256 as the hashing algorithm.The use case is double hypothetical - relying on wallets to export XPUBS and an endpoint that doesn't exist. BIP32 is a slowdown vs HMAC, a performance L to soak up forever.
And any lookup by pubkey would either be limited (pubkeys are SUPPOSED to be single use for privacy) or would likely allow the mint to link pubkeys (eg in a batch lookup scenario).
I have proposed a HMAC-SHA256 KDF derived alternative, which would close this PR
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.