|
|
|
|
|
import base64 |
|
|
from nacl.signing import VerifyKey |
|
|
from nacl.exceptions import BadSignatureError |
|
|
|
|
|
MESSAGE_PREFIX = "CHECKIN:" |
|
|
|
|
|
class SignatureError(Exception): |
|
|
pass |
|
|
|
|
|
|
|
|
_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" |
|
|
_INDEXES = {c: i for i, c in enumerate(_ALPHABET)} |
|
|
|
|
|
def _b58decode(s: str) -> bytes: |
|
|
if not s: |
|
|
return b"" |
|
|
num = 0 |
|
|
for ch in s: |
|
|
try: |
|
|
num = num * 58 + _INDEXES[ch] |
|
|
except KeyError: |
|
|
raise ValueError("invalid base58 character") from None |
|
|
|
|
|
if num == 0: |
|
|
full = b"\x00" |
|
|
else: |
|
|
byte_len = (num.bit_length() + 7) // 8 |
|
|
full = num.to_bytes(byte_len, "big") |
|
|
|
|
|
pad = len(s) - len(s.lstrip("1")) |
|
|
return b"\x00" * pad + full.lstrip(b"\x00") |
|
|
|
|
|
def verify_signature(address_base58: str, signature_b64: str, message: str) -> None: |
|
|
try: |
|
|
pubkey_bytes = _b58decode(address_base58) |
|
|
sig_bytes = base64.b64decode(signature_b64) |
|
|
vk = VerifyKey(pubkey_bytes) |
|
|
vk.verify(message.encode("utf-8"), sig_bytes) |
|
|
except (ValueError, BadSignatureError) as e: |
|
|
raise SignatureError(str(e)) |
|
|
|