diff --git a/06.md b/06.md index 315bb4da..6d0fa222 100644 --- a/06.md +++ b/06.md @@ -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. +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