Skip to content

Latest commit

 

History

History
190 lines (138 loc) · 6.03 KB

20.md

File metadata and controls

190 lines (138 loc) · 6.03 KB

NUT-20: Signature on Mint Quote

optional

depends on: NUT-04


This NUT defines signature-based authentication for mint quote redemption. When requesting a mint quote, clients provide a public key. The mint will then require a valid signature from the corresponding secret key to process the mint operation.

Caution

NUT-04 mint quotes without a public key can be minted by anyone who knows the mint quote id without providing a signature.

Mint quote

To request a mint quote, the wallet of Alice makes a POST /v1/mint/quote/{method} request where method is the payment method requested. We present an example with the method being bolt11 here.

POST https://mint.host:3338/v1/mint/quote/bolt11

The wallet of Alice includes the following PostMintQuoteBolt11Request data in its request:

{
  "amount": <int>,
  "unit": <str_enum["sat"]>,
  "description": <str>, // Optional
  "pubkey": <str> // Optional <-- New
}

with the requested amount,unit, and description according to NUT-04.

pubkey is the public key that will be required for signature verification during the minting operation. The mint will only mint ecash after receiving a valid signature from the corresponding private key in the subsequent PostMintRequest.

Important

Privacy: To prevent the mint from being able to link multiple mint quotes, wallets SHOULD generate a unique public key for each mint quote request.

The mint Bob then responds with a PostMintQuoteBolt11Response:

{
  "quote": <str>,
  "request": <str>,
  "state": <str_enum[STATE]>,
  "expiry": <int>,
  "pubkey": <str> // Optional <-- New
}

The response is the same as in NUT-04 except for pubkey which has been provided by the wallet in the previous request.

Example

Request of Alice with curl:

curl -X POST http://localhost:3338/v1/mint/quote/bolt11 -d '{"amount": 10, "unit": "sat", "pubkey": "03d56ce4e446a85bbdaa547b4ec2b073d40ff802831352b8272b7dd7a4de5a7cac"}' -H "Content-Type: application/json"

Response of Bob:

{
  "quote": "9d745270-1405-46de-b5c5-e2762b4f5e00",
  "request": "lnbc100n1pj4apw9...",
  "state": "UNPAID",
  "expiry": 1701704757,
  "pubkey": "03d56ce4e446a85bbdaa547b4ec2b073d40ff802831352b8272b7dd7a4de5a7cac"
}

Signing the mint request

Message aggregation

To provide a signature for a mint request, the owner of the signing public keys must concatenate the quote ID quote in PostMintQuoteBolt11Response and the B_ fields of all BlindedMessages in the PostMintBolt11Request (i.e., the outputs, see NUT-00) to a single message string in the order they appear in the PostMintRequest. This concatenated string is then hashed and signed (see Signature scheme).

Note

Concatenating the quote ID and the outputs into a single message prevents maliciously replacing the outputs.

If a request has n outputs, the message to sign becomes:

msg_to_sign =  quote || B_0 || ... || B_(n-1)

Where || denotes concatenation, quote is the UTF-8 quote id in PostMintQuoteBolt11Response, and each B_n is a UTF-8 encoded hex string of the outputs in the PostMintBolt11Request.

Signature scheme

To mint a quote where a public key was provided, the wallet includes a signature on msg_to_sign in the PostMintBolt11Request. We use a BIP340 Schnorr signature on the SHA-256 hash of the message to sign as defined above.

Minting tokens

After requesting a mint quote and paying the request, the wallet proceeds with minting new tokens by calling the POST /v1/mint/{method} endpoint where method is the payment method requested (here bolt11).

POST https://mint.host:3338/v1/mint/bolt11

The wallet Alice includes the following PostMintBolt11Request data in its request

{
  "quote": <str>,
  "outputs": <Array[BlindedMessage]>,
  "signature": <str|null> <-- New
}

with the quote being the quote ID from the previous step and outputs being BlindedMessages as in NUT-04.

signature is the signature on the msg_to_sign which is the concatenated quote id and the outputs as defined above.

The mint responds with a PostMintBolt11Response as in NUT-04 if all validations are successful.

Example

Request of Alice with curl:

curl -X POST https://mint.host:3338/v1/mint/bolt11 -H "Content-Type: application/json" -d \
'{
  "quote": "9d745270-1405-46de-b5c5-e2762b4f5e00",
  "outputs": [
    {
      "amount": 8,
      "id": "009a1f293253e41e",
      "B_": "035015e6d7ade60ba8426cefaf1832bbd27257636e44a76b922d78e79b47cb689d"
    },
    {
      "amount": 2,
      "id": "009a1f293253e41e",
      "B_": "0288d7649652d0a83fc9c966c969fb217f15904431e61a44b14999fabc1b5d9ac6"
    }
  ],
  "signature": "d9be080b33179387e504bb6991ea41ae0dd715e28b01ce9f63d57198a095bccc776874914288e6989e97ac9d255ac667c205fa8d90a211184b417b4ffdd24092"

}'

Response of Bob:

{
  "signatures": [
    {
      "id": "009a1f293253e41e",
      "amount": 2,
      "C_": "0224f1c4c564230ad3d96c5033efdc425582397a5a7691d600202732edc6d4b1ec"
    },
    {
      "id": "009a1f293253e41e",
      "amount": 8,
      "C_": "0277d1de806ed177007e5b94a8139343b6382e472c752a74e99949d511f7194f6c"
    }
  ]
}

Errors

If the wallet user Alice does not include a signature on the PostMintBolt11Request but did include a pubkey in the PostMintBolt11QuoteRequest then Bob MUST respond with an error. Alice CAN repeat the request with a valid signature.

See Error Codes:

  • 20008: Mint quote with pubkey but no valid signature provided for mint request.
  • 20009: Mint quote requires pubkey but none given or invalid pubkey.

Settings

The settings for this NUT indicate the support for requiring a signature before minting. They are part of the info response of the mint (NUT-06) which in this case reads

{
  "20": {
    "supported": <bool>,
  }
}