Source code for dposlib.ark.sig

# -*- encoding:utf-8 -*-

"""
Advanced signature manipulation. It is the recomended module to manually issue
signatures for ark blockchain and forks.

Variables:
  - ``privateKey`` (:class:`str`): hexlified private key
  - ``publicKey`` (:class:`str`):  hexlified compressed - encoded public key
  - ``message`` (:class:`str`):    message to sign as string
"""

from dposlib.ark import secp256k1
from dposlib.ark.secp256k1 import ecdsa, schnorr
from dposlib.util.bin import unhexlify


[docs]class Signature(list): r = property( lambda cls: list.__getitem__(cls, 0), None, None, "Signature part #1" ) s = property( lambda cls: list.__getitem__(cls, 1), None, None, "Signature part #2" ) der = property( lambda cls: cls._der_getter(), lambda cls, v: setattr(cls, "_der", v), None, "Return DER encoded signature as bytes sequence" ) raw = property( lambda cls: cls._raw_getter(), lambda cls, v: setattr(cls, "_raw", v), None, "Return RAW Encode signature as bytes sequence" ) def __init__(self, *rs): list.__init__(self, [int(e) for e in rs]) def __repr__(self): return "<secp256k1 signature:\n r:%064x\n s:%064x\n>" % tuple(self) def _der_getter(cls): if not hasattr(cls, "_der"): setattr(cls, "_der", secp256k1.der_from_sig(*cls)) return getattr(cls, "_der") def _raw_getter(cls): if not hasattr(cls, "_raw"): setattr( cls, "_raw", secp256k1.bytes_from_int(cls[0]) + secp256k1.bytes_from_int(cls[1]) ) return getattr(cls, "_raw")
[docs] def ecdsa_verify(self, message, publicKey): """ Check if public key match message signature according to ``ECDSA`` scheme. Args: message (:class:`str`): message to verify publicKey (:class:`str`): public key Returns: :class:`bool`: True if match """ return ecdsa.verify( secp256k1.hash_sha256(message), secp256k1.Point.decode(unhexlify(publicKey)).encode(), self.der )
[docs] def b410_schnorr_verify(self, message, publicKey): """ Check if public key match message signature according to `Bcrypto 4.10 schnorr <https://github.com/bcoin-org/bcrypto/blob/v4.1.\ 0/lib/js/schnorr.js>`_ scheme. Args: message (:class:`str`): message to verify publicKey (:class:`str`): public key Returns: :class:`bool`: True if match """ return schnorr.bcrypto410_verify( secp256k1.hash_sha256(message), secp256k1.Point.decode(unhexlify(publicKey)).encode(), self.raw )
[docs] def schnorr_verify(self, message, publicKey): """ Check if public key match message signature according to `BIP schnorr <https://github.com/sipa/bips/blob/bip-schnorr/bip-schnor\ r.mediawiki>`_ scheme. Args: message (:class:`str`): message to verify publicKey (:class:`str`): public key Returns: :class:`bool`: True if match """ return schnorr.verify( secp256k1.hash_sha256(message), schnorr.bytes_from_point( secp256k1.Point.decode(unhexlify(publicKey)) ), self.raw )
[docs] @staticmethod def from_raw(raw): """ Decode signature from RAW encoded bytes sequence. Arguments: raw (:class:`bytes`): encoded signature Returns: :class:`Signature`: signature """ length = len(raw) // 2 sig = Signature( secp256k1.int_from_bytes(raw[:length]), secp256k1.int_from_bytes(raw[length:]), ) sig._raw = raw return sig
[docs] @staticmethod def from_der(der): """ Decode signature from DER encoded bytes sequence. Arguments: der (:class:`bytes`): encoded signature Returns: :class:`Signature`: signature """ sig = Signature(*secp256k1.sig_from_der(der)) sig._der = der return sig
[docs] @staticmethod def ecdsa_sign(message, privateKey, canonical=True): """ Generate message signature according to ``ECDSA`` scheme using a random nonce. Args: message (:class:`str`): message to verify privateKey (:class:`str`): private key canonical (:class:`bool`): canonalize signature Returns: :class:`Signature`: signature """ return Signature.from_der( ecdsa.sign( secp256k1.hash_sha256(message), unhexlify(privateKey), canonical=canonical ) )
[docs] @staticmethod def ecdsa_rfc6979_sign(message, privateKey, canonical=True): """ Generate message signature according to ``ECDSA`` scheme using a deterministic nonce (RFC-6976). Args: message (:class:`str`): message to verify privateKey (:class:`str`): private key canonical (:class:`bool`): canonalize signature Returns: :class:`Signature`: signature """ return Signature.from_der( ecdsa.rfc6979_sign( secp256k1.hash_sha256(message), unhexlify(privateKey), canonical=canonical ) )
[docs] @staticmethod def b410_schnorr_sign(message, privateKey): """ Generate message signature according to `Bcrypto 4.10 schnorr <https://github.com/bcoin-org/bcrypto/blob/v4.1.\ 0/lib/js/schnorr.js>`_ scheme. Args: message (:class:`str`): message to verify privateKey (:class:`str`): private key Returns: :class:`Signature`: signature """ return Signature.from_raw( schnorr.bcrypto410_sign( secp256k1.hash_sha256(message), unhexlify(privateKey) ) )
[docs] @staticmethod def schnorr_sign(message, privateKey): """ Generate message signature according to `BIP schnorr <https://github.com/sipa/bips/blob/bip-schnorr/bip-schnor\ r.mediawiki>`_ scheme. Args: message (:class:`str`): message to verify privateKey (:class:`str`): private key Returns: :class:`Signature`: signature """ return Signature.from_raw( schnorr.sign( secp256k1.hash_sha256(message), unhexlify(privateKey) ) )