Skip to content

Commit

Permalink
Merge 302461b into f78e382
Browse files Browse the repository at this point in the history
  • Loading branch information
eukreign committed Jan 17, 2022
2 parents f78e382 + 302461b commit d1282ce
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 23 deletions.
36 changes: 33 additions & 3 deletions lbry/wallet/bip32.py
Expand Up @@ -92,6 +92,10 @@ def __init__(self, ledger, pubkey, chain_code, n, depth, parent=None):
else:
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
def _verifying_key_from_pubkey(cls, pubkey):
""" Converts a 33-byte compressed pubkey into an coincurve.PublicKey object. """
Expand Down Expand Up @@ -137,9 +141,35 @@ def extended_key(self):
self.pubkey_bytes
)

def verify(self, signature, data):
""" Produce a signature for piece of data by double hashing it and signing the hash. """
return self.verifying_key.verify(signature, data, hasher=double_sha256)
def verify(self, signature, digest) -> bool:
""" Verify that a signature is valid for a 32 byte digest. """

if len(signature) != 64:
raise ValueError('Signature must be 64 bytes long.')

if len(digest) != 32:
raise ValueError('Digest must be 32 bytes long.')

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, digest, key.public_key
)

return bool(verified)


class PrivateKey(_KeyBase):
Expand Down
24 changes: 4 additions & 20 deletions lbry/wallet/transaction.py
Expand Up @@ -4,13 +4,6 @@
from binascii import hexlify, unhexlify
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.crypto.hash import hash160, sha256
from lbry.crypto.base58 import Base58
Expand All @@ -25,7 +18,7 @@
from .bcd_data_stream import BCDataStream
from .hash import TXRef, TXRefImmutable
from .util import ReadOnlyList
from .bip32 import PrivateKey
from .bip32 import PrivateKey, PublicKey

if typing.TYPE_CHECKING:
from lbry.wallet.account import Account
Expand Down Expand Up @@ -426,18 +419,9 @@ def get_signature_digest(self, ledger):

@staticmethod
def is_signature_valid(signature, digest, public_key_bytes):
signature = cdata_to_der(deserialize_compact(signature))
public_key = cPublicKey(public_key_bytes)
is_valid = public_key.verify(signature, digest, None)
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
return PublicKey\
.from_compressed(public_key_bytes)\
.verify(signature, digest)

def is_signed_by(self, channel: 'Output', ledger=None):
return self.is_signature_valid(
Expand Down

0 comments on commit d1282ce

Please sign in to comment.