mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-23 09:37:31 +00:00
ecc: small API clean-up
This commit is contained in:
parent
288d793893
commit
0a5ad9fda4
8 changed files with 28 additions and 57 deletions
|
@ -26,49 +26,36 @@
|
|||
import base64
|
||||
import hashlib
|
||||
import functools
|
||||
import copy
|
||||
from typing import Union, Tuple, Optional
|
||||
from ctypes import (
|
||||
byref, c_byte, c_int, c_uint, c_char_p, c_size_t, c_void_p, create_string_buffer,
|
||||
CFUNCTYPE, POINTER, cast
|
||||
)
|
||||
|
||||
from .util import bfh, bh2u, assert_bytes, to_bytes, InvalidPassword, profiler, randrange
|
||||
from .crypto import (sha256d, aes_encrypt_with_iv, aes_decrypt_with_iv, hmac_oneshot)
|
||||
from . import constants
|
||||
from .logging import get_logger
|
||||
|
||||
# TODO -->>>
|
||||
import ctypes
|
||||
from ctypes import (
|
||||
byref, c_byte, c_int, c_uint, c_char_p, c_size_t, c_void_p, create_string_buffer,
|
||||
CFUNCTYPE, POINTER, cast
|
||||
)
|
||||
from .ecc_fast import _libsecp256k1, SECP256K1_EC_UNCOMPRESSED
|
||||
# TODO <<<--
|
||||
|
||||
_logger = get_logger(__name__)
|
||||
|
||||
|
||||
def generator():
|
||||
return GENERATOR
|
||||
|
||||
|
||||
def point_at_infinity():
|
||||
return ECPubkey(None)
|
||||
|
||||
|
||||
def string_to_number(b: bytes) -> int:
|
||||
return int.from_bytes(b, byteorder='big', signed=False)
|
||||
|
||||
|
||||
def sig_string_from_der_sig(der_sig: bytes, order=None) -> bytes:
|
||||
def sig_string_from_der_sig(der_sig: bytes) -> bytes:
|
||||
r, s = get_r_and_s_from_der_sig(der_sig)
|
||||
return sig_string_from_r_and_s(r, s)
|
||||
|
||||
|
||||
def der_sig_from_sig_string(sig_string: bytes, order=None) -> bytes:
|
||||
def der_sig_from_sig_string(sig_string: bytes) -> bytes:
|
||||
r, s = get_r_and_s_from_sig_string(sig_string)
|
||||
return der_sig_from_r_and_s(r, s)
|
||||
|
||||
|
||||
def der_sig_from_r_and_s(r: int, s: int, order=None) -> bytes:
|
||||
def der_sig_from_r_and_s(r: int, s: int) -> bytes:
|
||||
sig_string = (int.to_bytes(r, length=32, byteorder="big") +
|
||||
int.to_bytes(s, length=32, byteorder="big"))
|
||||
sig = create_string_buffer(64)
|
||||
|
@ -85,7 +72,7 @@ def der_sig_from_r_and_s(r: int, s: int, order=None) -> bytes:
|
|||
return bytes(der_sig)[:der_sig_size]
|
||||
|
||||
|
||||
def get_r_and_s_from_der_sig(der_sig: bytes, order=None) -> Tuple[int, int]:
|
||||
def get_r_and_s_from_der_sig(der_sig: bytes) -> Tuple[int, int]:
|
||||
assert isinstance(der_sig, bytes)
|
||||
sig = create_string_buffer(64)
|
||||
ret = _libsecp256k1.secp256k1_ecdsa_signature_parse_der(_libsecp256k1.ctx, sig, der_sig, len(der_sig))
|
||||
|
@ -99,7 +86,7 @@ def get_r_and_s_from_der_sig(der_sig: bytes, order=None) -> Tuple[int, int]:
|
|||
return r, s
|
||||
|
||||
|
||||
def get_r_and_s_from_sig_string(sig_string: bytes, order=None) -> Tuple[int, int]:
|
||||
def get_r_and_s_from_sig_string(sig_string: bytes) -> Tuple[int, int]:
|
||||
if not (isinstance(sig_string, bytes) and len(sig_string) == 64):
|
||||
raise Exception("sig_string must be bytes, and 64 bytes exactly")
|
||||
sig = create_string_buffer(64)
|
||||
|
@ -114,7 +101,7 @@ def get_r_and_s_from_sig_string(sig_string: bytes, order=None) -> Tuple[int, int
|
|||
return r, s
|
||||
|
||||
|
||||
def sig_string_from_r_and_s(r: int, s: int, order=None) -> bytes:
|
||||
def sig_string_from_r_and_s(r: int, s: int) -> bytes:
|
||||
sig_string = (int.to_bytes(r, length=32, byteorder="big") +
|
||||
int.to_bytes(s, length=32, byteorder="big"))
|
||||
sig = create_string_buffer(64)
|
||||
|
@ -250,12 +237,12 @@ class ECPubkey(object):
|
|||
|
||||
other %= CURVE_ORDER
|
||||
if self.is_at_infinity() or other == 0:
|
||||
return point_at_infinity()
|
||||
return POINT_AT_INFINITY
|
||||
pubkey = self._to_libsecp256k1_pubkey_ptr()
|
||||
|
||||
ret = _libsecp256k1.secp256k1_ec_pubkey_tweak_mul(_libsecp256k1.ctx, pubkey, other.to_bytes(32, byteorder="big"))
|
||||
if not ret:
|
||||
return point_at_infinity()
|
||||
return POINT_AT_INFINITY
|
||||
return ECPubkey._from_libsecp256k1_pubkey_ptr(pubkey)
|
||||
|
||||
def __rmul__(self, other: int):
|
||||
|
@ -276,7 +263,7 @@ class ECPubkey(object):
|
|||
array_of_pubkey_ptrs = (c_char_p * 2)(pubkey1, pubkey2)
|
||||
ret = _libsecp256k1.secp256k1_ec_pubkey_combine(_libsecp256k1.ctx, pubkey_sum, array_of_pubkey_ptrs, 2)
|
||||
if not ret:
|
||||
return point_at_infinity()
|
||||
return POINT_AT_INFINITY
|
||||
return ECPubkey._from_libsecp256k1_pubkey_ptr(pubkey_sum)
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
|
@ -345,7 +332,7 @@ class ECPubkey(object):
|
|||
return CURVE_ORDER
|
||||
|
||||
def is_at_infinity(self):
|
||||
return self == point_at_infinity()
|
||||
return self == POINT_AT_INFINITY
|
||||
|
||||
@classmethod
|
||||
def is_pubkey_bytes(cls, b: bytes):
|
||||
|
@ -359,6 +346,7 @@ class ECPubkey(object):
|
|||
GENERATOR = ECPubkey(bytes.fromhex('0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'
|
||||
'483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'))
|
||||
CURVE_ORDER = 0xFFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_BAAEDCE6_AF48A03B_BFD25E8C_D0364141
|
||||
POINT_AT_INFINITY = ECPubkey(None)
|
||||
|
||||
|
||||
def msg_magic(message: bytes) -> bytes:
|
||||
|
@ -414,7 +402,7 @@ class ECPrivkey(ECPubkey):
|
|||
raise InvalidECPointException('Invalid secret scalar (not within curve order)')
|
||||
self.secret_scalar = secret
|
||||
|
||||
pubkey = generator() * secret
|
||||
pubkey = GENERATOR * secret
|
||||
super().__init__(pubkey.get_public_key_bytes(compressed=False))
|
||||
|
||||
@classmethod
|
||||
|
@ -450,7 +438,7 @@ class ECPrivkey(ECPubkey):
|
|||
def get_secret_bytes(self) -> bytes:
|
||||
return int.to_bytes(self.secret_scalar, length=32, byteorder='big', signed=False)
|
||||
|
||||
def sign(self, msg_hash: bytes, sigencode=None, sigdecode=None) -> bytes:
|
||||
def sign(self, msg_hash: bytes, sigencode=None) -> bytes:
|
||||
if not (isinstance(msg_hash, bytes) and len(msg_hash) == 32):
|
||||
raise Exception("msg_hash to be signed must be bytes, and 32 bytes exactly")
|
||||
if sigencode is None:
|
||||
|
@ -481,13 +469,11 @@ class ECPrivkey(ECPubkey):
|
|||
sig_string = sig_string_from_r_and_s(r, s)
|
||||
self.verify_message_hash(sig_string, msg_hash)
|
||||
|
||||
sig = sigencode(r, s, CURVE_ORDER)
|
||||
sig = sigencode(r, s)
|
||||
return sig
|
||||
|
||||
def sign_transaction(self, hashed_preimage: bytes) -> bytes:
|
||||
return self.sign(hashed_preimage,
|
||||
sigencode=der_sig_from_r_and_s,
|
||||
sigdecode=get_r_and_s_from_der_sig)
|
||||
return self.sign(hashed_preimage, sigencode=der_sig_from_r_and_s)
|
||||
|
||||
def sign_message(self, message: bytes, is_compressed: bool, algo=lambda x: sha256d(msg_magic(x))) -> bytes:
|
||||
def bruteforce_recid(sig_string):
|
||||
|
@ -503,9 +489,7 @@ class ECPrivkey(ECPubkey):
|
|||
|
||||
message = to_bytes(message, 'utf8')
|
||||
msg_hash = algo(message)
|
||||
sig_string = self.sign(msg_hash,
|
||||
sigencode=sig_string_from_r_and_s,
|
||||
sigdecode=get_r_and_s_from_sig_string)
|
||||
sig_string = self.sign(msg_hash, sigencode=sig_string_from_r_and_s)
|
||||
sig65, recid = bruteforce_recid(sig_string)
|
||||
return sig65
|
||||
|
||||
|
|
|
@ -109,10 +109,6 @@ def load_library():
|
|||
return None
|
||||
|
||||
|
||||
def is_using_fast_ecc():
|
||||
return True # TODO rm
|
||||
|
||||
|
||||
try:
|
||||
_libsecp256k1 = load_library()
|
||||
except BaseException as e:
|
||||
|
|
|
@ -615,7 +615,7 @@ class Old_KeyStore(MasterPublicKeyMixin, Deterministic_KeyStore):
|
|||
def get_pubkey_from_mpk(cls, mpk, for_change, n) -> bytes:
|
||||
z = cls.get_sequence(mpk, for_change, n)
|
||||
master_public_key = ecc.ECPubkey(bfh('04'+mpk))
|
||||
public_key = master_public_key + z*ecc.generator()
|
||||
public_key = master_public_key + z*ecc.GENERATOR
|
||||
return public_key.get_public_key_bytes(compressed=False)
|
||||
|
||||
@lru_cache(maxsize=None)
|
||||
|
|
|
@ -1039,7 +1039,7 @@ class Peer(Logger):
|
|||
timestamp=now.to_bytes(4, byteorder="big"),
|
||||
)
|
||||
sighash = sha256d(chan_upd[2 + 64:])
|
||||
sig = ecc.ECPrivkey(self.privkey).sign(sighash, sig_string_from_r_and_s, get_r_and_s_from_sig_string)
|
||||
sig = ecc.ECPrivkey(self.privkey).sign(sighash, sig_string_from_r_and_s)
|
||||
message_type, payload = decode_msg(chan_upd)
|
||||
payload['signature'] = sig
|
||||
chan_upd = encode_msg(message_type, **payload)
|
||||
|
@ -1071,8 +1071,8 @@ class Peer(Logger):
|
|||
)
|
||||
to_hash = chan_ann[256+2:]
|
||||
h = sha256d(to_hash)
|
||||
bitcoin_signature = ecc.ECPrivkey(chan.config[LOCAL].multisig_key.privkey).sign(h, sig_string_from_r_and_s, get_r_and_s_from_sig_string)
|
||||
node_signature = ecc.ECPrivkey(self.privkey).sign(h, sig_string_from_r_and_s, get_r_and_s_from_sig_string)
|
||||
bitcoin_signature = ecc.ECPrivkey(chan.config[LOCAL].multisig_key.privkey).sign(h, sig_string_from_r_and_s)
|
||||
node_signature = ecc.ECPrivkey(self.privkey).sign(h, sig_string_from_r_and_s)
|
||||
self.send_message("announcement_signatures",
|
||||
channel_id=chan.channel_id,
|
||||
short_channel_id=chan.short_channel_id,
|
||||
|
|
|
@ -254,7 +254,7 @@ def privkey_to_pubkey(priv: bytes) -> bytes:
|
|||
return ecc.ECPrivkey(priv[:32]).get_public_key_bytes()
|
||||
|
||||
def derive_pubkey(basepoint: bytes, per_commitment_point: bytes) -> bytes:
|
||||
p = ecc.ECPubkey(basepoint) + ecc.generator() * ecc.string_to_number(sha256(per_commitment_point + basepoint))
|
||||
p = ecc.ECPubkey(basepoint) + ecc.GENERATOR * ecc.string_to_number(sha256(per_commitment_point + basepoint))
|
||||
return p.get_public_key_bytes()
|
||||
|
||||
def derive_privkey(secret: int, per_commitment_point: bytes) -> int:
|
||||
|
|
|
@ -40,7 +40,6 @@ from .lntransport import LNTransport, LNResponderTransport
|
|||
from .lnpeer import Peer, LN_P2P_NETWORK_TIMEOUT
|
||||
from .lnaddr import lnencode, LnAddr, lndecode
|
||||
from .ecc import der_sig_from_sig_string
|
||||
from .ecc_fast import is_using_fast_ecc
|
||||
from .lnchannel import Channel
|
||||
from .lnchannel import channel_states, peer_states
|
||||
from . import lnutil
|
||||
|
@ -303,7 +302,6 @@ class LNGossip(LNWorker):
|
|||
self.localfeatures |= LnLocalFeatures.GOSSIP_QUERIES_OPT
|
||||
self.localfeatures |= LnLocalFeatures.GOSSIP_QUERIES_REQ
|
||||
self.unknown_ids = set()
|
||||
assert is_using_fast_ecc(), "verifying LN gossip msgs without libsecp256k1 is hopeless"
|
||||
|
||||
def start_network(self, network: 'Network'):
|
||||
assert network
|
||||
|
|
|
@ -100,7 +100,7 @@ class Test_bitcoin(ElectrumTestCase):
|
|||
self._do_test_crypto(message)
|
||||
|
||||
def _do_test_crypto(self, message):
|
||||
G = ecc.generator()
|
||||
G = ecc.GENERATOR
|
||||
_r = G.order()
|
||||
pvk = randrange(_r)
|
||||
|
||||
|
@ -128,11 +128,11 @@ class Test_bitcoin(ElectrumTestCase):
|
|||
|
||||
@needs_test_with_all_ecc_implementations
|
||||
def test_ecc_sanity(self):
|
||||
G = ecc.generator()
|
||||
G = ecc.GENERATOR
|
||||
n = G.order()
|
||||
self.assertEqual(ecc.CURVE_ORDER, n)
|
||||
inf = n * G
|
||||
self.assertEqual(ecc.point_at_infinity(), inf)
|
||||
self.assertEqual(ecc.POINT_AT_INFINITY, inf)
|
||||
self.assertTrue(inf.is_at_infinity())
|
||||
self.assertFalse(G.is_at_infinity())
|
||||
self.assertEqual(11 * G, 7 * G + 4 * G)
|
||||
|
|
|
@ -70,7 +70,6 @@ from .address_synchronizer import (AddressSynchronizer, TX_HEIGHT_LOCAL,
|
|||
from .util import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED, PR_INFLIGHT
|
||||
from .contacts import Contacts
|
||||
from .interface import NetworkException
|
||||
from .ecc_fast import is_using_fast_ecc
|
||||
from .mnemonic import Mnemonic
|
||||
from .logging import get_logger
|
||||
from .lnworker import LNWallet
|
||||
|
@ -270,9 +269,6 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
|
|||
def init_lightning(self):
|
||||
if self.db.get('lightning_privkey2'):
|
||||
return
|
||||
if not is_using_fast_ecc():
|
||||
raise Exception('libsecp256k1 library not available. '
|
||||
'Verifying Lightning channels is too computationally expensive without libsecp256k1, aborting.')
|
||||
# TODO derive this deterministically from wallet.keystore at keystore generation time
|
||||
# probably along a hardened path ( lnd-equivalent would be m/1017'/coinType'/ )
|
||||
seed = os.urandom(32)
|
||||
|
@ -2085,9 +2081,6 @@ class Deterministic_Wallet(Abstract_Wallet):
|
|||
|
||||
@profiler
|
||||
def try_detecting_internal_addresses_corruption(self):
|
||||
if not is_using_fast_ecc():
|
||||
self.logger.info("internal address corruption test skipped due to missing libsecp256k1")
|
||||
return
|
||||
addresses_all = self.get_addresses()
|
||||
# sample 1: first few
|
||||
addresses_sample1 = addresses_all[:10]
|
||||
|
|
Loading…
Add table
Reference in a new issue