def __init__(self, tree_height, seed=None, _xmssfast=None): """ :param tree_height: height of the tree to generate. number of OTS keypairs=2**tree_height :param seed: >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getHeight() 4 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getSecretKeySize() 132 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getSignatureSize() 2308 >>> from qrl.crypto.doctest_data import *; len(XMSS(4, xmss_test_seed1)._xmss.getSK()) == XMSS(4, xmss_test_seed1)._xmss.getSecretKeySize() True >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getPK() ) '26b3bcc104d686ecfd9fdea7b1963384339121430fbe056cab7c3048ea3e4c4e51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSK() ) == xmss_sk_expected1 True >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getRoot() ) '26b3bcc104d686ecfd9fdea7b1963384339121430fbe056cab7c3048ea3e4c4e' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getPKSeed() ) '51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff' >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getIndex() 0 >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSKSeed() ) '5f2eb95ccf6a0e3e7f472c32d234340c20b3fd379dc28b710affcc0cb2afa57b' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSKPRF() ) '3aa40c0f99459afe7efe72eb9517ee8ded49ccd51dab72ebf6bc37d73240bb3a' >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getAddress('Q') 'Q1d651431536359202ce7095757e3ed66f579a6eab488ac1331486f207c91604016b6a443' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed2)._xmss.getPK() ) # doctest: +SKIP '' """ self._type = 'XMSS' if _xmssfast is not None: self._xmss = _xmssfast self._seed = self._xmss.getSeed() else: # TODO: This is the old code, probably it should be removed if seed is None: # FIXME: Improve seed generation self._seed = getRandomSeed(48, '') else: if isinstance(seed, str): self._seed = str2bin(seed) else: self._seed = seed self._xmss = XmssFast(self._seed, tree_height) self.addresses = [(0, self.get_address(), self.get_number_signatures()) ]
def test_hash_function(self): xmss_height = 4 seed = bytearray([i for i in range(48)]) xmss = XMSS(XmssFast(seed, xmss_height, SHAKE_128)) self.assertEqual('shake128', xmss.hash_function) xmss = XMSS(XmssFast(seed, xmss_height, SHAKE_256)) self.assertEqual('shake256', xmss.hash_function) xmss = XMSS(XmssFast(seed, xmss_height, SHA2_256)) self.assertEqual('sha2_256', xmss.hash_function)
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 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 __init__(self, tree_height, seed=None, _xmssfast=None): """ :param tree_height: height of the tree to generate. number of OTS keypairs=2**tree_height :param seed: >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getHeight() 4 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getSecretKeySize() 132 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getSignatureSize() 2308 >>> from qrl.crypto.doctest_data import *; len(XMSS(4, xmss_test_seed1)._xmss.getSK()) == XMSS(4, xmss_test_seed1)._xmss.getSecretKeySize() True >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getPK() ) '26b3bcc104d686ecfd9fdea7b1963384339121430fbe056cab7c3048ea3e4c4e51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSK() ) == xmss_sk_expected1 True >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getRoot() ) '26b3bcc104d686ecfd9fdea7b1963384339121430fbe056cab7c3048ea3e4c4e' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getPKSeed() ) '51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff' >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getIndex() 0 >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSKSeed() ) '5f2eb95ccf6a0e3e7f472c32d234340c20b3fd379dc28b710affcc0cb2afa57b' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSKPRF() ) '3aa40c0f99459afe7efe72eb9517ee8ded49ccd51dab72ebf6bc37d73240bb3a' >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getAddress('Q') 'Q1d651431536359202ce7095757e3ed66f579a6eab488ac1331486f207c91604016b6a443' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed2)._xmss.getPK() ) # doctest: +SKIP '' """ self._type = 'XMSS' if _xmssfast is not None: self._xmss = _xmssfast self._seed = self._xmss.getSeed() else: # TODO: This is the old code, probably it should be removed if seed is None: # FIXME: Improve seed generation self._seed = getRandomSeed(48, '') else: if isinstance(seed, str): self._seed = str2bin(seed) else: self._seed = seed self._xmss = XmssFast(self._seed, tree_height) self.addresses = [(0, self.get_address(), self.get_number_signatures())]
def test_PK(self): xmss_height = 10 seed = bytearray([i for i in range(48)]) xmss = XMSS(XmssFast(seed, xmss_height)) pk = xmss.pk self.assertEqual( '010500ffc6e502e2a8244aed6a8cd67531e79f95baa638615ba789c194a1d15d7eb' '77e4e3983bd564298c49ae2e7fa6e28d4b954d8cd59398f1225b08d6144854aee0e', bin2hstr(pk))
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 from_extended_seed(extended_seed: bytes): if len(extended_seed) != 51: raise Exception('Extended seed should be 51 bytes long') descr = QRLDescriptor.fromBytes(extended_seed[0:3]) if descr.getSignatureType() != pyqrllib.XMSS: raise Exception('Signature type nor supported') height = descr.getHeight() hash_function = descr.getHashFunction() tmp = XmssFast(extended_seed[3:], height, hash_function) return XMSS(tmp)
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 get_new_address(signature_tree_height=config.dev.xmss_tree_height, seed=None) -> AddressBundle: """ Get a new wallet address The address format is a list of two items [address, data structure from random_mss call] :param signature_tree_height: :param address_type: :param seed: :return: a wallet address """ # FIXME: This should be always using the extended seed instead if seed and signature_tree_height: xmss = XMSS(XmssFast(seed, signature_tree_height)) elif seed: xmss = XMSS.from_extended_seed(seed) else: xmss = XMSS.from_height(signature_tree_height) return AddressBundle(bin2hstr(xmss.address).encode(), xmss)
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 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 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
def from_height(tree_height: int, hash_function="shake128"): if hash_function not in hash_functions: raise Exception("XMSS does not support this hash function!") seed = getRandomSeed(48, '') return XMSS(XmssFast(seed, tree_height, hash_functions[hash_function]))
class XMSS(object): # FIXME: Getters are only temporarily. Delete everything or use properties def __init__(self, tree_height, seed=None, _xmssfast=None): """ :param tree_height: height of the tree to generate. number of OTS keypairs=2**tree_height :param seed: >>> from qrl.crypto.doctest_data import *; XMSS(4, mnemonic2bin(xmss_mnemonic_test1, wordlist)).get_address() 'Q572721d2221f1d43b18eecacb945221f1156f1e2f519b71e3def43d761e88f3af72feb52' >>> from qrl.crypto.doctest_data import *; XMSS(4, mnemonic2bin(xmss_mnemonic_test2, wordlist)).get_address() 'Q578230464f0550df33f1bad86b725ce6e6c5e278c5d03a100fb93c1d282daec21b2422f2' >>> from qrl.crypto.doctest_data import *; XMSS(4, mnemonic2bin(xmss_mnemonic_test2, wordlist)).get_address() 'Q578230464f0550df33f1bad86b725ce6e6c5e278c5d03a100fb93c1d282daec21b2422f2' # NEW TESTS >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getHeight() 4 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getSecretKeySize() 132 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getSignatureSize() 2308 >>> from qrl.crypto.doctest_data import *; len(XMSS(4, xmss_test_seed1)._xmss.getSK()) == XMSS(4, xmss_test_seed1)._xmss.getSecretKeySize() True >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getPK() ) '26b3bcc104d686ecfd9fdea7b1963384339121430fbe056cab7c3048ea3e4c4e51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSK() ) == xmss_sk_expected1 True >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getRoot() ) '26b3bcc104d686ecfd9fdea7b1963384339121430fbe056cab7c3048ea3e4c4e' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getPKSeed() ) '51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff' >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getIndex() 0 >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSKSeed() ) '5f2eb95ccf6a0e3e7f472c32d234340c20b3fd379dc28b710affcc0cb2afa57b' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSKPRF() ) '3aa40c0f99459afe7efe72eb9517ee8ded49ccd51dab72ebf6bc37d73240bb3a' >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getAddress('Q') 'Q1d651431536359202ce7095757e3ed66f579a6eab488ac1331486f207c91604016b6a443' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed2)._xmss.getPK() ) # doctest: +SKIP '' """ self._type = 'XMSS' if _xmssfast is not None: self._xmss = _xmssfast else: # TODO: This is the old code, probably it should be removed if seed is None: # FIXME: Improve seed generation self._seed = getRandomSeed(48, '') else: if isinstance(seed, str): self._seed = str2bin(seed) else: self._seed = seed self._xmss = XmssFast(self._seed, tree_height) self.addresses = [(0, self.get_address(), self.get_number_signatures())] def _sk(self): """ >>> from qrl.crypto.doctest_data import *; bin2hstr(XMSS(4, xmss_test_seed1)._sk()) == xmss_sk_expected1 True >>> from qrl.crypto.doctest_data import *; bin2hstr(XMSS(4, xmss_test_seed2)._sk()) == xmss_sk_expected2 True """ return self._xmss.getSK() def pk(self): """ >>> from qrl.crypto.doctest_data import *; bin2hstr(XMSS(4, xmss_test_seed1).pk()) == xmss_pk_expected1 True >>> from qrl.crypto.doctest_data import *; bin2hstr(XMSS(4, xmss_test_seed2).pk()) == xmss_pk_expected2 True """ return self._xmss.getPK() def get_number_signatures(self): """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1).get_number_signatures() 16 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed2).get_number_signatures() 16 """ # type: () -> int return 2 ** self._xmss.getHeight() def get_remaining_signatures(self): """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1).get_remaining_signatures() 16 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed2).get_remaining_signatures() 16 """ return self.get_number_signatures() - self._xmss.getIndex() def get_mnemonic(self): """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1).get_mnemonic() == xmss_mnemonic_expected1 True >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed2).get_mnemonic() == xmss_mnemonic_expected2 True >>> from qrl.crypto.doctest_data import *; XMSS(4, mnemonic2bin(xmss_mnemonic_test1, wordlist)).get_mnemonic() == xmss_mnemonic_test1 True >>> from qrl.crypto.doctest_data import *; XMSS(4, mnemonic2bin(xmss_mnemonic_test2, wordlist)).get_mnemonic() == xmss_mnemonic_test2 True """ return bin2mnemonic(self._xmss.getSeed(), wordlist) def get_address(self): return self._xmss.getAddress('Q') def get_type(self): # type: () -> str return self._type def get_index(self): """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1).get_index() 0 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed2).get_index() 0 >>> from qrl.crypto.doctest_data import * >>> xmss = XMSS(4, xmss_test_seed2) >>> s = xmss.SIGN(str2bin("test")) >>> xmss.get_index() 1 """ # type: () -> int return self._xmss.getIndex() def set_index(self, new_index): """ :return: :rtype: >>> from qrl.crypto.doctest_data import * >>> xmss = XMSS(4, xmss_test_seed1) >>> xmss.set_index(1) >>> xmss.get_index() 1 >>> from qrl.crypto.doctest_data import * >>> xmss = XMSS(4, xmss_test_seed1) >>> xmss.set_index(10) >>> xmss.get_index() 10 """ self._xmss.setIndex(new_index) def get_hexseed(self): """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1).get_hexseed() '303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030' >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed2).get_hexseed() '333133313331333133313331333133313331333133313331333133313331333133313331333133313331333133313331' """ return bin2hstr(self._seed) def get_seed(self): """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1).get_seed() ) '303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed2).get_seed() ) '333133313331333133313331333133313331333133313331333133313331333133313331333133313331333133313331' """ return self._seed def get_seed_public(self): """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1).get_seed_private() ) '5f2eb95ccf6a0e3e7f472c32d234340c20b3fd379dc28b710affcc0cb2afa57b' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed2).get_seed_private() ) 'ad70ef34f316aaadcbf16a64b1b381db731eb53d833745c0d3eaa1e24cf728a2' """ return self._xmss.getPKSeed() def get_seed_private(self): """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1).get_seed_public() ) '51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed2).get_seed_public() ) 'df2355c48096f2351e4d04db57b326c355345552d31b75a65ac18b1f6d7c7875' """ return self._xmss.getSKSeed() @staticmethod # NOTE: USED EXTERNALLY!!! 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 SIGN(self, message): # type: (bytearray) -> tuple """ :param message: :return: >>> from qrl.crypto.doctest_data import *; bin2hstr(XMSS(4, xmss_test_seed1).SIGN(str2bin("test_message"))) == xmss_sign_expected1 True >>> from qrl.crypto.doctest_data import *; bin2hstr(XMSS(4, xmss_test_seed2).SIGN(str2bin("test_message"))) == xmss_sign_expected2 True """ return self._xmss.sign(message) def list_addresses(self): """ List the addresses derived in the main tree :return: """ addr_arr = [] for addr in self.addresses: addr_arr.append(addr[1]) return addr_arr
def get_slave_xmss() -> XMSS: xmss_height = 6 seed = bytes([i + 10 for i in range(48)]) return XMSS(XmssFast(seed, xmss_height))
def get_bob_xmss(xmss_height=6) -> XMSS: seed = bytes([i + 5 for i in range(48)]) return XMSS(XmssFast(seed, xmss_height))
def get_some_address(idx=0) -> bytes: seed = bytearray([i for i in range(48)]) seed[0] = idx xmss = XMSS(XmssFast(seed, 4)) return xmss.address
def test_add_4(self, mock_difficulty_tracker_get): with set_qrl_dir('wallet_ver1'): with State() as state: with mocked_genesis() as custom_genesis: chain_manager = ChainManager(state) chain_manager._difficulty_tracker = Mock() tmp_difficulty = StringToUInt256('2') tmp_target = DifficultyTracker.get_target(tmp_difficulty) mock_difficulty_tracker_get.return_value = [ tmp_difficulty, tmp_target ] alice_xmss = get_alice_xmss() slave_xmss = XMSS( XmssFast(alice_xmss.seed, alice_xmss.height)) random_xmss1 = get_random_xmss() random_kyber1 = Kyber() random_dilithium1 = Dilithium() random_xmss2 = get_random_xmss() random_kyber2 = Kyber() random_dilithium2 = Dilithium() message = b'Hello World How are you?' prf512_seed = b'10192' custom_genesis.genesis_balance.extend([ qrl_pb2.GenesisBalance(address=random_xmss1.address, balance=65000000000000000) ]) custom_genesis.genesis_balance.extend([ qrl_pb2.GenesisBalance(address=random_xmss2.address, balance=65000000000000000) ]) chain_manager.load(custom_genesis) with mock.patch('qrl.core.misc.ntp.getTime') as time_mock: time_mock.return_value = 1615270948 lattice_public_key_txn = LatticePublicKey.create( fee=1, kyber_pk=random_kyber1.getPK(), dilithium_pk=random_dilithium1.getPK(), xmss_pk=random_xmss1.pk) lattice_public_key_txn._data.nonce = 1 lattice_public_key_txn.sign(random_xmss1) genesis_block = GenesisBlock() tmp_block1 = Block.create( block_number=1, prev_block_headerhash=genesis_block.headerhash, prev_block_timestamp=genesis_block.timestamp, transactions=[lattice_public_key_txn], miner_address=slave_xmss.address) # Mine the nonce while not PoWValidator().validate_mining_nonce( state, tmp_block1.blockheader, False): tmp_block1.set_nonces(tmp_block1.mining_nonce + 1, 0) res = chain_manager.add_block(block=tmp_block1) self.assertTrue(res) # Need to move forward the time to align with block times time_mock.return_value += config.dev.minimum_minting_delay * 2 encrypted_eph_message = create_ephemeral_channel( msg_id=lattice_public_key_txn.txhash, ttl=time_mock.return_value, ttr=0, addr_from=random_xmss2.address, kyber_pk=random_kyber2.getPK(), kyber_sk=random_kyber2.getSK(), receiver_kyber_pk=random_kyber1.getPK(), dilithium_pk=random_dilithium2.getPK(), dilithium_sk=random_dilithium2.getSK(), prf512_seed=prf512_seed, data=message, nonce=1) chain_manager.state.update_ephemeral( encrypted_eph_message) eph_metadata = chain_manager.state.get_ephemeral_metadata( lattice_public_key_txn.txhash) # Decrypting Payload encrypted_eph_message = eph_metadata.encrypted_ephemeral_message_list[ 0] encrypted_payload = encrypted_eph_message.payload random_kyber1.kem_decode( encrypted_eph_message.channel.enc_aes256_symkey) aes_key = bytes(random_kyber1.getMyKey()) myAES = AES(aes_key) decrypted_payload = myAES.decrypt(encrypted_payload) ephemeral_channel_payload = EphemeralChannelPayload.from_json( decrypted_payload) self.assertEqual(ephemeral_channel_payload.prf512_seed, b'10192') self.assertEqual(ephemeral_channel_payload.data, b'Hello World How are you?') # TODO (cyyber): Add Ephemeral Testing code using Naive RNG tmp_block2 = Block.create( block_number=2, prev_block_headerhash=tmp_block1.headerhash, prev_block_timestamp=tmp_block1.timestamp, transactions=[], miner_address=slave_xmss.address) # Mine the nonce while not PoWValidator().validate_mining_nonce( state, tmp_block2.blockheader, False): tmp_block2.set_nonces(tmp_block2.mining_nonce + 1, 0) res = chain_manager.add_block(block=tmp_block2) self.assertTrue(res) # Need to move forward the time to align with block times time_mock.return_value += config.dev.minimum_minting_delay * 2 tmp_block3 = Block.create( block_number=3, prev_block_headerhash=tmp_block2.headerhash, prev_block_timestamp=tmp_block1.timestamp, transactions=[], miner_address=slave_xmss.address) # Mine the nonce while not PoWValidator().validate_mining_nonce( state, tmp_block3.blockheader, False): tmp_block3.set_nonces(tmp_block3.mining_nonce + 1, 0) res = chain_manager.add_block(block=tmp_block3) self.assertTrue(res) time_mock.return_value += config.dev.minimum_minting_delay tmp_block4 = Block.create( block_number=4, prev_block_headerhash=tmp_block3.headerhash, prev_block_timestamp=tmp_block1.timestamp, transactions=[], miner_address=slave_xmss.address) # Mine the nonce while not PoWValidator().validate_mining_nonce( state, tmp_block4.blockheader, False): tmp_block4.set_nonces(tmp_block4.mining_nonce + 1, 0) res = chain_manager.add_block(block=tmp_block4) self.assertTrue(res) address_state = chain_manager.get_address( random_xmss1.address) self.assertEqual( address_state.latticePK_list[0].kyber_pk, lattice_public_key_txn.kyber_pk) self.assertEqual( address_state.latticePK_list[0].dilithium_pk, lattice_public_key_txn.dilithium_pk) self.assertEqual(address_state.address, lattice_public_key_txn.addr_from) random_xmss1_state = chain_manager.get_address( random_xmss1.address) self.assertEqual(64999999999999999, random_xmss1_state.balance)
def test_signature_type(self): xmss_height = 4 seed = bytearray([i for i in range(48)]) xmss = XMSS(XmssFast(seed, xmss_height)) self.assertEqual(0, xmss.signature_type)
class XMSS(object): # FIXME: Getters are only temporarily. Delete everything or use properties def __init__(self, tree_height, seed=None, _xmssfast=None): """ :param tree_height: height of the tree to generate. number of OTS keypairs=2**tree_height :param seed: >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getHeight() 4 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getSecretKeySize() 132 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getSignatureSize() 2308 >>> from qrl.crypto.doctest_data import *; len(XMSS(4, xmss_test_seed1)._xmss.getSK()) == XMSS(4, xmss_test_seed1)._xmss.getSecretKeySize() True >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getPK() ) '26b3bcc104d686ecfd9fdea7b1963384339121430fbe056cab7c3048ea3e4c4e51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSK() ) == xmss_sk_expected1 True >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getRoot() ) '26b3bcc104d686ecfd9fdea7b1963384339121430fbe056cab7c3048ea3e4c4e' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getPKSeed() ) '51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff' >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getIndex() 0 >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSKSeed() ) '5f2eb95ccf6a0e3e7f472c32d234340c20b3fd379dc28b710affcc0cb2afa57b' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSKPRF() ) '3aa40c0f99459afe7efe72eb9517ee8ded49ccd51dab72ebf6bc37d73240bb3a' >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getAddress('Q') 'Q1d651431536359202ce7095757e3ed66f579a6eab488ac1331486f207c91604016b6a443' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed2)._xmss.getPK() ) # doctest: +SKIP '' """ self._type = 'XMSS' if _xmssfast is not None: self._xmss = _xmssfast self._seed = self._xmss.getSeed() else: # TODO: This is the old code, probably it should be removed if seed is None: # FIXME: Improve seed generation self._seed = getRandomSeed(48, '') else: if isinstance(seed, str): self._seed = str2bin(seed) else: self._seed = seed self._xmss = XmssFast(self._seed, tree_height) self.addresses = [(0, self.get_address(), self.get_number_signatures())] @property def height(self): return self._xmss.getHeight() def _sk(self): # FIXME: Move to property """ >>> from qrl.crypto.doctest_data import *; bin2hstr(XMSS(4, xmss_test_seed1)._sk()) == xmss_sk_expected1 True >>> from qrl.crypto.doctest_data import *; bin2hstr(XMSS(4, xmss_test_seed2)._sk()) == xmss_sk_expected2 True """ return bytes(self._xmss.getSK()) def pk(self): # FIXME: Move to property """ >>> from qrl.crypto.doctest_data import *; bin2hstr(XMSS(4, xmss_test_seed1).pk()) == xmss_pk_expected1 True >>> from qrl.crypto.doctest_data import *; bin2hstr(XMSS(4, xmss_test_seed2).pk()) == xmss_pk_expected2 True """ return bytes(self._xmss.getPK()) def get_number_signatures(self): # FIXME: Move to property """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1).get_number_signatures() 16 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed2).get_number_signatures() 16 """ # type: () -> int return 2 ** self._xmss.getHeight() def get_remaining_signatures(self): # FIXME: Move to property """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1).get_remaining_signatures() 16 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed2).get_remaining_signatures() 16 """ return self.get_number_signatures() - self._xmss.getIndex() def get_mnemonic(self): # FIXME: Move to property """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; XMSS(4, hstr2bin(xmss_mnemonic_seed1)).get_mnemonic() == xmss_mnemonic_test1 True >>> from qrl.crypto.doctest_data import *; XMSS(4, hstr2bin(xmss_mnemonic_seed2)).get_mnemonic() == xmss_mnemonic_test2 True >>> from qrl.crypto.doctest_data import *; XMSS(4, mnemonic2bin(xmss_mnemonic_test1)).get_mnemonic() == xmss_mnemonic_test1 True >>> from qrl.crypto.doctest_data import *; XMSS(4, mnemonic2bin(xmss_mnemonic_test2)).get_mnemonic() == xmss_mnemonic_test2 True """ return bin2mnemonic(self._xmss.getSeed()) def get_address(self)->bytes: # FIXME: Move to property return bytes(self._xmss.getAddress('Q').encode()) def get_type(self): # FIXME: Move to property # type: () -> str return self._type def get_index(self): # FIXME: Move to property """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1).get_index() 0 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed2).get_index() 0 >>> from qrl.crypto.doctest_data import * >>> xmss = XMSS(4, xmss_test_seed2) >>> s = xmss.SIGN(str2bin("test")) >>> xmss.get_index() 1 """ # type: () -> int return self._xmss.getIndex() def set_index(self, new_index): """ :return: :rtype: >>> from qrl.crypto.doctest_data import * >>> xmss = XMSS(4, xmss_test_seed1) >>> xmss.set_index(1) >>> xmss.get_index() 1 >>> from qrl.crypto.doctest_data import * >>> xmss = XMSS(4, xmss_test_seed1) >>> xmss.set_index(10) >>> xmss.get_index() 10 """ self._xmss.setIndex(new_index) def get_hexseed(self): # FIXME: Move to property """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1).get_hexseed() '303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030' >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed2).get_hexseed() '333133313331333133313331333133313331333133313331333133313331333133313331333133313331333133313331' """ return bin2hstr(self._seed) def get_seed(self): # FIXME: Move to property """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1).get_seed() ) '303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed2).get_seed() ) '333133313331333133313331333133313331333133313331333133313331333133313331333133313331333133313331' """ return self._seed def get_seed_public(self): # FIXME: Move to property """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1).get_seed_private() ) '5f2eb95ccf6a0e3e7f472c32d234340c20b3fd379dc28b710affcc0cb2afa57b' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed2).get_seed_private() ) 'ad70ef34f316aaadcbf16a64b1b381db731eb53d833745c0d3eaa1e24cf728a2' """ return bytes(self._xmss.getPKSeed()) def get_seed_private(self): # FIXME: Move to property """ :return: :rtype: >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1).get_seed_public() ) '51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed2).get_seed_public() ) 'df2355c48096f2351e4d04db57b326c355345552d31b75a65ac18b1f6d7c7875' """ return bytes(self._xmss.getSKSeed()) @staticmethod # NOTE: USED EXTERNALLY!!! 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 def SIGN(self, message): # type: (bytes) -> bytes """ :param message: :return: >>> from qrl.crypto.doctest_data import *; bin2hstr(XMSS(4, xmss_test_seed1).SIGN(str2bin("test_message"))) == xmss_sign_expected1 True >>> from qrl.crypto.doctest_data import *; bin2hstr(XMSS(4, xmss_test_seed2).SIGN(str2bin("test_message"))) == xmss_sign_expected2 True """ return bytes(self._xmss.sign(message)) def list_addresses(self): """ List the addresses derived in the main tree :return: """ addr_arr = [] for addr in self.addresses: addr_arr.append(addr[1]) return addr_arr
def __init__(self, tree_height, seed=None): """ :param tree_height: height of the tree to generate. number of OTS keypairs=2**tree_height :param seed: >>> from qrl.crypto.doctest_data import *; XMSS(4, mnemonic2bin(xmss_mnemonic_test1, wordlist)).get_address() 'Q572721d2221f1d43b18eecacb945221f1156f1e2f519b71e3def43d761e88f3af72feb52' >>> from qrl.crypto.doctest_data import *; XMSS(4, mnemonic2bin(xmss_mnemonic_test2, wordlist)).get_address() 'Q578230464f0550df33f1bad86b725ce6e6c5e278c5d03a100fb93c1d282daec21b2422f2' >>> from qrl.crypto.doctest_data import *; XMSS(4, mnemonic2bin(xmss_mnemonic_test2, wordlist)).get_address() 'Q578230464f0550df33f1bad86b725ce6e6c5e278c5d03a100fb93c1d282daec21b2422f2' # NEW TESTS >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getHeight() 4 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getSecretKeySize() 132 >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getSignatureSize() 2308 >>> from qrl.crypto.doctest_data import *; len(XMSS(4, xmss_test_seed1)._xmss.getSK()) == XMSS(4, xmss_test_seed1)._xmss.getSecretKeySize() True >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getPK() ) '26b3bcc104d686ecfd9fdea7b1963384339121430fbe056cab7c3048ea3e4c4e51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSK() ) == xmss_sk_expected1 True >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getRoot() ) '26b3bcc104d686ecfd9fdea7b1963384339121430fbe056cab7c3048ea3e4c4e' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getPKSeed() ) '51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff' >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getIndex() 0 >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSKSeed() ) '5f2eb95ccf6a0e3e7f472c32d234340c20b3fd379dc28b710affcc0cb2afa57b' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed1)._xmss.getSKPRF() ) '3aa40c0f99459afe7efe72eb9517ee8ded49ccd51dab72ebf6bc37d73240bb3a' >>> from qrl.crypto.doctest_data import *; XMSS(4, xmss_test_seed1)._xmss.getAddress('Q') 'Q1d651431536359202ce7095757e3ed66f579a6eab488ac1331486f207c91604016b6a443' >>> from qrl.crypto.doctest_data import *; bin2hstr( XMSS(4, xmss_test_seed2)._xmss.getPK() ) # doctest: +SKIP '' """ self._number_signatures = 2**tree_height self._type = 'XMSS' # FIXME: Set index to appropiate value after restoring self._index = 0 if seed is None: # FIXME: Improve seed generation self._seed = getRandomSeed(48, '') else: if isinstance(seed, str): self._seed = str2bin(seed) else: self._seed = seed # TODO: ##################### # FIXME Seed is fixed!!!!!!!!!!!!!!!!!!!! self._xmss = XmssFast(self._seed, tree_height) # TODO: Need to set an index # data to allow signing of smaller xmss trees/different addresses derived from same SEED.. # position in wallet denoted by first number and address/tree by signatures self.addresses = [(0, self.get_address(), self.get_number_signatures()) ]
def from_height(tree_height: int): seed = getRandomSeed(48, '') return XMSS(XmssFast(seed, tree_height, pyqrllib.SHAKE_128))