def __init__(self, H): assert isinstance(H, bytes) if not seclib: try: Hpoint = ser_to_point(H) except: raise ValueError("H could not be parsed") HGpoint = Hpoint + ecdsa.SECP256k1.generator if HGpoint == ecdsa.ellipticcurve.INFINITY: # this happens if H = -G raise InsecureHPoint(-1) self._ecdsa_H = Hpoint self._ecdsa_HG = HGpoint self.H = point_to_ser(Hpoint, comp=False) self.HG = point_to_ser(HGpoint, comp=False) else: ctx = seclib.ctx H_buf = create_string_buffer(64) res = seclib.secp256k1_ec_pubkey_parse(ctx, H_buf, H, c_size_t(len(H))) if not res: raise ValueError('H could not be parsed by the secp256k1 library') self._seclib_H = H_buf.raw G = point_to_ser(ecdsa.SECP256k1.generator, comp=False) G_buf = create_string_buffer(64) res = seclib.secp256k1_ec_pubkey_parse(ctx, G_buf, G, c_size_t(len(G))) assert res, "G point should always deserialize without issue" HG_buf = create_string_buffer(64) publist = (c_void_p*2)(*(cast(x, c_void_p) for x in (H_buf, G_buf))) res = seclib.secp256k1_ec_pubkey_combine(ctx, HG_buf, publist, 2) if res != 1: # this happens if H = -G raise InsecureHPoint(-1) self._seclib_HG = HG_buf.raw # now serialize H and HG as uncompressed bytes serpoint = create_string_buffer(65) sersize = c_size_t(65) res = seclib.secp256k1_ec_pubkey_serialize(ctx, serpoint, byref(sersize), H_buf, secp256k1.SECP256K1_EC_UNCOMPRESSED) assert res == 1 assert sersize.value == 65 self.H = serpoint.raw res = seclib.secp256k1_ec_pubkey_serialize(ctx, serpoint, byref(sersize), HG_buf, secp256k1.SECP256K1_EC_UNCOMPRESSED) assert res == 1 assert sersize.value == 65 self.HG = serpoint.raw
def __init__(self, master_privkey): G = generator_secp256k1 order = G.order() # make two derived private keys (integers between 1 and p-1 inclusive) # hard derivation (irreversible): x = int.from_bytes(hashlib.sha512(b'Split1' + master_privkey.to_bytes(32, 'big')).digest(), 'big') self.priv1 = 1 + (x % (order-1)) x = int.from_bytes(hashlib.sha512(b'Split2' + master_privkey.to_bytes(32, 'big')).digest(), 'big') self.priv2 = 1 + (x % (order-1)) # soft derivation (reversible): #self.priv1 = (0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * master_privkey) % order #self.priv2 = (0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb * master_privkey) % order # generate compressed pubkeys self.pub1ser = point_to_ser(self.priv1 * G, True) self.pub2ser = point_to_ser(self.priv2 * G, True) self.keypairs = { self.pub1ser.hex() : (self.priv1.to_bytes(32, 'big'), True), self.pub2ser.hex() : (self.priv2.to_bytes(32, 'big'), True), } # params from ABC 0.18.2 unit tests cds_sig = bytes.fromhex('30440220256c12175e809381f97637933ed6ab97737d263eaaebca6add21bced67fd12a402205ce29ecc1369d6fc1b51977ed38faaf41119e3be1d7edfafd7cfaf0b6061bd07') cds_msg = b'' cds_pubkey = bytes.fromhex('038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508') self.redeemscript = joinbytes([ OpCodes.OP_IF, #this branch can only run on CDS-supporting chain len(cds_sig), cds_sig, len(cds_msg), cds_msg, len(cds_pubkey), cds_pubkey, OpCodes.OP_CHECKDATASIGVERIFY, len(self.pub1ser), self.pub1ser, OpCodes.OP_ELSE, #this branch can run on any chain len(self.pub2ser), self.pub2ser, OpCodes.OP_ENDIF, OpCodes.OP_CHECKSIG ]) assert 76 < len(self.redeemscript) <= 255 # simplify push in scriptsig; note len is around 200. self.address = Address.from_multisig_script(self.redeemscript) # make dummy scripts of correct size for size estimation. self.dummy_scriptsig_redeem = '01'*(4 + 72 + len(self.redeemscript)) self.dummy_scriptsig_refund = '00'*(4 + 72 + len(self.redeemscript))
def verify_tx_signature(self, signature, transaction, verification_key): "It verifies the transaction signatures" txin = list( filter(lambda x: verification_key in x['pubkeys'], transaction.inputs())) if txin: tx_num = transaction.inputs().index(txin[0]) pre_hash = Hash(bfh(transaction.serialize_preimage(tx_num))) order = generator_secp256k1.order() r, s = ecdsa.util.sigdecode_der(bfh(signature.decode()[:-2]), order) sig_string = ecdsa.util.sigencode_string(r, s, order) compressed = len(verification_key) <= 66 for recid in range(0, 4): try: pubk = MyVerifyingKey.from_signature(sig_string, recid, pre_hash, curve=SECP256k1) pubkey = bh2u(point_to_ser(pubk.pubkey.point, compressed)) if verification_key == pubkey: return True except: continue else: return False
def verify_tx_signature(self, signature, transaction, verification_key, utxo): '''Verify the signature for a specific utxo ("prevout_hash:n") given a transaction and verification key.''' txin = list( filter( lambda x: (verification_key in x['pubkeys'] and utxo == "{}:{}".format( x['tx_hash'], x['tx_pos'])), transaction.inputs())) if txin: tx_num = transaction.inputs().index(txin[0]) pre_hash = Hash(bfh(transaction.serialize_preimage(tx_num))) order = generator_secp256k1.order() r, s = ecdsa.util.sigdecode_der(bfh(signature.decode()[:-2]), order) sig_string = ecdsa.util.sigencode_string(r, s, order) compressed = len(verification_key) <= 66 for recid in range(0, 4): try: pubk = MyVerifyingKey.from_signature(sig_string, recid, pre_hash, curve=SECP256k1) pubkey = bh2u(point_to_ser(pubk.pubkey.point, compressed)) if verification_key == pubkey: return True except: continue else: return False
def sign_message(self, sequence, message, password): sig = None try: inputPath = self.get_derivation() + "/%d/%d" % sequence inputHash = Hash(msg_magic(message)).encode('hex') hasharray = [] hasharray.append({'hash': inputHash, 'keypath': inputPath}) hasharray = json.dumps(hasharray) msg = '{"sign":{"meta":"sign message", "data":%s}}' % (hasharray) dbb_client = self.plugin.get_client(self) if not dbb_client.is_paired(): raise Exception("Could not sign message.") reply = dbb_client.hid_send_encrypt(msg) self.handler.show_message(_("Signing message ...\r\n\r\n" \ "To continue, touch the Digital Bitbox's blinking light for 3 seconds.\r\n\r\n" \ "To cancel, briefly touch the blinking light or wait for the timeout.")) reply = dbb_client.hid_send_encrypt( msg ) # Send twice, first returns an echo for smart verification (not implemented) self.handler.clear_dialog() if 'error' in reply: raise Exception(reply['error']['message']) if 'sign' not in reply: raise Exception("Could not sign message.") if 'recid' in reply['sign'][0]: # firmware > v2.1.1 sig = chr(27 + int(reply['sign'][0]['recid'], 16) + 4) + reply['sign'][0]['sig'].decode('hex') h = Hash(msg_magic(message)) pk, compressed = pubkey_from_signature(sig, h) pk = point_to_ser(pk.pubkey.point, compressed) addr = public_key_to_p2pkh(pk) if verify_message(addr, sig, message) is False: raise Exception("Could not sign message") elif 'pubkey' in reply['sign'][0]: # firmware <= v2.1.1 for i in range(4): sig = chr(27 + i + 4) + reply['sign'][0]['sig'].decode('hex') try: addr = public_key_to_p2pkh( reply['sign'][0]['pubkey'].decode('hex')) if verify_message(addr, sig, message): break except Exception: continue else: raise Exception("Could not sign message") except BaseException as e: self.give_error(e) return sig
def verify_signature(self, signature, message, verification_key): "This method verifies signature of message" pk, compressed = pubkey_from_signature(signature, Hash(msg_magic(message))) address_from_signature = public_key_to_p2pkh( point_to_ser(pk.pubkey.point, compressed)) address_from_vk = self.address(verification_key) return address_from_signature == address_from_vk
def _calc_initial(self): Hpoint = self.setup._ecdsa_H HGpoint = self.setup._ecdsa_HG k = self.nonce a = self.amount_mod # We don't want to calculate (a * Hpoint) since the time to execute # would reveal information about size / bitcount of a. So, we use # the nonce as a blinding offset factor. Ppoint = ((a - k) % order) * Hpoint + k * HGpoint if Ppoint == ecdsa.ellipticcurve.INFINITY: raise ResultAtInfinity self.P_uncompressed = point_to_ser(Ppoint, comp=False) self.P_compressed = point_to_ser(Ppoint, comp=True)
def verify_signature(self, signature, message, verification_key): "This method verifies signature of message" try: pk, compressed = pubkey_from_signature(signature, Hash(msg_magic(message))) pubkey = point_to_ser(pk.pubkey.point, compressed).hex() return pubkey == verification_key except Exception as e: self.print_error("verify_signature:", repr(e)) return False
def add_points(points_iterable): """ Adds one or more serialized points together. This is fastest if the points are already uncompressed. Returns uncompressed point. Note: intermediate sums are allowed to be the point at infinity, but not the final result. """ plist = [] if seclib: ctx = seclib.ctx for pser in points_iterable: P_buf = create_string_buffer(64) _b = bytes(pser) res = seclib.secp256k1_ec_pubkey_parse(ctx, P_buf, _b, c_size_t(len(_b))) if not res: raise ValueError('point could not be parsed by the secp256k1 library') plist.append(P_buf) if not plist: raise ValueError('empty list') num = len(plist) result_buf = create_string_buffer(64) publist = (c_void_p*num)(*(cast(x, c_void_p) for x in plist)) res = seclib.secp256k1_ec_pubkey_combine(ctx, result_buf, publist, num) if res != 1: raise ResultAtInfinity serpoint = create_string_buffer(65) sersize = c_size_t(65) res = seclib.secp256k1_ec_pubkey_serialize(ctx, serpoint, byref(sersize), result_buf, secp256k1.SECP256K1_EC_UNCOMPRESSED) assert res == 1 assert sersize.value == 65 return serpoint.raw else: for pser in points_iterable: plist.append(ser_to_point(pser)) if not plist: raise ValueError('empty list') Psum = sum(plist[1:], plist[0]) if Psum == ecdsa.ellipticcurve.INFINITY: raise ResultAtInfinity return point_to_ser(Psum, comp=False)
def __init__(self, master_privkey): G = generator_secp256k1 order = G.order() # make two derived private keys (integers between 1 and p-1 inclusive) # hard derivation (irreversible): x = int.from_bytes( hashlib.sha512(b'SplitMUL' + master_privkey.to_bytes(32, 'big')).digest(), 'big') self.priv1 = 1 + (x % (order - 1)) # generate compressed pubkeys self.pub1ser = point_to_ser(self.priv1 * G, True) self.keypairs = { self.pub1ser.hex(): (self.priv1.to_bytes(32, 'big'), True), } self.redeemscript = joinbytes([ #this script can only run on MUL-supporting chain len(self.pub1ser), self.pub1ser, OpCodes.OP_CHECKSIGVERIFY, OpCodes.OP_1, OpCodes.OP_1, OpCodes.OP_MUL, ]) assert len( self.redeemscript ) <= 76 # simplify push in scriptsig; note len is around 38. self.address = Address.from_multisig_script(self.redeemscript) # make dummy scripts of correct size for size estimation. self.dummy_scriptsig_redeem = '01' * (3 + 72 + len(self.redeemscript))
def restore_from_privkey(self, secret_string): self.private_key = string_to_number(bytes.fromhex(secret_string)) self.eck = EC_KEY(bytes.fromhex(secret_string)) self.public_key = point_to_ser(self.private_key * self.G, True)
def verify_signature(self, sig, message, vk): pk, compressed = pubkey_from_signature(sig,Hash(msg_magic(message))) address_from_signature = public_key_to_p2pkh(point_to_ser(pk.pubkey.point,compressed)) address_from_vk = self.address(vk) return address_from_signature == address_from_signature
def sign_transaction(self, tx, password): if tx.is_complete(): return try: p2shTransaction = False derivations = self.get_tx_derivations(tx) inputhasharray = [] hasharray = [] pubkeyarray = [] # Build hasharray from inputs for i, txin in enumerate(tx.inputs()): if txin['type'] == 'coinbase': self.give_error( "Coinbase not supported") # should never happen if txin['type'] in ['p2sh']: p2shTransaction = True for x_pubkey in txin['x_pubkeys']: if x_pubkey in derivations: index = derivations.get(x_pubkey) inputPath = "%s/%d/%d" % (self.get_derivation(), index[0], index[1]) inputHash = Hash( tx.serialize_preimage(i).decode('hex')) hasharray_i = { 'hash': inputHash.encode('hex'), 'keypath': inputPath } hasharray.append(hasharray_i) inputhasharray.append(inputHash) break else: self.give_error("No matching x_key for sign_transaction" ) # should never happen # Sanity check if p2shTransaction: for txinput in tx.inputs(): if txinput['type'] != 'p2sh': self.give_error( "P2SH / regular input mixed in same transaction not supported" ) # should never happen # Build pubkeyarray from outputs (unused because echo for smart verification not implemented) if not p2shTransaction: for _type, address, amount in tx.outputs(): assert _type == TYPE_ADDRESS info = tx.output_info.get(address) if info is not None: index, xpubs, m = info changePath = self.get_derivation() + "/%d/%d" % index changePubkey = self.derive_pubkey(index[0], index[1]) pubkeyarray_i = { 'pubkey': changePubkey, 'keypath': changePath } pubkeyarray.append(pubkeyarray_i) # Build sign command dbb_signatures = [] steps = math.ceil(1.0 * len(hasharray) / self.maxInputs) for step in range(int(steps)): hashes = hasharray[step * self.maxInputs:(step + 1) * self.maxInputs] msg = '{"sign": {"meta":"%s", "data":%s, "checkpub":%s} }' % \ (Hash(tx.serialize()).encode('hex'), json.dumps(hashes), json.dumps(pubkeyarray)) dbb_client = self.plugin.get_client(self) if not dbb_client.is_paired(): raise Exception("Could not sign transaction.") reply = dbb_client.hid_send_encrypt(msg) if 'error' in reply: raise Exception(reply['error']['message']) if 'echo' not in reply: raise Exception("Could not sign transaction.") if steps > 1: self.handler.show_message(_("Signing large transaction. Please be patient ...\r\n\r\n" \ "To continue, touch the Digital Bitbox's blinking light for 3 seconds. " \ "(Touch " + str(step + 1) + " of " + str(int(steps)) + ")\r\n\r\n" \ "To cancel, briefly touch the blinking light or wait for the timeout.\r\n\r\n")) else: self.handler.show_message(_("Signing transaction ...\r\n\r\n" \ "To continue, touch the Digital Bitbox's blinking light for 3 seconds.\r\n\r\n" \ "To cancel, briefly touch the blinking light or wait for the timeout.")) reply = dbb_client.hid_send_encrypt( msg ) # Send twice, first returns an echo for smart verification (not implemented) self.handler.clear_dialog() if 'error' in reply: raise Exception(reply['error']['message']) if 'sign' not in reply: raise Exception("Could not sign transaction.") dbb_signatures.extend(reply['sign']) # Fill signatures if len(dbb_signatures) <> len(tx.inputs()): raise Exception("Incorrect number of transactions signed." ) # Should never occur for i, txin in enumerate(tx.inputs()): num = txin['num_sig'] for pubkey in txin['pubkeys']: signatures = filter(None, txin['signatures']) if len(signatures) == num: break # txin is complete ii = txin['pubkeys'].index(pubkey) signed = dbb_signatures[i] if 'recid' in signed: # firmware > v2.1.1 recid = int(signed['recid'], 16) s = signed['sig'].decode('hex') h = inputhasharray[i] pk = MyVerifyingKey.from_signature(s, recid, h, curve=SECP256k1) pk = point_to_ser(pk.pubkey.point, True).encode('hex') elif 'pubkey' in signed: # firmware <= v2.1.1 pk = signed['pubkey'] if pk != pubkey: continue sig_r = int(signed['sig'][:64], 16) sig_s = int(signed['sig'][64:], 16) sig = sigencode_der(sig_r, sig_s, generator_secp256k1.order()) txin['signatures'][ii] = sig.encode('hex') + int_to_hex( Transaction.nHashType() & 255, 1) tx._inputs[i] = txin except BaseException as e: self.give_error(e, True) else: print_error("Transaction is_complete", tx.is_complete()) tx.raw = tx.serialize()
def verify_signature(self, signature, message, verification_key): "This method verifies signature of message" pk, compressed = pubkey_from_signature(signature, Hash(msg_magic(message))) pubkey = point_to_ser(pk.pubkey.point, compressed).hex() return pubkey == verification_key
def generate_key_pair(self): self.private_key = ecdsa.util.randrange(pow(2, 256)) % self._r self.eck = EC_KEY(number_to_string(self.private_key, self._r)) self.public_key = point_to_ser(self.private_key * self.G, True)
def generate_key_pair(self): """ generate encryption/decryption pair """ self.private_key = ecdsa.util.randrange(self._r) self.eck = EC_KEY(number_to_string(self.private_key, self._r)) self.public_key = point_to_ser(self.private_key * self.G, True)
def sign_message(self, sequence, message, password, sigtype=SignatureType.BITCOIN): if sigtype == SignatureType.ECASH: raise RuntimeError( _('eCash message signing is not available for {}').format( self.device)) sig = None try: message = message.encode('utf8') inputPath = self.get_derivation() + "/%d/%d" % sequence msg_hash = Hash(msg_magic(message)) inputHash = to_hexstr(msg_hash) hasharray = [] hasharray.append({'hash': inputHash, 'keypath': inputPath}) hasharray = json.dumps(hasharray) msg = b'{"sign":{"meta":"sign message", "data":%s}}' % hasharray.encode( 'utf8') dbb_client = self.plugin.get_client(self) if not dbb_client.is_paired(): raise Exception(_("Could not sign message.")) reply = dbb_client.hid_send_encrypt(msg) self.handler.show_message( _("Signing message ...") + "\n\n" + _("To continue, touch the Digital Bitbox's blinking light for 3 seconds." ) + "\n\n" + _("To cancel, briefly touch the blinking light or wait for the timeout." )) reply = dbb_client.hid_send_encrypt( msg ) # Send twice, first returns an echo for smart verification (not implemented) self.handler.finished() if 'error' in reply: raise Exception(reply['error']['message']) if 'sign' not in reply: raise Exception(_("Could not sign message.")) if 'recid' in reply['sign'][0]: # firmware > v2.1.1 sig = bytes([27 + int(reply['sign'][0]['recid'], 16) + 4 ]) + binascii.unhexlify(reply['sign'][0]['sig']) pk, compressed = pubkey_from_signature(sig, msg_hash) pk = point_to_ser(pk.pubkey.point, compressed) addr = public_key_to_p2pkh(pk) if verify_message(addr, sig, message) is False: raise Exception(_("Could not sign message")) elif 'pubkey' in reply['sign'][0]: # firmware <= v2.1.1 for i in range(4): sig = bytes([27 + i + 4]) + binascii.unhexlify( reply['sign'][0]['sig']) try: addr = public_key_to_p2pkh( binascii.unhexlify(reply['sign'][0]['pubkey'])) if verify_message(addr, sig, message): break except Exception: continue else: raise Exception(_("Could not sign message")) except BaseException as e: self.give_error(e) return sig
def restore_from_privkey(self, secret_string): "restore key pair from private key expressed in a hex form" self.private_key = string_to_number(bytes.fromhex(secret_string)) self.eck = EC_KEY(bytes.fromhex(secret_string)) self.public_key = point_to_ser(self.private_key * self.G, True)
def sign_transaction(self, tx, password): if tx.is_complete(): return try: p2pkhTransaction = True derivations = self.get_tx_derivations(tx) inputhasharray = [] hasharray = [] pubkeyarray = [] # Build hasharray from inputs for i, txin in enumerate(tx.inputs()): if txin['type'] == 'coinbase': self.give_error("Coinbase not supported") # should never happen if txin['type'] != 'p2pkh': p2pkhTransaction = False for x_pubkey in txin['x_pubkeys']: if x_pubkey in derivations: index = derivations.get(x_pubkey) inputPath = "%s/%d/%d" % (self.get_derivation(), index[0], index[1]) inputHash = Hash(binascii.unhexlify(tx.serialize_preimage(i))) hasharray_i = {'hash': to_hexstr(inputHash), 'keypath': inputPath} hasharray.append(hasharray_i) inputhasharray.append(inputHash) break else: self.give_error("No matching x_key for sign_transaction") # should never happen # Build pubkeyarray from outputs for _type, address, amount in tx.outputs(): if not _type == TYPE_ADDRESS: self.give_error(_("Only address outputs are supported by {}").format(self.name)) info = tx.output_info.get(address) if info is not None: index, xpubs, m, script_type = info changePath = self.get_derivation() + "/%d/%d" % index changePubkey = self.derive_pubkey(index[0], index[1]) pubkeyarray_i = {'pubkey': changePubkey, 'keypath': changePath} pubkeyarray.append(pubkeyarray_i) # Special serialization of the unsigned transaction for # the mobile verification app. # At the moment, verification only works for p2pkh transactions. if p2pkhTransaction: class CustomTXSerialization(Transaction): @classmethod def input_script(self, txin, estimate_size=False, sign_schnorr=False): if txin['type'] == 'p2pkh': return Transaction.get_preimage_script(txin) if txin['type'] == 'p2sh': # Multisig verification has partial support, but is disabled. This is the # expected serialization though, so we leave it here until we activate it. return '00' + push_script(Transaction.get_preimage_script(txin)) raise Exception("unsupported type %s" % txin['type']) tx_dbb_serialized = CustomTXSerialization(tx.serialize()).serialize() else: # We only need this for the signing echo / verification. tx_dbb_serialized = None # Build sign command dbb_signatures = [] steps = math.ceil(1.0 * len(hasharray) / self.maxInputs) for step in range(int(steps)): hashes = hasharray[step * self.maxInputs : (step + 1) * self.maxInputs] msg = { "sign": { "data": hashes, "checkpub": pubkeyarray, }, } if tx_dbb_serialized is not None: msg["sign"]["meta"] = to_hexstr(Hash(tx_dbb_serialized)) msg = json.dumps(msg).encode('ascii') dbb_client = self.plugin.get_client(self) if not dbb_client.is_paired(): raise Exception("Could not sign transaction.") reply = dbb_client.hid_send_encrypt(msg) if 'error' in reply: raise Exception(reply['error']['message']) if 'echo' not in reply: raise Exception("Could not sign transaction.") if self.plugin.is_mobile_paired() and tx_dbb_serialized is not None: reply['tx'] = tx_dbb_serialized self.plugin.comserver_post_notification(reply) if steps > 1: self.handler.show_message(_("Signing large transaction. Please be patient ...") + "\n\n" + _("To continue, touch the Digital Bitbox's blinking light for 3 seconds.") + " " + _("(Touch {} of {})").format((step + 1), steps) + "\n\n" + _("To cancel, briefly touch the blinking light or wait for the timeout.") + "\n\n") else: self.handler.show_message(_("Signing transaction...") + "\n\n" + _("To continue, touch the Digital Bitbox's blinking light for 3 seconds.") + "\n\n" + _("To cancel, briefly touch the blinking light or wait for the timeout.")) # Send twice, first returns an echo for smart verification reply = dbb_client.hid_send_encrypt(msg) self.handler.finished() if 'error' in reply: if reply["error"].get('code') in (600, 601): # aborted via LED short touch or timeout raise UserCancelled() raise Exception(reply['error']['message']) if 'sign' not in reply: raise Exception("Could not sign transaction.") dbb_signatures.extend(reply['sign']) # Fill signatures if len(dbb_signatures) != len(tx.inputs()): raise Exception("Incorrect number of transactions signed.") # Should never occur for i, txin in enumerate(tx.inputs()): num = txin['num_sig'] for pubkey in txin['pubkeys']: signatures = list(filter(None, txin['signatures'])) if len(signatures) == num: break # txin is complete ii = txin['pubkeys'].index(pubkey) signed = dbb_signatures[i] if 'recid' in signed: # firmware > v2.1.1 recid = int(signed['recid'], 16) s = binascii.unhexlify(signed['sig']) h = inputhasharray[i] pk = MyVerifyingKey.from_signature(s, recid, h, curve = SECP256k1) pk = to_hexstr(point_to_ser(pk.pubkey.point, True)) elif 'pubkey' in signed: # firmware <= v2.1.1 pk = signed['pubkey'] if pk != pubkey: continue sig_r = int(signed['sig'][:64], 16) sig_s = int(signed['sig'][64:], 16) sig = sigencode_der(sig_r, sig_s, generator_secp256k1.order()) txin['signatures'][ii] = to_hexstr(sig) + '41' tx._inputs[i] = txin except UserCancelled: raise except BaseException as e: self.give_error(e, True) else: print_error("Transaction is_complete", tx.is_complete()) tx.raw = tx.serialize()
def generate_fake_key_pair(self): self.fake_private_key = ecdsa.util.randrange(self._r) self.fake_eck = EC_KEY(number_to_string(self.fake_private_key, self._r)) self.fake_public_key = point_to_ser(self.fake_private_key * self.G, True)