-
Notifications
You must be signed in to change notification settings - Fork 71
Keyset ID V2 #182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Keyset ID V2 #182
Conversation
|
Thank you! Please:
|
|
Should we maybe add a paragraph to this that describes the way the Mint handles proofs with Short IDv2? Alternatively a substitution could be performed by the client, but this means that it has to request |
|
Quite honest, I am not sure such small change justifies creating a new keyset version and the headache attached to it. Maybe we should keep this improvement in mind and apply it together with some future proposal that changes something significant? |
|
@prusnak this was suggested to enable wallets to store proofs without referencing mint URLs. @thesimplekid @ok300 do you think this is still necessary? |
The longer keyset ids to reduce the chance of a collision and the keyset expiry are things we've talked about awhile and I would like to see, I think it makes sense to move forward with this. I cant think of anything else we wanted to include that we should hold this for, but if there is I am open to it. |
I agree. This is exactly the kind of change I was mentioning when I said to "justify" creating a new keyset version. |
|
A few NITs, otherwise it's an ACK from me: The specified behavior is a bit ambiguous in 2 places.
This doesn't say if it's the long or short ID. It should probably say "short ID" or rename the variable to
This makes it sound preferable, but optional to use the shorter |
|
@davidcaseria I think it would be better if the long keyset ID was 32-bytes:
|
|
CDK draft: cashubtc/cdk#702 |
Why? |
|
Re: Derivation and invalid results (k > N or k == 0) Usually you would
I think this should be our default for all derivations too. It requires implementations to bubble up that error to the application layer to properly increment counters (e.g. counter 2 is requested, but produces an invalid result, so counter 3 will be consumed), but that is a sound way to handle this edge case |
In an ideal world, we would reduce mod N, which then reduces the failure to But if we cannot do this reliably in all implementations, it may be "prudent" to throw for values > N, specifically in the case of SHA256 digests, as it removes the miniscule risk of some implementations not being able to derive blinding factors for certain hashes... which Murphy's law says will be the most expensive mistake possible. Maybe that's why BIP32 specified as discard and retry, not reduce %N. Really wish mod n wasn't an issue, the single subtract is so elegant. |
|
Cross referencing the NUT-00 conventions PR, which currently warns against doing MOD N. #322 Will need to update this if we proceed with the the proposed blinding scheme here. |
|
I think all points should be addressed now. |
|
@callebtc - the changes are looking great. I think we are there! |
|
should we add a couple test vectors for the preimage? |
robwoodgate
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK @ 6e785b2
Epic work, I think this is a much stronger spec now.
| sorted_keys = dict(sorted(keys.items())) | ||
| keyset_id_bytes = b",".join( | ||
| [f"{k}:{v.serialize()}".encode("utf-8") for k, v in sorted_keys.items()] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this code it occurred to me, that this works fine only if there are no duplicate entries in key values of keys. And this seems to be the case since keys is expected to be a dict. (otherwise the keys would need to be a list of tuples instead of a dict).
However, does the keyset spec disallow multiple public keys with the same denomination? I don't think we should allow this, but in that case, we should add this limitation to the keyset spec. Or is such limitation already in the keyset spec?
| if input_fee_ppk is not None and input_fee_ppk != 0: | ||
| keyset_id_bytes += f"|input_fee_ppk:{input_fee_ppk}".encode("utf-8") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's worth noting that including the fee in the ID now means that mints cannot change the fee of past keysets. This to some extent reduces the mint's ability to dynamically change fees in response to a DoS, for example, as the first operation will still have the lower fee, only the second operation will incur the higher fee of the new keyset. I am not necessarily against this change; I just think we should be aware of it and make sure we are making this tradeoff intentionally.
Co-authored-by: asmo <[email protected]>
Summary
This PR introduces Keyset ID v2 (version byte
01) and updates the spec + vectors accordingly.The Keyset ID v2 derivation is designed to be unambiguous across keysets by hashing both the key amounts and keyset metadata.
Changes
Keyset ID v2 (NUT-02)
01(version byte) +SHA256(preimage)(32 bytes)ifield): first 8 bytes of the full keyset ID (hex string length 16)Derivation preimage (v2)
Preimage is constructed as UTF-8 bytes in this exact order:
"{amount}:{pubkey_hex}"amount:pubkey_hexpair with a comma (,)"|unit:{unit}"input_fee_ppkis present and non-zero, append"|input_fee_ppk:{input_fee_ppk}"input_fee_ppkis omitted /null/0, it MUST be omitted from the preimage.final_expiryis present and non-zero, append"|final_expiry:{final_expiry}"Then
id = "01" + sha256(preimage).hexdigest().Deterministic secrets (NUT-13)
00: legacy BIP32 derivation01: HMAC-SHA256 derivationmessage = b"Cashu_KDF_HMAC_SHA256" || keyset_id_bytes || counter_k_bytes || derivation_type_byteSpec/test-vector updates in this PR
tests/02-tests.mdV2 keyset IDs to match the new preimage rules (includinginput_fee_ppkbehavior).02.mdexamples to use fully specified vector keysets (no ellipses), so IDs are verifiable.tests/13-tests.mdV2 secrets/r vectors to match the updated V2 keyset ID.tools/regenerate_vectors.pyto regenerate/sanity-check the affected vectors.Implementation Status