forked from LBRYCommunity/lbry-sdk
drop dependency on cryptography library in wallet module
This commit is contained in:
parent
f78e3825ca
commit
ac201c718e
2 changed files with 34 additions and 23 deletions
|
@ -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):
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Reference in a new issue