diff --git a/lnbits/core/models.py b/lnbits/core/models.py index 23c111f3a..4655c256c 100644 --- a/lnbits/core/models.py +++ b/lnbits/core/models.py @@ -1,4 +1,5 @@ import json +import hmac import hashlib from ecdsa import SECP256k1, SigningKey # type: ignore from typing import List, NamedTuple, Optional, Dict @@ -35,10 +36,12 @@ class Wallet(NamedTuple): def balance(self) -> int: return self.balance_msat // 1000 - @property - def lnurlauth_key(self) -> SigningKey: + def lnurlauth_key(self, domain: str) -> SigningKey: + hashing_key = hashlib.sha256(self.id.encode("utf-8")).digest() + linking_key = hmac.digest(hashing_key, domain.encode("utf-8"), "sha256") + return SigningKey.from_string( - hashlib.sha256(self.id.encode("utf-8")).digest(), + linking_key, curve=SECP256k1, hashfunc=hashlib.sha256, ) diff --git a/lnbits/core/services.py b/lnbits/core/services.py index 511bf1e92..991e278b3 100644 --- a/lnbits/core/services.py +++ b/lnbits/core/services.py @@ -160,8 +160,10 @@ async def redeem_lnurl_withdraw(wallet_id: str, res: LnurlWithdrawResponse, memo async def perform_lnurlauth(callback: str) -> Optional[LnurlErrorResponse]: - k1 = unhexlify(parse_qs(urlparse(callback).query)["k1"][0]) - key = g.wallet.lnurlauth_key + cb = urlparse(callback) + + k1 = unhexlify(parse_qs(cb.query)["k1"][0]) + key = g.wallet.lnurlauth_key(cb.netloc) def int_to_bytes_suitable_der(x: int) -> bytes: """for strict DER we need to encode the integer with some quirks""" diff --git a/lnbits/core/views/api.py b/lnbits/core/views/api.py index 61b3854a9..fd4a1159f 100644 --- a/lnbits/core/views/api.py +++ b/lnbits/core/views/api.py @@ -310,7 +310,9 @@ async def api_lnurlscan(code: str): if url.is_login: params.update(kind="auth") params.update(callback=url.url) # with k1 already in it - params.update(pubkey=g.wallet.lnurlauth_key.verifying_key.to_string("compressed").hex()) + + lnurlauth_key = g.wallet.lnurlauth_key(domain) + params.update(pubkey=lnurlauth_key.verifying_key.to_string("compressed").hex()) else: async with httpx.AsyncClient() as client: r = await client.get(url.url, timeout=40)