ecc.py 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet
  4. # Copyright (C)2013-2024 The MMGen Project <mmgen@tuta.io>
  5. # Licensed under the GNU General Public License, Version 3:
  6. # https://www.gnu.org/licenses
  7. # Public project repositories:
  8. # https://github.com/mmgen/mmgen-wallet
  9. # https://gitlab.com/mmgen/mmgen-wallet
  10. """
  11. test.include.ecc: elliptic curve utilities for the MMGen test suite
  12. """
  13. import ecdsa
  14. from mmgen.proto.secp256k1.keygen import pubkey_format
  15. def _pubkey_to_pub_point(vk_bytes):
  16. try:
  17. return ecdsa.VerifyingKey.from_string(vk_bytes, curve=ecdsa.curves.SECP256k1).pubkey.point
  18. except Exception as e:
  19. raise ValueError(f'invalid pubkey {vk_bytes.hex()}\n {type(e).__name__}: {e}')
  20. def _check_pub_point(pub_point,vk_bytes,addend_bytes=None):
  21. if pub_point is ecdsa.ellipticcurve.INFINITY:
  22. raise ValueError(
  23. 'pubkey {}{} produced key with point at infinity!'.format(
  24. vk_bytes.hex(),
  25. '' if addend_bytes is None else f' + {addend_bytes.hex()}'))
  26. def pubkey_check_pyecdsa(vk_bytes):
  27. _check_pub_point(_pubkey_to_pub_point(vk_bytes), vk_bytes)
  28. def pubkey_tweak_add_pyecdsa(vk_bytes,pk_addend_bytes):
  29. pk_addend = int.from_bytes(pk_addend_bytes, byteorder='big')
  30. point_sum = (
  31. _pubkey_to_pub_point(vk_bytes) +
  32. ecdsa.SigningKey.from_secret_exponent(pk_addend, curve=ecdsa.SECP256k1).verifying_key.pubkey.point
  33. )
  34. _check_pub_point(point_sum, vk_bytes, pk_addend_bytes)
  35. return pubkey_format(
  36. ecdsa.VerifyingKey.from_public_point(point_sum, curve=ecdsa.curves.SECP256k1).to_string(),
  37. compressed = len(vk_bytes) == 33)