-
Notifications
You must be signed in to change notification settings - Fork 85
NUT-06: require signed mint info #416
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,7 +19,8 @@ With the mint's response being of the form `GetInfoResponse`: | |
| ```json | ||
| { | ||
| "name": "Bob's Cashu mint", | ||
| "pubkey": "0283bf290884eed3a7ca2663fc0260de2e2064d6b355ea13f98dec004b7a7ead99", | ||
| "pubkey": "02d53b2972b5fcfda2861d937a40bd4dd4170718276e35ac82a84fa60c3a365046", | ||
| "signature": "efed7369effde640baee2f089681a57fd559e45ebf5bbf9a1f2200bb4137291453b617d7955f0e47426be39f21c4253e92bac8ada04f730021a3e313465334d9", | ||
| "version": "Nutshell/0.15.0", | ||
| "description": "The short mint description", | ||
| "description_long": "A description that can be a long piece of text.", | ||
|
|
@@ -87,8 +88,11 @@ With the mint's response being of the form `GetInfoResponse`: | |
| } | ||
| ``` | ||
|
|
||
| For reproducibility, the example uses the mint seed `NUT-06 example mint seed` and zero-filled auxiliary randomness for BIP-340 signing. | ||
|
|
||
| - (optional) `name` is the name of the mint and should be recognizable. | ||
| - (optional) `pubkey` is the hex pubkey of the mint. | ||
| - (mandatory) `pubkey` is the mint's identity public key as a lowercase hex-encoded, 33-byte compressed secp256k1 public key. | ||
| - (mandatory) `signature` is the lowercase hex encoding of the mint's 64-byte BIP-340 Schnorr signature on the response payload, constructed as specified below. | ||
| - (optional) `version` is the implementation name and the version of the software running on this mint separated with a slash "/". | ||
| - (optional) `description` is a short description of the mint that can be shown in the wallet next to the mint's name. | ||
| - (optional) `description_long` is a long description that can be shown in an additional field. | ||
|
|
@@ -100,6 +104,30 @@ With the mint's response being of the form `GetInfoResponse`: | |
| - (optional) `tos_url` is the URL pointing to the Terms of Service of the mint. | ||
| - (optional) `nuts` indicates each NUT specification that the mint supports and its settings. The settings are defined in each NUT separately. | ||
|
|
||
| ## Mint identity key | ||
|
|
||
| The mint identity key is deterministically derived from the mint seed. Given the exact `seed` string used by the mint: | ||
|
|
||
| 1. Encode `seed` as UTF-8. | ||
| 2. Compute `secret_key = SHA256(seed)`. | ||
| 3. Interpret `secret_key` as a 32-byte big-endian integer. It **MUST** be a valid secp256k1 secret key in the range `1..n-1`, where `n` is the order of the secp256k1 curve. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens if it does not fit? Maybe introduce a counter to the HMAC above and retry with ctr = 1, 2, 3, etc.?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. probability it doesn't fit should be roughly
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| 4. Compute `pubkey = secret_key * G` and serialize it in 33-byte compressed SEC1 format. | ||
|
|
||
| The mint **MUST** return this public key in `GetInfoResponse.pubkey`. | ||
|
|
||
| ## Signature | ||
|
|
||
| The mint **MUST** sign every `GetInfoResponse` with the identity key corresponding to `pubkey`. To construct and sign the message: | ||
|
|
||
| 1. Start with the complete `GetInfoResponse` JSON object. | ||
| 2. Remove the top-level `signature` and `time` members. The `time` member is excluded so that an otherwise unchanged response has a stable signed payload. | ||
| 3. Canonicalize the resulting JSON object using the JSON Canonicalization Scheme (JCS) defined in [RFC 8785]. Encode the canonical JSON as UTF-8. | ||
| 4. Compute the SHA-256 hash of those bytes. | ||
| 5. Sign the 32-byte hash using [BIP-340] Schnorr over secp256k1. | ||
| 6. Encode the resulting 64-byte signature as lowercase hexadecimal and return it in `GetInfoResponse.signature`. | ||
|
|
||
| Wallets **MUST** reject the response if `pubkey` or `signature` is missing or malformed, or if BIP-340 verification fails. For BIP-340 verification, wallets use the 32-byte x-coordinate of the compressed `pubkey`. | ||
|
|
||
| With curl: | ||
|
|
||
| ```bash | ||
|
|
@@ -119,3 +147,5 @@ curl -X GET https://mint.host:3338/v1/info | |
| [10]: 10.md | ||
| [11]: 11.md | ||
| [12]: 12.md | ||
| [RFC 8785]: https://www.rfc-editor.org/rfc/rfc8785 | ||
| [BIP-340]: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki | ||
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.
we should use HMAC-SHA256 construction like we do in other NUTS (e.g. 12 or 13)