ut_ecc.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #!/usr/bin/env python3
  2. """
  3. test.modtest_d.ut_ecc: elliptic curve unit test for the MMGen suite
  4. """
  5. from mmgen.proto.secp256k1.secp256k1 import pubkey_gen, pubkey_tweak_add, pubkey_check
  6. from ..include.common import vmsg
  7. from ..include.ecc import pubkey_tweak_add_pyecdsa
  8. from mmgen.protocol import CoinProtocol
  9. secp256k1_group_order = CoinProtocol.Secp256k1.secp256k1_group_order
  10. class unit_tests:
  11. def pubkey_ops(self, name, ut):
  12. vmsg(' Generating pubkey, adding scalar 123456789 to pubkey:')
  13. pk_addend_bytes = int.to_bytes(123456789, length=32, byteorder='big')
  14. for privkey in (
  15. 'beadcafe' * 8,
  16. f'{1:064x}',
  17. f'{secp256k1_group_order-1:x}',
  18. ):
  19. vmsg(f' privkey = 0x{privkey}')
  20. for compressed, length in ((False, 65), (True, 33)):
  21. vmsg(f' {compressed=}')
  22. pubkey_bytes = pubkey_gen(bytes.fromhex(privkey), int(compressed))
  23. pubkey_check(pubkey_bytes)
  24. vmsg(f' pubkey: {pubkey_bytes.hex()}')
  25. res1 = pubkey_tweak_add(pubkey_bytes, pk_addend_bytes)
  26. pubkey_check(res1)
  27. vmsg(f' tweaked: {res1.hex()}')
  28. res2 = pubkey_tweak_add_pyecdsa(pubkey_bytes, pk_addend_bytes)
  29. pubkey_check(res2)
  30. assert len(res1) == length
  31. assert res1 == res2
  32. return True
  33. def pubkey_errors(self, name, ut):
  34. def gen1(): pubkey_gen(bytes(32), 1)
  35. def gen2(): pubkey_gen(secp256k1_group_order.to_bytes(length=32, byteorder='big'), 1)
  36. def gen3(): pubkey_gen((secp256k1_group_order+1).to_bytes(length=32, byteorder='big'), 1)
  37. def gen4(): pubkey_gen(bytes.fromhex('ff'*32), 1)
  38. def gen5(): pubkey_gen(bytes.fromhex('ab'*31), 1)
  39. def gen6(): pubkey_gen(bytes.fromhex('ab'*33), 1)
  40. pubkey_bytes = pubkey_gen(bytes.fromhex('beadcafe'*8), 1)
  41. def tweak1(): pubkey_tweak_add(pubkey_bytes, bytes(32))
  42. def tweak2(): pubkey_tweak_add(bytes.fromhex('03'*64), int.to_bytes(1, length=32, byteorder='big'))
  43. def check1(): pubkey_check(bytes.fromhex('04'*33))
  44. def check2(): pubkey_check(bytes.fromhex('03'*65))
  45. def check3(): pubkey_check(bytes.fromhex('02'*65))
  46. def check4(): pubkey_check(bytes.fromhex('03'*64))
  47. def check5(): pubkey_check(b'')
  48. bad_data = (
  49. ('privkey == 0', 'ValueError', 'Private key not in allowable range', gen1),
  50. ('privkey == group order', 'ValueError', 'Private key not in allowable range', gen2),
  51. ('privkey == group order+1', 'ValueError', 'Private key not in allowable range', gen3),
  52. ('privkey == 2^256-1', 'ValueError', 'Private key not in allowable range', gen4),
  53. ('len(privkey) == 31', 'ValueError', 'Private key length not 32 bytes', gen5),
  54. ('len(privkey) == 33', 'ValueError', 'Private key length not 32 bytes', gen6),
  55. ('tweak == 0', 'ValueError', 'Tweak not in allowable range', tweak1),
  56. ('pubkey length == 64', 'ValueError', 'Serialized public key length not', tweak2),
  57. ('invalid pubkey (33 bytes)', 'ValueError', 'Invalid first byte', check1),
  58. ('invalid pubkey (65 bytes)', 'ValueError', 'Invalid first byte', check2),
  59. ('invalid pubkey (65 bytes)', 'ValueError', 'Invalid first byte', check3),
  60. ('pubkey length == 64', 'ValueError', 'Serialized public key length not', check4),
  61. ('pubkey length == 0', 'ValueError', 'Serialized public key length not', check5),
  62. )
  63. ut.process_bad_data(bad_data, pfx='')
  64. return True