From db0a2c082acf3ad591439b3af90ad4e000cf2f09 Mon Sep 17 00:00:00 2001 From: Michal Rostecki Date: Sun, 26 Apr 2020 19:55:15 +0200 Subject: [PATCH] pyln-proto: Use only coincurve for libsecp256k1 bindings secp256k1 Python library is not maintained anymore and coincurve was already used in the `wire` module. Changelog-None Signed-off-by: Michal Rostecki --- contrib/pyln-proto/pyln/proto/invoice.py | 26 ++++++++++-------------- contrib/pyln-proto/requirements.txt | 1 - contrib/pyln-proto/tests/test_invoice.py | 12 +++++++++++ 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/contrib/pyln-proto/pyln/proto/invoice.py b/contrib/pyln-proto/pyln/proto/invoice.py index 558db4eaf..539bc62d6 100755 --- a/contrib/pyln-proto/pyln/proto/invoice.py +++ b/contrib/pyln-proto/pyln/proto/invoice.py @@ -6,7 +6,7 @@ import base58 import bitstring import hashlib import re -import secp256k1 +import coincurve import time import struct @@ -180,14 +180,14 @@ class Invoice(object): def __str__(self): return "Invoice[{}, amount={}{} tags=[{}]]".format( - hexlify(self.pubkey.serialize()).decode('utf-8'), + hexlify(self.pubkey.format()).decode('utf-8'), self.amount, self.currency, ", ".join([k + '=' + str(v) for k, v in self.tags]) ) @property def hexpubkey(self): - return hexlify(self.pubkey.serialize()).decode('ASCII') + return hexlify(self.pubkey.format()).decode('ASCII') @property def hexpaymenthash(self): @@ -273,11 +273,8 @@ class Invoice(object): raise ValueError("Must include either 'd' or 'h'") # We actually sign the hrp, then data (padded to 8 bits with zeroes). - privkey = secp256k1.PrivateKey(bytes(unhexlify(privkey))) - sig = privkey.ecdsa_sign_recoverable(bytearray([ord(c) for c in hrp]) + data.tobytes()) - # This doesn't actually serialize, but returns a pair of values :( - sig, recid = privkey.ecdsa_recoverable_serialize(sig) - data += bytes(sig) + bytes([recid]) + privkey = coincurve.PrivateKey(secret=bytes(unhexlify(privkey))) + data += privkey.sign_recoverable(bytearray([ord(c) for c in hrp]) + data.tobytes()) return bech32_encode(hrp, bitarray_to_u5(data)) @@ -374,8 +371,7 @@ class Invoice(object): if data_length != 53: inv.unknown_tags.append((tag, tagdata)) continue - inv.pubkey = secp256k1.PublicKey(flags=secp256k1.ALL_FLAGS) - inv.pubkey.deserialize(trim_to_bytes(tagdata)) + inv.pubkey = coincurve.PublicKey(trim_to_bytes(tagdata)) elif tag == 'c': inv.min_final_cltv_expiry = tagdata.uint @@ -395,11 +391,11 @@ class Invoice(object): if not inv.pubkey.ecdsa_verify(bytearray([ord(c) for c in hrp]) + data.tobytes(), inv.signature): raise ValueError('Invalid signature') else: # Recover pubkey from signature. - inv.pubkey = secp256k1.PublicKey(flags=secp256k1.ALL_FLAGS) - inv.signature = inv.pubkey.ecdsa_recoverable_deserialize( - sigdecoded[0:64], sigdecoded[64]) - inv.pubkey.public_key = inv.pubkey.ecdsa_recover( - bytearray([ord(c) for c in hrp]) + data.tobytes(), inv.signature) + inv.signature = coincurve.ecdsa.deserialize_recoverable( + sigdecoded[0:65]) + inv.pubkey = coincurve.PublicKey.from_signature_and_message( + sigdecoded[0:65], + bytearray([ord(c) for c in hrp]) + data.tobytes()) return inv diff --git a/contrib/pyln-proto/requirements.txt b/contrib/pyln-proto/requirements.txt index 30e6d1c89..98a17156b 100644 --- a/contrib/pyln-proto/requirements.txt +++ b/contrib/pyln-proto/requirements.txt @@ -2,4 +2,3 @@ bitstring==3.1.6 cryptography==2.8 coincurve==13.0.0 base58==1.0.2 -secp256k1==0.13.2 diff --git a/contrib/pyln-proto/tests/test_invoice.py b/contrib/pyln-proto/tests/test_invoice.py index 4e3532784..7d4334c86 100644 --- a/contrib/pyln-proto/tests/test_invoice.py +++ b/contrib/pyln-proto/tests/test_invoice.py @@ -1,6 +1,7 @@ from pyln.proto import Invoice from decimal import Decimal from bitstring import ConstBitStream +import binascii def test_decode(): @@ -13,3 +14,14 @@ def test_decode(): assert(inv.amount == Decimal('0.000001')) assert(inv.featurebits == ConstBitStream('0x28200')) print(inv) + + +def test_encode(): + inv = Invoice(paymenthash=binascii.unhexlify("76272b9b95b14eb6bece3cd051006d8aabac63c3a50bd7ea2bb53612b0a9324b"), + amount=Decimal('0.000001'), + tags=[('d', 'test_pay_routeboost2'), + ('x', 604800)], + date=1579298293) + privkey = 'c28a9f80738f770d527803a566cf6fc3edf6cea586c4fc4a5223a5ad797e1ac3' + i = inv.encode(privkey) + assert(i == 'lnbc1u1p0zyt04pp5wcnjhxu4k98td0kw8ng9zqrd3246cc7r559a063tk5mp9v9fxf9sdpqw3jhxazlwpshjhmjda6hgetzdahhxapjxqyjw5q0s43wfg4f6yl200hc805kc9u97dp7m6j98fz33uzf4t6kp73trcz8fxkrpass063j2j4quxjr4th2r72lk27tm2aw383zgnl8zpgajsq5kmll8')