コード例 #1
0
def test_mult_recursive_aff() -> None:
    for ec in all_curves.values():
        assert _mult_recursive_aff(0, ec.G, ec) == INF
        assert _mult_recursive_aff(0, INF, ec) == INF

        assert _mult_recursive_aff(1, INF, ec) == INF
        assert _mult_aff(1, ec.G, ec) == ec.G

        Q = ec._add_aff(ec.G, ec.G)
        assert Q == _mult_recursive_aff(2, ec.G, ec)

        Q = _mult_recursive_aff(ec.n - 1, ec.G, ec)
        assert ec.negate(ec.G) == Q
        assert _mult_recursive_aff(ec.n - 1, INF, ec) == INF

        assert ec._add_aff(Q, ec.G) == INF
        assert _mult_recursive_aff(ec.n, ec.G, ec) == INF
        assert _mult_recursive_aff(ec.n, INF, ec) == INF

        with pytest.raises(BTClibValueError, match="negative m: "):
            _mult_recursive_aff(-1, ec.G, ec)

    for ec in low_card_curves.values():
        for q in range(ec.n):
            Q = _mult_recursive_aff(q, ec.G, ec)
            assert ec.is_on_curve(Q), f"{q}, {ec}"
            QJ = _mult(q, ec.GJ, ec)
            assert ec.is_on_curve(ec._aff_from_jac(QJ)), f"{q}, {ec}"
            assert Q == ec._aff_from_jac(QJ), f"{q}, {ec}"
        assert INF == _mult_recursive_aff(q, INF, ec), f"{q}, {ec}"
        assert ec._jac_equality(INFJ, _mult(q, INFJ, ec)), f"{q}, {ec}"
コード例 #2
0
ファイル: test_curvegroup.py プロジェクト: tunnelr/btclib
def test_mult() -> None:
    for ec in low_card_curves.values():
        for q in range(ec.n):
            Q = _mult_aff(q, ec.G, ec)
            assert ec.is_on_curve(Q), f"{q}, {ec}"
            QJ = _mult(q, ec.GJ, ec)
            assert ec.is_on_curve(ec._aff_from_jac(QJ)), f"{q}, {ec}"
            assert Q == ec._aff_from_jac(QJ), f"{q}, {ec}"
        assert INF == _mult_aff(q, INF, ec), f"{q}, {ec}"
        assert ec._jac_equality(INFJ, _mult(q, INFJ, ec)), f"{q}, {ec}"
コード例 #3
0
ファイル: test_ssa.py プロジェクト: giubby84/btclib
def test_low_cardinality() -> None:
    "test low-cardinality curves for all msg/key pairs."

    # ec.n has to be prime to sign
    test_curves = [
        low_card_curves["ec13_11"],
        low_card_curves["ec13_19"],
        low_card_curves["ec17_13"],
        low_card_curves["ec17_23"],
        low_card_curves["ec19_13"],
        low_card_curves["ec19_23"],
        low_card_curves["ec23_19"],
        low_card_curves["ec23_31"],
    ]

    # only low cardinality test curves or it would take forever
    for ec in test_curves:
        # BIP340 Schnorr only applies to curve whose prime p = 3 %4
        if not ec.pIsThreeModFour:
            err_msg = "field prime is not equal to 3 mod 4: "
            with pytest.raises(ValueError, match=err_msg):
                ssa._sign(32 * b"\x00", 1, None, ec)
            continue
        for q in range(1, ec.n // 2):  # all possible private keys
            QJ = _mult(q, ec.GJ, ec)  # public key
            x_Q = ec._x_aff_from_jac(QJ)
            if not ec.has_square_y(QJ):
                q = ec.n - q
                QJ = ec.negate_jac(QJ)
            for k in range(1, ec.n // 2):  # all possible ephemeral keys
                RJ = _mult(k, ec.GJ, ec)
                r = ec._x_aff_from_jac(RJ)
                if not ec.has_square_y(RJ):
                    k = ec.n - k
                for e in range(ec.n):  # all possible challenges
                    s = (k + e * q) % ec.n

                    sig = ssa.__sign(e, q, k, r, ec)
                    assert (r, s) == sig
                    # valid signature must validate
                    ssa.__assert_as_valid(e, QJ, r, s, ec)

                    # if e == 0 then the sig is valid for all {q, Q}
                    # no public key can be recovered
                    if e == 0:
                        err_msg = "invalid zero challenge"
                        with pytest.raises(ValueError, match=err_msg):
                            ssa.__recover_pubkey(e, r, s, ec)
                    else:
                        assert x_Q == ssa.__recover_pubkey(e, r, s, ec)
コード例 #4
0
def test_mult_w_NAF() -> None:
    for w in range(1, 6):
        for ec in low_card_curves.values():
            assert ec._jac_equality(_mult_w_NAF(0, ec.GJ, ec, w), INFJ)
            assert ec._jac_equality(_mult_w_NAF(0, INFJ, ec, w), INFJ)

            assert ec._jac_equality(_mult_w_NAF(1, INFJ, ec, w), INFJ)
            assert ec._jac_equality(_mult_w_NAF(1, ec.GJ, ec, w), ec.GJ)

            PJ = _mult_w_NAF(2, ec.GJ, ec, w)
            assert ec._jac_equality(PJ, ec._add_jac(ec.GJ, ec.GJ))

            PJ = _mult_w_NAF(ec.n - 1, ec.GJ, ec, w)
            assert ec._jac_equality(ec.negate_jac(ec.GJ), PJ)

            assert ec._jac_equality(_mult_w_NAF(ec.n - 1, INFJ, ec, w), INFJ)
            assert ec._jac_equality(ec._add_jac(PJ, ec.GJ), INFJ)
            assert ec._jac_equality(_mult_w_NAF(ec.n, ec.GJ, ec, w), INFJ)

            with pytest.raises(BTClibValueError, match="negative m: "):
                _mult_w_NAF(-1, ec.GJ, ec, w)

            with pytest.raises(BTClibValueError, match="non positive w: "):
                _mult_w_NAF(1, ec.GJ, ec, -w)

    ec = ec23_31
    for w in range(1, 10):
        for k1 in range(ec.n):
            K1 = _mult_w_NAF(k1, ec.GJ, ec, w)
            assert ec._jac_equality(K1, _mult(k1, ec.GJ, ec))
コード例 #5
0
def test_mult_recursive_jac() -> None:
    for ec in all_curves.values():
        assert ec._jac_equality(_mult_recursive_jac(0, ec.GJ, ec), INFJ)
        assert ec._jac_equality(_mult_recursive_jac(0, INFJ, ec), INFJ)

        assert ec._jac_equality(_mult_recursive_jac(1, INFJ, ec), INFJ)
        assert ec._jac_equality(_mult_recursive_jac(1, ec.GJ, ec), ec.GJ)

        PJ = ec._add_jac(ec.GJ, ec.GJ)
        assert ec._jac_equality(PJ, _mult_recursive_jac(2, ec.GJ, ec))

        PJ = _mult_recursive_jac(ec.n - 1, ec.GJ, ec)
        assert ec._jac_equality(ec.negate_jac(ec.GJ), PJ)
        assert ec._jac_equality(_mult_recursive_jac(ec.n - 1, INFJ, ec), INFJ)

        assert ec._jac_equality(ec._add_jac(PJ, ec.GJ), INFJ)
        assert ec._jac_equality(_mult_recursive_jac(ec.n, ec.GJ, ec), INFJ)
        assert ec._jac_equality(_mult_recursive_jac(ec.n, INFJ, ec), INFJ)

        with pytest.raises(BTClibValueError, match="negative m: "):
            _mult_recursive_jac(-1, ec.GJ, ec)

    ec = ec23_31
    for k1 in range(ec.n):
        K1 = _mult_recursive_jac(k1, ec.GJ, ec)
        assert ec._jac_equality(K1, _mult(k1, ec.GJ, ec))
コード例 #6
0
def test_mult_base_3() -> None:
    for ec in low_card_curves.values():
        assert ec._jac_equality(_mult_base_3(0, ec.GJ, ec), INFJ)
        assert ec._jac_equality(_mult_base_3(0, INFJ, ec), INFJ)

        assert ec._jac_equality(_mult_base_3(1, INFJ, ec), INFJ)
        assert ec._jac_equality(_mult_base_3(1, ec.GJ, ec), ec.GJ)

        PJ = _mult_base_3(2, ec.GJ, ec)
        assert ec._jac_equality(PJ, ec._add_jac(ec.GJ, ec.GJ))

        PJ = _mult_base_3(ec.n - 1, ec.GJ, ec)
        assert ec._jac_equality(ec.negate_jac(ec.GJ), PJ)
        assert ec._jac_equality(_mult_base_3(ec.n - 1, INFJ, ec), INFJ)

        assert ec._jac_equality(ec._add_jac(PJ, ec.GJ), INFJ)
        assert ec._jac_equality(_mult_base_3(ec.n, ec.GJ, ec), INFJ)
        assert ec._jac_equality(_mult_mont_ladder(ec.n, INFJ, ec), INFJ)

        with pytest.raises(BTClibValueError, match="negative m: "):
            _mult_base_3(-1, ec.GJ, ec)

    ec = ec23_31
    for k1 in range(ec.n):
        K1 = _mult_base_3(k1, ec.GJ, ec)
        assert ec._jac_equality(K1, _mult(k1, ec.GJ, ec))
コード例 #7
0
def test_low_cardinality() -> None:
    """test low-cardinality curves for all msg/key pairs."""

    # ec.n has to be prime to sign
    test_curves = [
        low_card_curves["ec13_11"],
        # low_card_curves["ec13_19"],
        # low_card_curves["ec17_13"],
        low_card_curves["ec17_23"],
        low_card_curves["ec19_13"],
        # low_card_curves["ec19_23"],
        low_card_curves["ec23_19"],
        low_card_curves["ec23_31"],
    ]

    low_s = True
    # only low cardinality test curves or it would take forever
    for ec in test_curves:
        for q in range(1, ec.n):  # all possible private keys
            QJ = _mult(q, ec.GJ, ec)  # public key
            for k in range(1, ec.n):  # all possible ephemeral keys
                RJ = _mult(k, ec.GJ, ec)
                r = ec._x_aff_from_jac(RJ) % ec.n
                k_inv = mod_inv(k, ec.n)
                for e in range(ec.n):  # all possible challenges
                    s = k_inv * (e + q * r) % ec.n
                    # bitcoin canonical 'low-s' encoding for ECDSA
                    if low_s and s > ec.n / 2:
                        s = ec.n - s
                    if r == 0 or s == 0:
                        err_msg = "failed to sign: "
                        with pytest.raises(BTClibRuntimeError, match=err_msg):
                            dsa.__sign(e, q, k, low_s, ec)
                        continue

                    sig = dsa.__sign(e, q, k, low_s, ec)
                    assert (r, s) == sig
                    # valid signature must pass verification
                    dsa.__assert_as_valid(e, QJ, r, s, ec)

                    jacobian_keys = dsa.__recover_pubkeys(e, r, s, ec)
                    # FIXME speed this up
                    Qs = [ec._aff_from_jac(key) for key in jacobian_keys]
                    assert ec._aff_from_jac(QJ) in Qs
                    assert len(jacobian_keys) in (2, 4)
コード例 #8
0
ファイル: test_ssa.py プロジェクト: NirvanaNimbusa/btclib
def test_low_cardinality() -> None:
    "test low-cardinality curves for all msg/key pairs."

    # ec.n has to be prime to sign
    test_curves = [
        low_card_curves["ec13_11"],
        low_card_curves["ec13_19"],
        low_card_curves["ec17_13"],
        low_card_curves["ec17_23"],
        low_card_curves["ec19_13"],
        low_card_curves["ec19_23"],
        low_card_curves["ec23_19"],
        low_card_curves["ec23_31"],
    ]

    # only low cardinality test curves or it would take forever
    for ec in test_curves:
        for q in range(1, ec.n // 2):  # all possible private keys
            QJ = _mult(q, ec.GJ, ec)  # public key
            x_Q, y_Q = ec._aff_from_jac(QJ)
            if y_Q % 2:
                q = ec.n - q
                QJ = ec.negate_jac(QJ)
            for k in range(1, ec.n // 2):  # all possible ephemeral keys
                RJ = _mult(k, ec.GJ, ec)
                r, ry = ec._aff_from_jac(RJ)
                if ry % 2:
                    k = ec.n - k
                for e in range(ec.n):  # all possible challenges
                    s = (k + e * q) % ec.n

                    sig = ssa.__sign(e, q, k, r, ec)
                    assert (r, s) == sig
                    # valid signature must validate
                    ssa.__assert_as_valid(e, QJ, r, s, ec)

                    # if e == 0 then the sig is valid for all {q, Q}
                    # no public key can be recovered
                    if e == 0:
                        err_msg = "invalid zero challenge"
                        with pytest.raises(BTClibValueError, match=err_msg):
                            ssa.__recover_pubkey(e, r, s, ec)
                    else:
                        assert x_Q == ssa.__recover_pubkey(e, r, s, ec)
コード例 #9
0
def test_jac_equality() -> None:

    ec = ec23_31
    assert ec._jac_equality(ec.GJ, _jac_from_aff(ec.G))

    # q in [2, n-1], as the difference with ec.GJ is checked below
    q = 2 + secrets.randbelow(ec.n - 2)
    Q = _mult_aff(q, ec.G, ec)
    QJ = _mult(q, ec.GJ, ec)
    assert ec._jac_equality(QJ, _jac_from_aff(Q))
    assert not ec._jac_equality(QJ, ec.negate_jac(QJ))
    assert not ec._jac_equality(QJ, ec.GJ)
コード例 #10
0
    _mult_w_NAF,
)

# setup
random.seed(42)
qs = [random.getrandbits(ec.nlen) % ec.n for _ in range(300)]

gen_only = True
print("generator only") if gen_only else print("random points")

cached_multiples.cache_clear()
cached_multiples(ec.GJ, ec)
T = ec.GJ
start = time.time()
for q in qs:
    T = _mult(q, ec.GJ, ec) if gen_only else _mult(q, T, ec)
benchmark = time.time() - start
print("Benchmark completed", cached_multiples.cache_info())

T = ec.GJ
start = time.time()
for q in qs:
    T = _mult_jac(q, ec.GJ, ec) if gen_only else _mult_jac(q, T, ec)
double_and_add = time.time() - start
print(f"Double & add     : {double_and_add / benchmark:.0%}")

T = ec.GJ
start = time.time()
for q in qs:
    T = _mult_mont_ladder(q, ec.GJ, ec) if gen_only else _mult_mont_ladder(
        q, T, ec)
コード例 #11
0
def test_assorted_jac_mult() -> None:
    ec = ec23_31
    H = second_generator(ec)
    HJ = _jac_from_aff(H)
    for k1 in range(ec.n):
        K1J = _mult(k1, ec.GJ, ec)
        for k2 in range(ec.n):
            K2J = _mult(k2, HJ, ec)

            shamir = _double_mult(k1, ec.GJ, k2, ec.GJ, ec)
            assert ec.is_on_curve(ec._aff_from_jac(shamir))
            assert ec._jac_equality(shamir, _mult(k1 + k2, ec.GJ, ec))

            shamir = _double_mult(k1, INFJ, k2, HJ, ec)
            assert ec.is_on_curve(ec._aff_from_jac(shamir))
            assert ec._jac_equality(shamir, K2J)

            shamir = _double_mult(k1, ec.GJ, k2, INFJ, ec)
            assert ec.is_on_curve(ec._aff_from_jac(shamir))
            assert ec._jac_equality(shamir, K1J)

            shamir = _double_mult(k1, ec.GJ, k2, HJ, ec)
            assert ec.is_on_curve(ec._aff_from_jac(shamir))
            K1JK2J = ec._add_jac(K1J, K2J)
            assert ec._jac_equality(K1JK2J, shamir)

            k3 = 1 + secrets.randbelow(ec.n - 1)
            K3J = _mult(k3, ec.GJ, ec)
            K1JK2JK3J = ec._add_jac(K1JK2J, K3J)
            assert ec.is_on_curve(ec._aff_from_jac(K1JK2JK3J))
            boscoster = _multi_mult([k1, k2, k3], [ec.GJ, HJ, ec.GJ], ec)
            assert ec.is_on_curve(ec._aff_from_jac(boscoster))
            assert ec._aff_from_jac(K1JK2JK3J) == ec._aff_from_jac(
                boscoster), k3
            assert ec._jac_equality(K1JK2JK3J, boscoster)

            k4 = 1 + secrets.randbelow(ec.n - 1)
            K4J = _mult(k4, HJ, ec)
            K1JK2JK3JK4J = ec._add_jac(K1JK2JK3J, K4J)
            assert ec.is_on_curve(ec._aff_from_jac(K1JK2JK3JK4J))
            points = [ec.GJ, HJ, ec.GJ, HJ]
            boscoster = _multi_mult([k1, k2, k3, k4], points, ec)
            assert ec.is_on_curve(ec._aff_from_jac(boscoster))
            assert ec._aff_from_jac(K1JK2JK3JK4J) == ec._aff_from_jac(
                boscoster), k4
            assert ec._jac_equality(K1JK2JK3JK4J, boscoster)
            assert ec._jac_equality(K1JK2JK3J,
                                    _multi_mult([k1, k2, k3, 0], points, ec))
            assert ec._jac_equality(K1JK2J,
                                    _multi_mult([k1, k2, 0, 0], points, ec))
            assert ec._jac_equality(K1J, _multi_mult([k1, 0, 0, 0], points,
                                                     ec))
            assert ec._jac_equality(INFJ, _multi_mult([0, 0, 0, 0], points,
                                                      ec))

    err_msg = "mismatch between number of scalars and points: "
    with pytest.raises(BTClibValueError, match=err_msg):
        _multi_mult([k1, k2, k3, k4], [ec.GJ, HJ, ec.GJ], ec)

    err_msg = "negative coefficient: "
    with pytest.raises(BTClibValueError, match=err_msg):
        _multi_mult([k1, k2, -k3], [ec.GJ, HJ, ec.GJ], ec)

    with pytest.raises(BTClibValueError, match="negative first coefficient: "):
        _double_mult(-5, HJ, 1, ec.GJ, ec)
    with pytest.raises(BTClibValueError,
                       match="negative second coefficient: "):
        _double_mult(1, HJ, -5, ec.GJ, ec)
コード例 #12
0
import time

from btclib.curve import secp256k1 as ec
from btclib.curvegroup import _double_mult, _mult

random.seed(42)

# setup
us = []
vs = []
QJs = []
for _ in range(500):
    us.append(random.getrandbits(ec.nlen) % ec.n)
    vs.append(random.getrandbits(ec.nlen) % ec.n)
    q = random.getrandbits(ec.nlen) % ec.n
    QJs.append(_mult(q, ec.GJ, ec))
"""
for u, v, QJ in zip(us, vs, QJs):
    t1 = ec._add_jac(_mult(u, ec.GJ, ec), _mult(v, QJ, ec))
    t2 = _double_mult(u, ec.GJ, v, QJ, ec)
    assert ec._jac_equality(t1, t2)
"""

start = time.time()
for u, v, QJ in zip(us, vs, QJs):
    ec._add_jac(_mult(u, ec.GJ, ec), _mult(v, QJ, ec))
elapsed1 = time.time() - start

start = time.time()
for u, v, QJ in zip(us, vs, QJs):
    _double_mult(u, ec.GJ, v, QJ, ec)