forked from LBRYCommunity/lbry-sdk
Merge pull request #3534 from lbryio/normalize_signatures
drop dependency on cryptography library in wallet module
This commit is contained in:
commit
b5ead91746
2 changed files with 37 additions and 23 deletions
|
@ -92,6 +92,10 @@ class PublicKey(_KeyBase):
|
|||
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. """
|
||||
|
@ -137,9 +141,35 @@ class PublicKey(_KeyBase):
|
|||
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):
|
||||
|
|
|
@ -4,13 +4,6 @@ import typing
|
|||
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
|
||||
|
@ -25,7 +18,7 @@ from .constants import COIN, NULL_HASH32
|
|||
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
|
||||
|
@ -426,18 +419,9 @@ class Output(InputOutput):
|
|||
|
||||
@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(
|
||||
|
|
Loading…
Reference in a new issue