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.
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.
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"
}
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
.
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.
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.
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"
}
]
}
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 withpubkey
but no validsignature
provided for mint request.20009
: Mint quote requirespubkey
but none given or invalidpubkey
.
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>,
}
}