def __init__(self, key, compressed=True, testnet=False): if isinstance(key, str): try: key = bytes_from_hex(key) except: if is_wif_valid(key): key = PrivateKey(key) if isinstance(key, bytes): if len(key) == 32: key = PrivateKey(key, compressed=compressed, testnet=testnet) elif is_public_key_valid(key): public_key = key self.testnet = testnet self.compressed = True if len(key) == 33 else False else: raise TypeError("key invalid") if isinstance(key, PrivateKey): #: flag for testnet network private key (boolean) self.testnet = key.testnet #: flag for compressed type of corresponding public key (boolean) self.compressed = key.compressed public_key = private_to_public_key(key.key, compressed=key.compressed, hex=False) #: public key in bytes (bytes) self.key = public_key #: public key in HEX (string) self.hex = self.key.hex()
def sign_message(msg, private_key, hex=True): """ Sign message :param msg: message to sign bytes or HEX encoded string. :param private_key: private key (bytes, hex encoded string or WIF format) :param hex: (optional) If set to True return key in HEX format, by default is True. :return: DER encoded signature in bytes or HEX encoded string. """ if isinstance(msg, bytearray): msg = bytes(msg) if isinstance(msg, str): try: msg = bytes_from_hex(msg) except: pass if not isinstance(msg, bytes): raise TypeError("message must be a bytes or hex encoded string") if isinstance(private_key, bytearray): private_key = bytes(private_key) if isinstance(private_key, str): try: private_key = bytes_from_hex(private_key) except: if is_wif_valid(private_key): private_key = wif_to_private_key(private_key, hex=False) if not isinstance(private_key, bytes): raise TypeError( "private key must be a bytes, hex encoded string or in WIF format") signature = __secp256k1_ecdsa_sign__(msg, private_key) return signature.hex() if hex else signature
def is_wif_valid(wif): """ Check is private key in WIF format string is valid. :param wif: private key in WIF format string. :return: boolean. """ return __parent__.is_wif_valid(wif)
def sign_bitcoin_message(msg, wif, base64_encoded=True): if not is_wif_valid(wif): raise ValueError("invalid private key") compressed = True if wif[0] in ('K', 'L') else False msg = bitcoin_message(msg) signature = __secp256k1_ecdsa_sign__(msg, wif_to_private_key(wif, hex=False), 0) signature = bytes([signature[0] + 27 + int(compressed) * 4 ]) + signature[1:] if base64_encoded: return base64.b64encode(signature).decode() return signature
def __init__(self, key=None, compressed=True, testnet=False): if key is None: #: flag for compressed type of corresponding public key (boolean) self.compressed = compressed #: flag for testnet network private key (boolean) self.testnet = testnet #: private key in bytes (bytes) self.key = create_private_key(wif=False) #: private key in HEX (string) self.hex = self.key.hex() #: private key in WIF format (string) self.wif = private_key_to_wif(self.key, compressed, testnet) else: if isinstance(key, str): try: key = bytes_from_hex(key) except: pass if isinstance(key, bytes): if len(key) != 32: raise TypeError("private key invalid length") self.key = key self.compressed = compressed self.testnet = testnet self.hex = self.key.hex() self.wif = private_key_to_wif(self.key, compressed, testnet) return if not isinstance(key, str) or not is_wif_valid(key): raise TypeError("private key invalid") self.key = wif_to_private_key(key, hex=False) self.hex = self.key.hex() if key[0] in (MAINNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX, TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX): self.compressed = False else: self.compressed = True if key[0] in (TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX, TESTNET_PRIVATE_KEY_COMPRESSED_PREFIX): self.testnet = True else: self.testnet = False self.wif = private_key_to_wif(self.key, self.compressed, self.testnet)
def multisig(cls, n, m, public_key_list, testnet=False, witness_version=0): """ The class method for creating a multisig address. :param n: count of required signatures (max 15). :param m: count of total addresses of participants (max 15). :param list address_list: addresses list, allowed types: - bytes or HEX encoded private key - private key in WIF format - PrivateKey instance, - bytes or HEX encoded public key - PublicKey instance """ if n > 15 or m > 15 or n > m or n < 1 or m < 1: raise TypeError("invalid n of m maximum 15 of 15 multisig allowed") if len(public_key_list) != m: raise TypeError("invalid address list count") script = bytes([0x50 + n]) for a in list(public_key_list): if isinstance(a, str): try: a = bytes.fromhex(a) except: if is_wif_valid(a): a = private_to_public_key(a, hex=False) pass if isinstance(a, Address): a = a.public_key.key elif isinstance(a, PublicKey): a = a.key elif isinstance(a, PrivateKey): a = private_to_public_key(a.key) if not isinstance(a, bytes): raise TypeError("invalid public key list element") if len(a) == 32: a = private_to_public_key(a) if len(a) != 33: raise TypeError("invalid public key list element size") script += b"%s%s" % (int_to_var_int(len(a)), a) script += b"%s%s" % (bytes([0x50 + m]), OP_CHECKMULTISIG) return cls(script, testnet=testnet, witness_version=witness_version)
def sign_message(msg, private_key, hex=True): """ Sign message :param msg: message to sign bytes or HEX encoded string. :param private_key: private key (bytes, hex encoded string or WIF format) :param hex: (optional) If set to True return key in HEX format, by default is True. :return: DER encoded signature in bytes or HEX encoded string. """ if isinstance(msg, bytearray): msg = bytes(msg) if isinstance(msg, str): try: msg = bytes_from_hex(msg) except: pass if not isinstance(msg, bytes): raise TypeError("message must be a bytes or hex encoded string") if isinstance(private_key, bytearray): private_key = bytes(private_key) if isinstance(private_key, str): try: private_key = bytes_from_hex(private_key) except: if is_wif_valid(private_key): private_key = wif_to_private_key(private_key, hex=False) if not isinstance(private_key, bytes): raise TypeError("private key must be a bytes, hex encoded string or in WIF format") raw_sig = ffi.new('secp256k1_ecdsa_signature *') signed = secp256k1_ecdsa_sign(ECDSA_CONTEXT_SIGN, raw_sig, msg, private_key, ffi.NULL, ffi.NULL) if not signed: raise RuntimeError("secp256k1 error") len_sig = 74 output = ffi.new('unsigned char[%d]' % len_sig) outputlen = ffi.new('size_t *', len_sig) res = secp256k1_ecdsa_signature_serialize_der(ECDSA_CONTEXT_SIGN, output, outputlen, raw_sig) if not res: raise RuntimeError("secp256k1 error") signature = bytes(ffi.buffer(output, outputlen[0])) return signature.hex() if hex else signature
def test_is_wif_valid(): assert is_wif_valid( "L49obCXV7fGz2YRzLCSJgeZBYmGeBbKPT7xiehUeYX2S4URkPFZX") == True assert is_wif_valid( "5KPPLXhtga99qqMceRo4Z6LXV3Kx6a9hRx3ez2U7EwP5KZfy2Wf") == True assert is_wif_valid( "5KPPLXhtga99qqMcWRo4Z6LXV3Kx6a9hRx3ez2U7EwP5KZfy2Wf") == False assert is_wif_valid( "93A1vGXSGoDHotruGmgyRgtV8hgfFjgtmtuc4epcag886W9d44L") == True assert is_wif_valid( "cUWo47XLYiyFByuFicFS3y4FAza3r3R5XA7Bm7wA3dgSKDYox7h6") == True assert is_wif_valid("YiyByuFicFS3y4FAza3r3R5XA7Bm7wA3dgSKDYox7h6") == False assert is_wif_valid( "5KPPLXhtga99qqMcWRo4Z6LXV3Kx6a9hRx3ez2U7EwP5K333Zfy2Wf") == False assert is_wif_valid( "L49obCXV7fGz2YRzLCSJgeZqqBYmGeBbKPT7xiehUeYX2S4URkPFZX") == False assert is_wif_valid( "cUWo47XLYtga99qqMcWRo4Z6LXV3Kx6a9hRx3ez2U7EwP5KZfy2Wf") == False assert is_wif_valid( "cUWo47XLYiyFByuFi§FS3y4FAza3r3R5XA7Bm7wA3dgSKDY12oxQ7h9") == False assert is_wif_valid(22) == False