Files
nutshell/cashu/core/nuts/nut20.py
lollerfirst d98d166df1 Support NUT-XX (signatures on quotes) for mint and wallet side (#670)
* nut-19 sign mint quote

* ephemeral key for quote

* `mint` adjustments + crypto/nut19.py

* wip: mint side working

* fix import

* post-merge fixups

* more fixes

* make format

* move nut19 to nuts directory

* `key` -> `privkey` and `pubkey`

* make format

* mint_info method for nut-19 support

* fix tests imports

* fix signature missing positional argument + fix db migration format not correctly escaped + pass in NUT-19 keypair to `request_mint` `request_mint_with_callback`

* make format

* fix `get_invoice_status`

* rename to xx

* nutxx -> nut20

* mypy

* remove `mint_quote_signature_required` as per spec

* wip edits

* clean up

* fix tests

* fix deprecated api tests

* fix redis tests

* fix cache tests

* fix regtest mint external

* fix mint regtest

* add test without signature

* test pubkeys in quotes

* wip

* add compat

---------

Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
2024-12-15 00:39:53 +01:00

42 lines
1.2 KiB
Python

from hashlib import sha256
from typing import List
from ..base import BlindedMessage
from ..crypto.secp import PrivateKey, PublicKey
def generate_keypair() -> tuple[str, str]:
privkey = PrivateKey()
assert privkey.pubkey
pubkey = privkey.pubkey
return privkey.serialize(), pubkey.serialize(True).hex()
def construct_message(quote_id: str, outputs: List[BlindedMessage]) -> bytes:
serialized_outputs = b"".join([o.B_.encode("utf-8") for o in outputs])
msgbytes = sha256(quote_id.encode("utf-8") + serialized_outputs).digest()
return msgbytes
def sign_mint_quote(
quote_id: str,
outputs: List[BlindedMessage],
private_key: str,
) -> str:
privkey = PrivateKey(bytes.fromhex(private_key), raw=True)
msgbytes = construct_message(quote_id, outputs)
sig = privkey.schnorr_sign(msgbytes, None, raw=True)
return sig.hex()
def verify_mint_quote(
quote_id: str,
outputs: List[BlindedMessage],
public_key: str,
signature: str,
) -> bool:
pubkey = PublicKey(bytes.fromhex(public_key), raw=True)
msgbytes = construct_message(quote_id, outputs)
sig = bytes.fromhex(signature)
return pubkey.schnorr_verify(msgbytes, sig, None, raw=True)