main.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. from eth_utils import (
  2. ValidationError,
  3. )
  4. from eth_keys.datatypes import (
  5. BaseSignature,
  6. LazyBackend,
  7. NonRecoverableSignature,
  8. PrivateKey,
  9. PublicKey,
  10. Signature,
  11. )
  12. from eth_keys.validation import (
  13. validate_message_hash,
  14. )
  15. # These must be aliased due to a scoping issue in mypy
  16. # https://github.com/python/mypy/issues/1775
  17. _PublicKey = PublicKey
  18. _PrivateKey = PrivateKey
  19. _Signature = Signature
  20. _NonRecoverableSignature = NonRecoverableSignature
  21. class KeyAPI(LazyBackend):
  22. PublicKey = PublicKey
  23. PrivateKey = PrivateKey
  24. Signature = Signature
  25. NonRecoverableSignature = NonRecoverableSignature
  26. #
  27. # Proxy method calls to the backends
  28. #
  29. def ecdsa_sign(self, message_hash: bytes, private_key: _PrivateKey) -> _Signature:
  30. validate_message_hash(message_hash)
  31. if not isinstance(private_key, PrivateKey):
  32. raise ValidationError(
  33. "The `private_key` must be an instance of "
  34. "`eth_keys.datatypes.PrivateKey`"
  35. )
  36. signature = self.backend.ecdsa_sign(message_hash, private_key)
  37. if not isinstance(signature, Signature):
  38. raise ValidationError(
  39. "Backend returned an invalid signature. Return value must be "
  40. "an instance of `eth_keys.datatypes.Signature`"
  41. )
  42. return signature
  43. def ecdsa_sign_non_recoverable(
  44. self, message_hash: bytes, private_key: _PrivateKey
  45. ) -> _NonRecoverableSignature:
  46. validate_message_hash(message_hash)
  47. if not isinstance(private_key, PrivateKey):
  48. raise ValidationError(
  49. "The `private_key` must be an instance of "
  50. "`eth_keys.datatypes.PrivateKey`"
  51. )
  52. signature = self.backend.ecdsa_sign_non_recoverable(message_hash, private_key)
  53. if not isinstance(signature, NonRecoverableSignature):
  54. raise ValidationError(
  55. "Backend returned an invalid signature. Return value must be "
  56. "an instance of `eth_keys.datatypes.Signature`"
  57. )
  58. return signature
  59. def ecdsa_verify(
  60. self, message_hash: bytes, signature: BaseSignature, public_key: _PublicKey
  61. ) -> bool:
  62. validate_message_hash(message_hash)
  63. if not isinstance(public_key, PublicKey):
  64. raise ValidationError(
  65. "The `public_key` must be an instance of `eth_keys.datatypes.PublicKey`"
  66. )
  67. if not isinstance(signature, BaseSignature):
  68. raise ValidationError(
  69. "The `signature` must be an instance of "
  70. "`eth_keys.datatypes.BaseSignature`"
  71. )
  72. return self.backend.ecdsa_verify(message_hash, signature, public_key)
  73. def ecdsa_recover(self, message_hash: bytes, signature: _Signature) -> _PublicKey:
  74. validate_message_hash(message_hash)
  75. if not isinstance(signature, Signature):
  76. raise ValidationError(
  77. "The `signature` must be an instance of `eth_keys.datatypes.Signature`"
  78. )
  79. public_key = self.backend.ecdsa_recover(message_hash, signature)
  80. if not isinstance(public_key, _PublicKey):
  81. raise ValidationError(
  82. "Backend returned an invalid public_key. Return value must be "
  83. "an instance of `eth_keys.datatypes.PublicKey`"
  84. )
  85. return public_key
  86. def private_key_to_public_key(self, private_key: _PrivateKey) -> _PublicKey:
  87. if not isinstance(private_key, PrivateKey):
  88. raise ValidationError(
  89. "The `private_key` must be an instance of "
  90. "`eth_keys.datatypes.PrivateKey`"
  91. )
  92. public_key = self.backend.private_key_to_public_key(private_key)
  93. if not isinstance(public_key, PublicKey):
  94. raise ValidationError(
  95. "Backend returned an invalid public_key. Return value must be "
  96. "an instance of `eth_keys.datatypes.PublicKey`"
  97. )
  98. return public_key
  99. # This creates an easy to import backend which will lazily fetch whatever
  100. # backend has been configured at runtime (as opposed to import or instantiation time).
  101. lazy_key_api = KeyAPI(backend=None)