def sign_data(cls, pri_key: bytes, digest_bytes: bytes): privkey = PrivateKey(pri_key) # we expect to have a private key as bytes. unhexlify it before passing. item = cls() item.pub_key = privkey.public_key.format() item.digest_bytes = digest_bytes item.sig_ser = privkey.sign(digest_bytes, hasher=None) return item
async def sign_message(cls, pri_key: bytes, message): # we expect to have a private key as bytes. unhexlify it before passing privkey = PrivateKey(pri_key) item = cls() message = VarInt(len(message)).encode() + message item.pub_key = privkey.public_key.format() # item.digest_bytes = digest_bytes item.sig_ser = privkey.sign(MESSAGE_TEMPLATE.format(message).encode()) return item
class Wallet(BaseWallet): HD_PATH = "44'/714'/0'/0/0" def __init__(self, private_key, env: Optional[BinanceEnvironment] = None): super().__init__(env) self._private_key = private_key self._pk = PrivateKey(bytes.fromhex(self._private_key)) self._public_key = self._pk.public_key.format(compressed=True) self._address = address_from_public_key(self._public_key, self._env.hrp) @classmethod def create_random_wallet( cls, language: MnemonicLanguage = MnemonicLanguage.ENGLISH, env: Optional[BinanceEnvironment] = None): """ Create wallet with random mnemonic code """ m = Mnemonic(language.value) phrase = m.generate() return cls.create_wallet_from_mnemonic(phrase, env=env) @classmethod def create_wallet_from_mnemonic(cls, mnemonic: str, env: Optional[BinanceEnvironment] = None): """ Create wallet with random mnemonic code """ seed = Mnemonic.to_seed(mnemonic) new_wallet = Bip32Wallet.from_master_secret(seed=seed, network='BTC') child = new_wallet.get_child_for_path(Wallet.HD_PATH) return cls(child.get_private_key_hex().decode(), env=env) @property def private_key(self): return self._private_key def sign_message(self, msg_bytes): # check if ledger wallet sig = self._pk.sign(msg_bytes) return serialize_compact(raw_sig=der_to_cdata(der=sig))
class BaseKey: """This class represents a point on the elliptic curve secp256k1 and provides all necessary cryptographic functionality. You shouldn't use this class directly. :param wif: A private key serialized to the Wallet Import Format. If the argument is not supplied, a new private key will be created. The WIF compression flag will be adhered to, but the version byte is disregarded. Compression will be used by all new keys. :type wif: ``str`` :raises TypeError: If ``wif`` is not a ``str``. """ def __init__(self, wif=None): if wif: if isinstance(wif, str): private_key_bytes, compressed, version = wif_to_bytes(wif) self._pk = ECPrivateKey(private_key_bytes) elif isinstance(wif, ECPrivateKey): self._pk = wif compressed = True else: raise TypeError('Wallet Import Format must be a string.') else: self._pk = ECPrivateKey() compressed = True self._public_point = None self._public_key = self._pk.public_key.format(compressed=compressed) @property def public_key(self): """The public point serialized to bytes.""" return self._public_key @property def public_point(self): """The public point (x, y).""" if self._public_point is None: self._public_point = Point(*public_key_to_coords(self._public_key)) return self._public_point def sign(self, data): """Signs some data which can be verified later by others using the public key. :param data: The message to sign. :type data: ``bytes`` :returns: A signature compliant with BIP-62. :rtype: ``bytes`` """ return self._pk.sign(data) def verify(self, signature, data): """Verifies some data was signed by this private key. :param signature: The signature to verify. :type signature: ``bytes`` :param data: The data that was supposedly signed. :type data: ``bytes`` :rtype: ``bool`` """ return self._pk.public_key.verify(signature, data) def pub_to_hex(self): """:rtype: ``str`` """ return bytes_to_hex(self.public_key) def to_hex(self): """:rtype: ``str``""" return self._pk.to_hex() def to_bytes(self): """:rtype: ``bytes``""" return self._pk.secret def to_der(self): """:rtype: ``bytes``""" return self._pk.to_der() def to_pem(self): """:rtype: ``bytes``""" return self._pk.to_pem() def to_int(self): """:rtype: ``int``""" return self._pk.to_int() def is_compressed(self): """Returns whether or not this private key corresponds to a compressed public key. :rtype: ``bool`` """ return True if len(self.public_key) == 33 else False def __eq__(self, other): return self.to_int() == other.to_int()