def validate_or_raise(self, verify_signature=True) -> bool: """ This method will validate a transaction and raise exception if problems are found :return: True if the exception is valid, exceptions otherwise :rtype: bool """ if not self._validate_custom(): raise ValueError("Custom validation failed") self._coinbase_filter() expected_transaction_hash = self.generate_txhash() if verify_signature and self.txhash != expected_transaction_hash: logger.warning('Invalid Transaction hash') logger.warning('Expected Transaction hash %s', bin2hstr(expected_transaction_hash)) logger.warning('Found Transaction hash %s', bin2hstr(self.txhash)) raise ValueError("Invalid Transaction Hash") if verify_signature: # Temporarily disabled following new added lines. # TODO: Review Juan # if not XMSS.validate_signature(self.signature, self.PK): # raise ValueError("Invalid xmss signature") if not XmssFast.verify(self.get_data_hash(), self.signature, self.PK): raise ValueError("Invalid xmss signature") return True
def audit_multisig_addr(qrl_client, addr): """ Validate the multi sig address """ balance = 0 tx_count = 0 bad_tx_count = 0 request_addr = qrl_pb2.GetMultiSigAddressStateReq( address=bytes.fromhex(addr[1:])) response_addr = qrl_client.GetMultiSigAddressState(request_addr) if not response_addr.HasField('state'): logging.error('could not find address {}'.format(addr)) return balance, tx_count, bad_tx_count balance = response_addr.state.balance request_txs = qrl_pb2.GetMultiSigSpendTxsByAddressReq( address=bytes.fromhex(addr[1:]), item_per_page=64, page_number=1, filter_type=qrl_pb2.GetMultiSigSpendTxsByAddressReq.EXECUTED_ONLY) response_txs = qrl_client.GetMultiSigSpendTxsByAddress(request_txs) tx_count = len(response_txs.transactions_detail) for tx_detail in response_txs.transactions_detail: tx = tx_detail.tx if not tx.HasField('multi_sig_spend'): bad_tx_count += 1 logging.error('txhash {} for addr {} does not exist'.format( tx.transaction_hash.hex(), addr)) continue tmptxhash = (tx.master_addr + to_bytes(tx.fee) + tx.multi_sig_spend.multi_sig_address + to_bytes(tx.multi_sig_spend.expiry_block_number) + get_tx_hash(tx.multi_sig_spend)) if not XmssFast.verify(sha256(tmptxhash), tx.signature, tx.public_key): logging.info( 'txhash {} for addr {} failed XmssFast verification'.format( tx.transaction_hash.hex(), addr)) return balance, tx_count, bad_tx_count
def test_verify_known_sig(): tx = get_tx(0)[2 + 39:] # need to skip metadata and source address msg = sha2_256(tx) pk = hstr2bin( "000400" "106D0856A5198967360B6BDFCA4976A433FA48DEA2A726FDAF30EA8CD3FAD211" "3191DA3442686282B3D5160F25CF162A517FD2131F83FBF2698A58F9C46AFC5D") sig = hstr2bin(expected_sig_tc0_idx0) # Generate identical tree to confirm signature xmss = XmssFast([0] * 48, 8, SHA2_256) pk2 = xmss.getPK() sig2 = xmss.sign(msg) assert bin2hstr(pk2).upper() == bin2hstr(pk).upper() assert XmssFast.verify(msg, sig2, pk) == True assert bin2hstr(sig2).upper() == bin2hstr(sig).upper() assert XmssFast.verify(msg, sig, pk) == True
def test_sign(): dev = LedgerQRL() dev.connect() signature = dev.sign(get_tx(0)) assert signature is not None # verify signature hashed_msg = sha2_256(get_tx(0)[2 + 39:]) pk = dev.pk_raw assert XmssFast.verify(hashed_msg, signature, pk) == True
def validate_or_raise(self) -> bool: """ This method will validate a transaction and raise exception if problems are found :return: True if the exception is valid, exceptions otherwise :rtype: bool """ if not self._validate_custom(): raise ValueError("Custom validation failed") if not XmssFast.verify(self.get_hashable_bytes(), self.signature, self.PK): raise ValueError("Invalid xmss signature") return True
def test_sign_verify(self): message = "This is a test" message_bin = str2bin(message) xmss_height = 10 seed = bytearray([i for i in range(48)]) xmss = XMSS(XmssFast(seed, xmss_height)) pk = xmss.pk xmss.set_ots_index(1) for i in range(10): self.assertTrue(xmss.ots_index == i + 1) signature = xmss.sign(message_bin) self.assertTrue(XmssFast.verify(message_bin, signature, pk))
def VERIFY(message: bytes, signature: bytes, pk: bytes): """ Verify an xmss sig with shorter PK same function but verifies using shorter signature where PK: {root, hex(_public_SEED)} # main verification function.. :param pk: :type pk: :param message: :param signature: :return: >>> from qrl.crypto.doctest_data import *; XMSS.VERIFY( str2bin("test_message"), hstr2bin(xmss_sign_expected1), hstr2bin(xmss_pk_expected1)) True >>> from qrl.crypto.doctest_data import *; XMSS.VERIFY( str2bin("test_messagex"), hstr2bin(xmss_sign_expected1), hstr2bin(xmss_pk_expected1)) False >>> from qrl.crypto.doctest_data import *; XMSS.VERIFY( str2bin("test_message"), hstr2bin(xmss_sign_expected2), hstr2bin(xmss_pk_expected2)) True >>> from qrl.crypto.doctest_data import *; XMSS.VERIFY( str2bin("test_messagex"), hstr2bin(xmss_sign_expected2), hstr2bin(xmss_pk_expected2)) False """ return XmssFast.verify(message, signature, pk)
def audit_regular_addr(qrl_client, addr): """ Validate the provided regular address """ balance = 0 tx_count = 0 bad_tx_count = 0 request_addr = qrl_pb2.GetAddressStateReq(address=bytes.fromhex(addr[1:])) response_addr = qrl_client.GetAddressState(request_addr) if not response_addr.HasField('state'): logging.error('could not find address {}'.format(addr)) return balance, tx_count, bad_tx_count balance = response_addr.state.balance tx_count = len(response_addr.state.transaction_hashes) for txhash in response_addr.state.transaction_hashes: request_tx = qrl_pb2.GetObjectReq(query=bytes.fromhex(txhash.hex())) response_tx = qrl_client.GetObject(request_tx) if not response_tx.HasField('transaction'): bad_tx_count += 1 logging.error('txhash {} for addr {} does not exist'.format( txhash, addr)) continue tx = response_tx.transaction.tx if tx.HasField('transfer') or tx.HasField('multi_sig_spend'): tmptxhash = (tx.master_addr + to_bytes(tx.fee)) if tx.HasField('transfer'): tmptxhash += (tx.transfer.message_data + get_tx_hash(tx.transfer)) if tx.HasField('multi_sig_spend'): tmptxhash += ( tx.multi_sig_spend.multi_sig_address + to_bytes(tx.multi_sig_spend.expiry_block_number) + get_tx_hash(tx.multi_sig_spend)) data_hash = sha256(tmptxhash) signature = tx.signature public_key = tx.public_key if not XmssFast.verify(data_hash, signature, public_key): logging.info( 'txhash {} for addr {} failed XmssFast verification'. format(txhash, addr)) return balance, tx_count, bad_tx_count
def VERIFY(message, signature, pk, height=config.dev): # type: (bytearray, list) -> bool # NOTE: used by transaction """ Verify an xmss sig with shorter PK same function but verifies using shorter signature where PK: {root, hex(_public_SEED)} # main verification function.. :param height: :type height: :param pk: :type pk: :param message: :param signature: :return: >>> from qrl.crypto.doctest_data import *; XMSS.VERIFY( str2bin("test_message"), hstr2bin(xmss_sign_expected1), hstr2bin(xmss_pk_expected1), xmss_sign_expected1_h) True >>> from qrl.crypto.doctest_data import *; XMSS.VERIFY( str2bin("test_messagex"), hstr2bin(xmss_sign_expected1), hstr2bin(xmss_pk_expected1), xmss_sign_expected1_h) False >>> from qrl.crypto.doctest_data import *; XMSS.VERIFY( str2bin("test_message"), hstr2bin(xmss_sign_expected2), hstr2bin(xmss_pk_expected2), xmss_sign_expected2_h) True >>> from qrl.crypto.doctest_data import *; XMSS.VERIFY( str2bin("test_messagex"), hstr2bin(xmss_sign_expected2), hstr2bin(xmss_pk_expected2), xmss_sign_expected2_h) False """ return XmssFast.verify(message, signature, pk, height)
def VERIFY(message: bytes, signature: bytes, pk: bytes): """ Verify an xmss sig with shorter PK same function but verifies using shorter signature where PK: {root, hex(_public_SEED)} # main verification function.. :param pk: :type pk: :param message: :param signature: :return: >>> from qrl.crypto.doctest_data import *; XMSS.VERIFY( str2bin("test_message"), hstr2bin(xmss_sign_expected1), hstr2bin(xmss_pk_expected1)) True >>> from qrl.crypto.doctest_data import *; XMSS.VERIFY( str2bin("test_messagex"), hstr2bin(xmss_sign_expected1), hstr2bin(xmss_pk_expected1)) False >>> from qrl.crypto.doctest_data import *; XMSS.VERIFY( str2bin("test_message"), hstr2bin(xmss_sign_expected2), hstr2bin(xmss_pk_expected2)) True >>> from qrl.crypto.doctest_data import *; XMSS.VERIFY( str2bin("test_messagex"), hstr2bin(xmss_sign_expected2), hstr2bin(xmss_pk_expected2)) False """ try: return XmssFast.verify(message, signature, pk) except ValueError: return False