ut_xmrseed.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #!/usr/bin/env python3
  2. """
  3. test/unit_tests_d/ut_xmrseed: Monero mnemonic unit test for the MMGen suite
  4. """
  5. from mmgen.common import *
  6. from mmgen.exception import *
  7. class unit_test(object):
  8. vectors = ( # private keys are reduced
  9. ( '148d78d2aba7dbca5cd8f6abcfb0b3c009ffbdbea1ff373d50ed94d78286640e', # Monero repo
  10. 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches ' +
  11. 'lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted',
  12. ),
  13. ( 'e8164dda6d42bd1e261a3406b2038dcbddadbeefdeadbeefdeadbeefdeadbe0f',
  14. 'viewpoint donuts ardent template unveil agile meant unafraid urgent athlete rustled mime azure ' +
  15. 'jaded hawk baby jagged haystack baby jagged haystack ramped oncoming point template'
  16. ),
  17. ( '6900dea9753f5c7ced87b53bdcfb109a8417bca6a2797a708194157b227fb60b',
  18. 'criminal bamboo scamper gnaw limits womanly wrong tuition birth mundane donuts square cohesive ' +
  19. 'dolphin titans narrate fuel saved wrap aloof magically mirror together update wrap'
  20. ),
  21. ( '0000000000000000000000000000000000000000000000000000000000000001',
  22. 'abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey ' +
  23. 'abbey abbey abbey abbey abbey bamboo jaws jerseys abbey'
  24. ),
  25. ( '1c95988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0f',
  26. 'powder directed sayings enmity bacon vapidly entrance bumper noodles iguana sleepless nasty flying ' +
  27. 'soil software foamy solved soggy foamy solved soggy jury yawning ankle solved'
  28. ),
  29. ( '2c94988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0f',
  30. 'memoir apart olive enmity bacon vapidly entrance bumper noodles iguana sleepless nasty flying soil ' +
  31. 'software foamy solved soggy foamy solved soggy jury yawning ankle foamy'
  32. ),
  33. ( '4bb0288c9673b69fa68c2174851884abbaaedce6af48a03bbfd25e8cd0364102',
  34. 'rated bicycle pheasants dejected pouch fizzle shipped rash citadel queen avatar sample muzzle mews ' +
  35. 'jagged origin yeti dunes obtains godfather unbending pastry vortex washing citadel'
  36. ),
  37. ( '4bb0288c9673b69fa68c2174851884abbaaedce6af48a03bbfd25e8cd0364100',
  38. 'rated bicycle pheasants dejected pouch fizzle shipped rash citadel queen avatar sample muzzle mews ' +
  39. 'jagged origin yeti dunes obtains godfather unbending kangaroo auctions audio citadel'
  40. ),
  41. ( '1d95988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0e',
  42. 'pram distance scamper enmity bacon vapidly entrance bumper noodles iguana sleepless nasty flying ' +
  43. 'soil software foamy solved soggy foamy solved soggy hashing mullet onboard solved'
  44. ),
  45. ( 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0f',
  46. 'foamy solved soggy foamy solved soggy foamy solved soggy foamy solved soggy foamy solved soggy ' +
  47. 'foamy solved soggy foamy solved soggy jury yawning ankle soggy'
  48. ),
  49. )
  50. def run_test(self,name,ut):
  51. def test_fromhex(b):
  52. vmsg('')
  53. qmsg('Checking seed to mnemonic conversion:')
  54. for privhex,chk in self.vectors:
  55. vmsg(f' {chk}')
  56. chk = tuple(chk.split())
  57. res = b.fromhex(privhex)
  58. if use_moneropy:
  59. mp_chk = tuple( mnemonic.mn_encode(privhex) )
  60. assert res[:24] == mp_chk, f'check failed:\nres: {res[:24]}\nchk: {chk}'
  61. assert res == chk, f'check failed:\nres: {res}\nchk: {chk}'
  62. def test_tohex(b):
  63. vmsg('')
  64. qmsg('Checking mnemonic to seed conversion:')
  65. for chk,words in self.vectors:
  66. vmsg(f' {chk}')
  67. res = b.tohex( words.split() )
  68. if use_moneropy:
  69. mp_chk = mnemonic.mn_decode( words.split() )
  70. assert res == mp_chk, f'check failed:\nres: {res}\nchk: {mp_chk}'
  71. assert res == chk, f'check failed:\nres: {res}\nchk: {chk}'
  72. msg_r('Testing xmrseed conversion routines...')
  73. qmsg('')
  74. from mmgen.xmrseed import xmrseed
  75. b = xmrseed()
  76. b.check_wordlist()
  77. try:
  78. from moneropy import mnemonic
  79. except ImportError:
  80. use_moneropy = False
  81. ymsg('Warning: unable to import moneropy, skipping external library checks')
  82. else:
  83. use_moneropy = True
  84. test_fromhex(b)
  85. test_tohex(b)
  86. vmsg('')
  87. qmsg('Checking error handling:')
  88. bad_chksum_mn = ('abbey ' * 21 + 'bamboo jaws jerseys donuts').split()
  89. bad_word_mn = "admire zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo".split()
  90. bad_seed = 'deadbeef'
  91. good_mn = self.vectors[0][1].split()
  92. good_hex = self.vectors[0][0]
  93. bad_len_mn = good_mn[:22]
  94. th = b.tohex
  95. fh = b.fromhex
  96. bad_data = (
  97. ('hex', 'HexadecimalStringError', 'not a hexadecimal', lambda:fh('xx')),
  98. ('seed len', 'SeedLengthError', 'invalid seed byte len', lambda:fh(bad_seed)),
  99. ('mnemonic type', 'AssertionError', 'must be list', lambda:th('string')),
  100. ('pad arg (fromhex)', 'AssertionError', "invalid 'pad' arg", lambda:fh(good_hex,pad=23)),
  101. ('pad arg (tohex)', 'AssertionError', "invalid 'pad' arg", lambda:th(good_mn,pad=23)),
  102. ('word', 'MnemonicError', "not in Monero", lambda:th(bad_word_mn)),
  103. ('checksum', 'MnemonicError', "checksum", lambda:th(bad_chksum_mn)),
  104. ('seed phrase len', 'MnemonicError', "phrase len", lambda:th(bad_len_mn)),
  105. )
  106. ut.process_bad_data(bad_data)
  107. vmsg('')
  108. msg('OK')
  109. return True