drop dependency on cryptography library in wallet module

This commit is contained in:
Lex Berezhny 2022-01-01 13:13:03 -05:00
parent f78e3825ca
commit ac201c718e
2 changed files with 34 additions and 23 deletions

View file

@ -92,6 +92,10 @@ class PublicKey(_KeyBase):
else: else:
self.verifying_key = self._verifying_key_from_pubkey(pubkey) self.verifying_key = self._verifying_key_from_pubkey(pubkey)
@classmethod
def from_compressed(cls, public_key_bytes, ledger=None) -> 'PublicKey':
return cls(ledger, public_key_bytes, bytes((0,)*32), 0, 0)
@classmethod @classmethod
def _verifying_key_from_pubkey(cls, pubkey): def _verifying_key_from_pubkey(cls, pubkey):
""" Converts a 33-byte compressed pubkey into an coincurve.PublicKey object. """ """ Converts a 33-byte compressed pubkey into an coincurve.PublicKey object. """
@ -137,9 +141,32 @@ class PublicKey(_KeyBase):
self.pubkey_bytes self.pubkey_bytes
) )
def verify(self, signature, data): def verify(self, signature, data) -> bool:
""" Produce a signature for piece of data by double hashing it and signing the hash. """ """ Verify that a signature is valid for data. """
return self.verifying_key.verify(signature, data, hasher=double_sha256)
if len(signature) != 64:
raise Exception('invalid signature length')
key = self.verifying_key
raw_signature = libsecp256k1_ffi.new('secp256k1_ecdsa_signature *')
parsed = libsecp256k1.secp256k1_ecdsa_signature_parse_compact(
key.context.ctx, raw_signature, signature
)
assert parsed == 1
normalized_signature = libsecp256k1_ffi.new('secp256k1_ecdsa_signature *')
libsecp256k1.secp256k1_ecdsa_signature_normalize(
key.context.ctx, normalized_signature, raw_signature
)
verified = libsecp256k1.secp256k1_ecdsa_verify(
key.context.ctx, normalized_signature, data, key.public_key
)
return bool(verified)
class PrivateKey(_KeyBase): class PrivateKey(_KeyBase):

View file

@ -4,13 +4,6 @@ import typing
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from typing import List, Iterable, Optional, Tuple from typing import List, Iterable, Optional, Tuple
from coincurve import PublicKey as cPublicKey
from coincurve.ecdsa import deserialize_compact, cdata_to_der
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import Prehashed
from cryptography.exceptions import InvalidSignature
from lbry.error import InsufficientFundsError from lbry.error import InsufficientFundsError
from lbry.crypto.hash import hash160, sha256 from lbry.crypto.hash import hash160, sha256
from lbry.crypto.base58 import Base58 from lbry.crypto.base58 import Base58
@ -25,7 +18,7 @@ from .constants import COIN, NULL_HASH32
from .bcd_data_stream import BCDataStream from .bcd_data_stream import BCDataStream
from .hash import TXRef, TXRefImmutable from .hash import TXRef, TXRefImmutable
from .util import ReadOnlyList from .util import ReadOnlyList
from .bip32 import PrivateKey from .bip32 import PrivateKey, PublicKey
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
from lbry.wallet.account import Account from lbry.wallet.account import Account
@ -426,18 +419,9 @@ class Output(InputOutput):
@staticmethod @staticmethod
def is_signature_valid(signature, digest, public_key_bytes): def is_signature_valid(signature, digest, public_key_bytes):
signature = cdata_to_der(deserialize_compact(signature)) return PublicKey\
public_key = cPublicKey(public_key_bytes) .from_compressed(public_key_bytes)\
is_valid = public_key.verify(signature, digest, None) .verify(signature, digest)
if not is_valid: # try old way
# ytsync signed claims don't seem to validate with coincurve
try:
pk = ec.EllipticCurvePublicKey.from_encoded_point(ec.SECP256K1(), public_key_bytes)
pk.verify(signature, digest, ec.ECDSA(Prehashed(hashes.SHA256())))
return True
except (ValueError, InvalidSignature):
pass
return is_valid
def is_signed_by(self, channel: 'Output', ledger=None): def is_signed_by(self, channel: 'Output', ledger=None):
return self.is_signature_valid( return self.is_signature_valid(