Skip to content

Commit

Permalink
introduced btclib bindings to libsecp256k1
Browse files Browse the repository at this point in the history
* Removed raw ffi
* Removed coincurve
* Added btclib_libsecp256k1 tests
  • Loading branch information
giacomocaironi committed Dec 1, 2021
1 parent 0ae63d9 commit d19b45e
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 43 deletions.
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ backports-datetime-fromisoformat>=1.0.0; python_version<'3.7'
dataclasses>=0.8; python_version<'3.7'
types-dataclasses>=0.1.5; python_version<'3.7'

# for libsecp256k1
coincurve
#optional
btclib_libsecp256k1
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"dataclasses>=0.8; python_version<'3.7'",
"dataclasses_json",
],
extra_requires={"secp256k1": ["btclib_libsecp256k1"]},
keywords=(
"bitcoin cryptography elliptic-curves ecdsa schnorr RFC-6979 "
"bip32 bip39 electrum base58 bech32 segwit message-signing "
Expand Down
62 changes: 21 additions & 41 deletions tests/ecc/test_dsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
from hashlib import sha1

import pytest
from coincurve._libsecp256k1 import ( # type: ignore # pylint: disable=no-name-in-module
ffi,
lib,
)

from btclib.alias import INF
from btclib.ecc import dsa
Expand All @@ -29,43 +25,6 @@
from btclib.hashes import reduce_to_hlen
from tests.ecc.test_curve import low_card_curves

GLOBAL_CTX = ffi.gc(
lib.secp256k1_context_create(
lib.SECP256K1_CONTEXT_SIGN | lib.SECP256K1_CONTEXT_VERIFY
),
lib.secp256k1_context_destroy,
)

CDATA_SIG_LENGTH = 64


def test_libsecp256k1() -> None:
msg = "Satoshi Nakamoto".encode()

q, _ = dsa.gen_keys(0x1)
sig = dsa.sign(msg, q)

msg_hash = reduce_to_hlen(msg)
secret = q.to_bytes(32, "big")

c_sig = ffi.new("secp256k1_ecdsa_signature *")
assert lib.secp256k1_ecdsa_sign(
GLOBAL_CTX, c_sig, msg_hash, secret, ffi.NULL, ffi.NULL
), "libsecp256k1 signature failed"

output = ffi.new(f"unsigned char[{CDATA_SIG_LENGTH}]")
assert lib.secp256k1_ecdsa_signature_serialize_compact(
GLOBAL_CTX, output, c_sig
), "libsecp256k1 signature serialization failed"

c_sig_bytes = bytes(ffi.buffer(output, CDATA_SIG_LENGTH))

r = c_sig_bytes[:32]
s = c_sig_bytes[32:]

assert r.hex() == sig.r.to_bytes(32, "big").hex()
assert s.hex() == sig.s.to_bytes(32, "big").hex()


def test_signature() -> None:
msg = "Satoshi Nakamoto".encode()
Expand Down Expand Up @@ -321,3 +280,24 @@ def test_sign_input_type() -> None:
sig = dsa.sign(msg, q)
dsa.assert_as_valid(msg, Q, sig)
dsa.assert_as_valid(msg, Q, sig.serialize())


def test_libsecp256k1() -> None:

try:
import btclib_libsecp256k1.dsa # pylint: disable=import-outside-toplevel
except ImportError: # pragma: no cover
pytest.skip()

prvkey, Q = dsa.gen_keys(0x1)
pubkey_bytes = bytes_from_point(Q)
msg = "Satoshi Nakamoto".encode()
msg_hash = reduce_to_hlen(msg)

libsecp256k1_sig = btclib_libsecp256k1.dsa.sign(msg_hash, prvkey)
btclib_sig = dsa.sign_(msg_hash, prvkey)

assert btclib_libsecp256k1.dsa.verify(
msg_hash, pubkey_bytes, btclib_sig.serialize()
)
assert dsa.verify(msg, prvkey, libsecp256k1_sig)
21 changes: 21 additions & 0 deletions tests/ecc/test_ssa.py
Original file line number Diff line number Diff line change
Expand Up @@ -711,3 +711,24 @@ def test_threshold() -> None:
# ADDITIONAL PHASE: reconstruction of the private key ###
secret = (omega1 * alpha1 + omega3 * alpha3) % ec.n
assert (q1 + q2 + q3) % ec.n in (secret, ec.n - secret)


def test_libsecp256k1() -> None:

try:
import btclib_libsecp256k1.ssa # pylint: disable=import-outside-toplevel
except ImportError: # pragma: no cover
pytest.skip()

prvkey, X_Q = ssa.gen_keys(0x1)
pubkey_bytes = X_Q.to_bytes(32, "big")
msg = "Satoshi Nakamoto".encode()
msg_hash = reduce_to_hlen(msg)

libsecp256k1_sig = btclib_libsecp256k1.ssa.sign(msg_hash, prvkey)
btclib_sig = ssa.sign_(msg_hash, prvkey)

assert btclib_libsecp256k1.ssa.verify(
msg_hash, pubkey_bytes, btclib_sig.serialize()
)
assert ssa.verify(msg, X_Q, libsecp256k1_sig)

0 comments on commit d19b45e

Please sign in to comment.