uploader-bot/app/core/_crypto/signer.py

59 lines
1.8 KiB
Python

from app.core._utils.b58 import b58encode, b58decode
try:
import nacl.encoding
import nacl.signing
import nacl.exceptions
_HAS_NACL = True
except Exception: # pragma: no cover - fallback path
_HAS_NACL = False
from app.core._utils.hash import blake3_digest
if _HAS_NACL:
class Signer:
def __init__(self, seed: bytes):
if len(seed) != 32:
raise ValueError("Seed must be 32 bytes")
self.signing_key = nacl.signing.SigningKey(seed)
self.verify_key = self.signing_key.verify_key
def sign(self, data_bytes: bytes) -> str:
signed_message = self.signing_key.sign(data_bytes)
signature = signed_message.signature
return b58encode(signature).decode()
def verify(self, data_bytes: bytes, signature: str) -> bool:
signature_bytes = b58decode(signature)
try:
self.verify_key.verify(data_bytes, signature_bytes)
return True
except nacl.exceptions.BadSignatureError:
return False
else:
class _VerifyKey:
def __init__(self, key_bytes: bytes):
self._key_bytes = key_bytes
def encode(self) -> bytes:
return self._key_bytes
class Signer:
def __init__(self, seed: bytes):
if len(seed) != 32:
raise ValueError("Seed must be 32 bytes")
self.seed = seed
self.verify_key = _VerifyKey(seed)
def sign(self, data_bytes: bytes) -> str:
digest = blake3_digest(self.seed + data_bytes)
return b58encode(digest).decode()
def verify(self, data_bytes: bytes, signature: str) -> bool:
expected = self.sign(data_bytes)
return expected == signature