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 make_bad_client(self, bad_cleint_thread, with_print=False): sk = random_sk() channel = ChannelWithPrint() if with_print else Channel() public_key = sk.get_public_key() inputs = {} number_of_pubs = random.randint(1, 3) secret_keys = [random_sk() for _ in range(number_of_pubs)] sks = {sk.get_public_key(): sk for sk in secret_keys} for pubk in sks: inputs[pubk] = [] number_of_coins = random.randint(1, 2) addr = public_key_to_p2pkh(bytes.fromhex(pubk)) for i in range(number_of_coins): min_amout_per_input = self.amount // number_of_pubs // number_of_coins coin_amount = random.randint( min_amout_per_input + self.fee + 1, min_amout_per_input + self.fee + 1000) coin_hash = fake_hash(addr, coin_amount) inputs[pubk].append(coin_hash + ":0") self.network.add_coin(addr, coin_amount, tx_hash=coin_hash) return bad_cleint_thread(self.HOST, self.PORT, self.network, self.amount, self.fee, sk, sks, inputs, public_key, self.get_random_address(), self.get_random_address(), logger=channel)
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 make_bad_client(self, bad_cleint_thread , with_print = False): sk = random_sk() channel = ChannelWithPrint() if with_print else Channel() pubk = sk.get_public_key() addr = public_key_to_p2pkh(bytes.fromhex(pubk)) self.network.add_coin(addr , self.amount + random.randint(self.amount + 1 , self.amount + self.fee + 1000)) # add checking fro parent class inheritance here # (host, port, network, amount, fee, sk, pubk, addr_new, change, logger = logger, ssl = False) return bad_cleint_thread(self.HOST, self.PORT, self.network, self.amount, self.fee, sk, pubk, self.get_random_address(), self.get_random_address(), logger = channel)
def test_002_insufficient_funds(self): protocolThreads = self.make_clients_threads(with_print = True) bad_addr = public_key_to_p2pkh(bytes.fromhex(protocolThreads[0].vk)) self.network.coins[bad_addr][0]['value'] = self.amount - 1 self.start_protocols(protocolThreads) done = False while not done: completes = [self.is_protocol_complete(p) for p in protocolThreads[1:]] done = all(completes) self.stop_protocols(protocolThreads) tx = protocolThreads[1].protocol.tx.raw for pThread in protocolThreads[2:]: self.assertEqual(tx, pThread.protocol.tx.raw)
def make_clients_threads(self, number_of_clients=None, with_print=False): if not number_of_clients: number_of_clients = self.number_of_players players = [{ "channel": ChannelWithPrint() if with_print else Channel() } for _ in range(number_of_clients)] for player in players: number_of_pubs = random.randint(1, 3) player["secret_keys"] = [ random_sk() for _ in range(number_of_pubs) ] player["sks"] = { sk.get_public_key(): sk for sk in player["secret_keys"] } player["inputs"] = {} for pubk in player["sks"]: player["inputs"][pubk] = [] number_of_coins = random.randint(1, 2) addr = public_key_to_p2pkh(bytes.fromhex(pubk)) for i in range(number_of_coins): min_amout_per_input = self.amount // number_of_pubs // number_of_coins coin_amount = random.randint( min_amout_per_input + self.fee + 1, min_amout_per_input + self.fee + 1000) coin_hash = fake_hash(addr, coin_amount) player["inputs"][pubk].append(coin_hash + ":0") # self.network.add_coin(addr, coin_amount, tx_hash=coin_hash) self.network.add_coin(Address.from_pubkey(pubk), coin_amount, tx_hash=coin_hash) player["sk"] = random_sk() player["pubk"] = player["sk"].get_public_key() protocolThreads = [ testThread(self.HOST, self.PORT, self.network, "x", self.amount, self.fee, player["sk"], player["sks"], player["inputs"], player["pubk"], self.get_random_address(), self.get_random_address(), logger=player['channel']) for player in players ] return protocolThreads
def make_clients_threads(self, number_of_clients = None, with_print = False): if not number_of_clients: number_of_clients = self.number_of_players # generate random keys players = [{"sk": random_sk(), "channel":ChannelWithPrint() if with_print else Channel()} for sk in range(number_of_clients)] # loggers = [Channel() for _ in range(self.number_of_players)] for player in players: pubk = player["sk"].get_public_key() addr = public_key_to_p2pkh(bytes.fromhex(pubk)) # add coins to pseudonetwork with sufficient ammount self.network.add_coin(addr , self.amount + random.randint(self.amount + 1 , self.amount + self.fee + 1000)) # make threads protocolThreads = [testThread.from_sk(player["sk"], self.HOST, self.PORT, self.network, self.amount, self.fee, self.get_random_address(), self.get_random_address(), logger = player['channel']) for player in players] return protocolThreads
def test_002_insufficient_funds(self): protocolThreads = self.make_clients_threads(with_print=True) # make insufficient funds for first player bad_addr = public_key_to_p2pkh(bytes.fromhex(protocolThreads[0].vk)) # print(self.network.coins[bad_addr][0]['value']) self.network.coins[bad_addr][0]['value'] = self.amount - 1 self.start_protocols(protocolThreads) done = False while not done: alives = [self.is_round_live(p) for p in protocolThreads[1:]] done = False if None in alives else not all(alives) self.stop_protocols(protocolThreads) tx = protocolThreads[1].protocol.tx.raw for pThread in protocolThreads[2:]: self.assertEqual(tx, pThread.protocol.tx.raw)
def test_002_insufficient_funds(self): from electroncash_plugins.shuffle.coin import Coin coin = Coin(self.network) protocolThreads = self.make_clients_threads(with_print = True) coins_1 = coin.get_coins(protocolThreads[0].inputs) for pubkey in coins_1: bad_addr = public_key_to_p2pkh(bytes.fromhex(pubkey)) for coin in coins_1[pubkey]: coin['value'] = 0 self.network.coins[bad_addr] = coins_1[pubkey] self.start_protocols(protocolThreads) done = False while not done: completes = [self.is_protocol_complete(p) for p in protocolThreads[1:]] done = all(completes) self.stop_protocols(protocolThreads) tx = protocolThreads[1].protocol.tx.raw for pThread in protocolThreads[2:]: self.assertEqual(tx, pThread.protocol.tx.raw) print(protocolThreads[-1].protocol.tx.raw) print(protocolThreads[-1].protocol.change_addresses)
def test_correct_protocol(self): players_count = 3 # generate random keys sks = [random_sk() for sk in range(players_count)] for sk in sks: pubk = sk.get_public_key() addr = public_key_to_p2pkh(bytes.fromhex(pubk)) # add coins to pseudonetwork with sufficient ammount self.network.add_coin(addr, self.amount + random.randint(1001, 5000)) # make threads protocolThreads = [ testThread.from_sk(sk, self.HOST, self.PORT, self.network, self.amount, self.fee, self.get_random_address(), self.get_random_address(), logger=self.logger) for sk in sks ] for pThread in protocolThreads: pThread.start() done = False completed = 0 while not done: message = self.logger.get() print(message) if message[-17:] == "complete protocol": completed += 1 if completed == players_count: done = True if message[:5] == 'Blame': done = True self.assertEqual(completed, players_count)
def address(self, vk): return public_key_to_p2pkh(bytes.fromhex(vk))
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_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 address(self, verification_key): "get address from public key" return public_key_to_p2pkh(bytes.fromhex(verification_key))
def get_random_address(self): return public_key_to_p2pkh(bytes.fromhex(random_sk().get_public_key()))
def make_fake_address(compressed=True): return public_key_to_p2pkh(make_fake_public_key(compressed=compressed))