Esempio n. 1
0
    def test_add(self):
        for ec in all_curves.values():
            Q1 = mult(ec.p, ec.G, ec)  # just a random point, not INF
            Q1J = _jac_from_aff(Q1)

            # distinct points
            Q3 = ec._add_aff(Q1, ec.G)
            Q3jac = ec._add_jac(Q1J, ec.GJ)
            self.assertEqual(Q3, ec._aff_from_jac(Q3jac))

            # point at infinity
            Q3 = ec._add_aff(ec.G, INF)
            Q3jac = ec._add_jac(ec.GJ, INFJ)
            self.assertEqual(Q3, ec._aff_from_jac(Q3jac))
            Q3 = ec._add_aff(INF, ec.G)
            Q3jac = ec._add_jac(INFJ, ec.GJ)
            self.assertEqual(Q3, ec._aff_from_jac(Q3jac))

            # point doubling
            Q3 = ec._add_aff(Q1, Q1)
            Q3jac = ec._add_jac(Q1J, Q1J)
            self.assertEqual(Q3, ec._aff_from_jac(Q3jac))

            # negate points
            Q1opp = ec.negate(Q1)
            Q3 = ec._add_aff(Q1, Q1opp)
            Q3jac = ec._add_jac(Q1J, _jac_from_aff(Q1opp))
            self.assertEqual(Q3, ec._aff_from_jac(Q3jac))
Esempio n. 2
0
    def test_add(self):
        for ec in all_curves:
            Q1 = mult(ec, ec._p, ec.G)  # just a random point, not Inf
            Q1J = _jac_from_aff(Q1)

            # distinct points
            Q3 = ec._add_aff(Q1,  ec.G)
            Q3jac = ec._add_jac(Q1J, ec.GJ)
            self.assertEqual(Q3, ec._aff_from_jac(Q3jac))

            # point at infinity
            Q3 = ec._add_aff(ec.G,  Inf)
            Q3jac = ec._add_jac(ec.GJ, InfJ)
            self.assertEqual(Q3, ec._aff_from_jac(Q3jac))
            Q3 = ec._add_aff(Inf,  ec.G)
            Q3jac = ec._add_jac(InfJ, ec.GJ)
            self.assertEqual(Q3, ec._aff_from_jac(Q3jac))

            # point doubling
            Q3 = ec._add_aff(Q1,  Q1)
            Q3jac = ec._add_jac(Q1J, Q1J)
            self.assertEqual(Q3, ec._aff_from_jac(Q3jac))

            # opposite points
            Q1opp = ec.opposite(Q1)
            Q3 = ec._add_aff(Q1,  Q1opp)
            Q3jac = ec._add_jac(Q1J, _jac_from_aff(Q1opp))
            self.assertEqual(Q3, ec._aff_from_jac(Q3jac))
def _batch_verify(ec: Curve, hf, ms: List[bytes], P: List[Point],
                  sig: List[ECSS]) -> bool:
    t = 0
    scalars: List(int) = list()
    points: List[Point] = list()
    for i in range(len(P)):
        _ensure_msg_size(hf, ms[i])
        ec.require_on_curve(P[i])
        r, s = _to_sig(ec, sig[i])
        e = _e(ec, hf, r, P[i], ms[i])
        y = ec.y(r)  # raises an error if y does not exist

        # deterministically generated using a CSPRNG seeded by a cryptographic
        # hash (e.g., SHA256) of all inputs of the algorithm, or randomly
        # generated independently for each run of the batch verification
        # algorithm  FIXME
        a = (1 if i == 0 else random.getrandbits(ec.nlen) % ec.n)
        scalars.append(a)
        points.append(_jac_from_aff((r, y)))
        scalars.append(a * e % ec.n)
        points.append(_jac_from_aff(P[i]))
        t += a * s % ec.n

    TJ = _mult_jac(ec, t, ec.GJ)
    RHSJ = _multi_mult(ec, scalars, points)

    # return T == RHS, checked in Jacobian coordinates
    RHSZ2 = RHSJ[2] * RHSJ[2]
    TZ2 = TJ[2] * TJ[2]
    if (TJ[0] * RHSZ2) % ec._p != (RHSJ[0] * TZ2) % ec._p:
        return False

    return (TJ[1] * RHSZ2 * RHSJ[2]) % ec._p == (RHSJ[1] * TZ2 * TJ[2]) % ec._p
Esempio n. 4
0
 def test_aff_jac_conversions(self):
     for ec in all_curves:
         Q = mult(ec, ec._p, ec.G)  # random point
         checkQ = ec._aff_from_jac(_jac_from_aff(Q))
         self.assertEqual(Q, checkQ)
     # with only the last curve
     checkInf = ec._aff_from_jac(_jac_from_aff(Inf))
     self.assertEqual(Inf, checkInf)
Esempio n. 5
0
def _batch_verify(ec: Curve, hf: Callable[[Any], Any], ms: Sequence[bytes],
                  P: Sequence[Point], sig: Sequence[ECSS]) -> bool:

    # the bitcoin proposed standard is only valid for curves
    # whose prime p = 3 % 4
    if not ec.pIsThreeModFour:
        errmsg = 'curve prime p must be equal to 3 (mod 4)'
        raise ValueError(errmsg)

    batch_size = len(P)
    if len(ms) != batch_size:
        errMsg = f"mismatch between number of pubkeys ({batch_size}) "
        errMsg += f"and number of messages ({len(ms)})"
        raise ValueError(errMsg)
    if len(sig) != batch_size:
        errMsg = f"mismatch between number of pubkeys ({batch_size}) "
        errMsg += f"and number of signatures ({len(sig)})"
        raise ValueError(errMsg)

    if batch_size == 1:
        return _verify(ec, hf, ms[0], P[0], sig[0])

    t = 0
    scalars: Sequence(int) = list()
    points: Sequence[Point] = list()
    for i in range(batch_size):
        r, s = _to_sig(ec, sig[i])
        _ensure_msg_size(hf, ms[i])
        ec.require_on_curve(P[i])
        e = _e(ec, hf, r, P[i], ms[i])
        # raises an error if y does not exist
        # no need to check for quadratic residue
        y = ec.y(r)

        # a in [1, n-1]
        # deterministically generated using a CSPRNG seeded by a
        # cryptographic hash (e.g., SHA256) of all inputs of the
        # algorithm, or randomly generated independently for each
        # run of the batch verification algorithm
        a = (1 if i == 0 else (1 + random.getrandbits(ec.nlen)) % ec.n)
        scalars.append(a)
        points.append(_jac_from_aff((r, y)))
        scalars.append(a * e % ec.n)
        points.append(_jac_from_aff(P[i]))
        t += a * s

    TJ = _mult_jac(ec, t, ec.GJ)
    RHSJ = _multi_mult(ec, scalars, points)

    # return T == RHS, checked in Jacobian coordinates
    RHSZ2 = RHSJ[2] * RHSJ[2]
    TZ2 = TJ[2] * TJ[2]
    if (TJ[0] * RHSZ2) % ec._p != (RHSJ[0] * TZ2) % ec._p:
        return False

    return (TJ[1] * RHSZ2 * RHSJ[2]) % ec._p == (RHSJ[1] * TZ2 * TJ[2]) % ec._p
Esempio n. 6
0
def test_jac():

    ec = Curve(13, 0, 2, (1, 9), 19, 1, False)
    assert ec._jac_equality(ec.GJ, _jac_from_aff(ec.G))

    # q in [2, n-1]
    q = 2 + secrets.randbelow(ec.n - 2)
    Q = _mult_aff(q, ec.G, ec)
    QJ = _mult_jac(q, ec.GJ, ec)
    assert ec._jac_equality(QJ, _jac_from_aff(Q))
    assert not ec._jac_equality(QJ, ec.negate(QJ))
    assert not ec._jac_equality(QJ, ec.GJ)
Esempio n. 7
0
    def test_opposite(self):
        for ec in all_curves:
            Q = mult(ec, ec._p, ec.G)  # just a random point, not Inf
            minus_Q = ec.opposite(Q)
            self.assertEqual(ec.add(Q, minus_Q), Inf)
            # jacobian coordinates
            Qjac = _jac_from_aff(Q)
            minus_Qjac = _jac_from_aff(minus_Q)
            self.assertEqual(ec._add_jac(Qjac, minus_Qjac)[2], 0)

            # opposite of Inf is Inf
            minus_Inf = ec.opposite(Inf)
            self.assertEqual(minus_Inf, Inf)
Esempio n. 8
0
    def test_opposite(self):
        for ec in all_curves.values():
            Q = mult(ec.p, ec.G, ec)  # just a random point, not INF
            minus_Q = ec.negate(Q)
            self.assertEqual(ec.add(Q, minus_Q), INF)
            # jacobian coordinates
            Qjac = _jac_from_aff(Q)
            minus_Qjac = _jac_from_aff(minus_Q)
            self.assertEqual(ec._add_jac(Qjac, minus_Qjac)[2], 0)

            # negate of INF is INF
            minus_Inf = ec.negate(INF)
            self.assertEqual(minus_Inf, INF)
Esempio n. 9
0
    def test_aff_jac_conversions(self):
        for ec in all_curves.values():
            Q = mult(ec.p, ec.G, ec)  # just a random point, not INF
            QJ = _jac_from_aff(Q)
            checkQ = ec._aff_from_jac(QJ)
            self.assertEqual(Q, checkQ)
            x = ec._x_aff_from_jac(QJ)
            self.assertEqual(Q[0], x)

            checkInf = ec._aff_from_jac(_jac_from_aff(INF))
            self.assertEqual(INF, checkInf)
            # relevant for BIP340-Schnorr signature verification
            self.assertFalse(ec.has_square_y(INF))
            self.assertRaises(ValueError, ec._x_aff_from_jac, INFJ)
            self.assertRaises(ValueError, ec.has_square_y, "Not a Point")
Esempio n. 10
0
def test_aff_jac_conversions():
    for ec in all_curves.values():

        # just a random point, not INF
        q = 1 + secrets.randbelow(ec.n - 1)
        Q = _mult_aff(q, ec.G, ec)
        QJ = _jac_from_aff(Q)
        assert Q == ec._aff_from_jac(QJ)
        x_Q = ec._x_aff_from_jac(QJ)
        assert Q[0] == x_Q

        assert INF == ec._aff_from_jac(_jac_from_aff(INF))

        # relevant for BIP340-Schnorr signature verification
        assert not ec.has_square_y(INF)
        with pytest.raises(ValueError,
                           match="infinity point has no x-coordinate"):
            ec._x_aff_from_jac(INFJ)
        with pytest.raises(TypeError, match="not a point"):
            ec.has_square_y("notapoint")
Esempio n. 11
0
def test_assorted_mult():
    ec = ec23_31
    H = second_generator(ec)
    HJ = _jac_from_aff(H)
    for k1 in range(ec.n):
        K1J = _mult_jac(k1, ec.GJ, ec)
        for k2 in range(ec.n):
            K2J = _mult_jac(k2, HJ, ec)

            shamir = _double_mult(k1, ec.GJ, k2, ec.GJ, ec)
            assert ec._jac_equality(shamir, _mult_jac(k1 + k2, ec.GJ, ec))

            shamir = _double_mult(k1, INFJ, k2, HJ, ec)
            assert ec._jac_equality(shamir, K2J)
            shamir = _double_mult(k1, ec.GJ, k2, INFJ, ec)
            assert ec._jac_equality(shamir, K1J)

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

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

            k4 = 1 + secrets.randbelow(ec.n - 1)
            K4J = _mult_jac(k4, HJ, ec)
            K1JK2JK3JK4J = ec._add_jac(K1JK2JK3J, K4J)
            points = [ec.GJ, HJ, ec.GJ, HJ]
            boscoster = _multi_mult([k1, k2, k3, k4], points, ec)
            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(ValueError, match=err_msg):
        _multi_mult([k1, k2, k3, k4], [ec.GJ, HJ, ec.GJ], ec)

    with pytest.raises(ValueError, match="negative first coefficient: "):
        _double_mult(-5, HJ, 1, ec.GJ, ec)
    with pytest.raises(ValueError, match="negative second coefficient: "):
        _double_mult(1, HJ, -5, ec.GJ, ec)
Esempio n. 12
0
def test_add():
    for ec in all_curves.values():

        # just a random point, not INF
        q = 1 + secrets.randbelow(ec.n - 1)
        Q = _mult_aff(q, ec.G, ec)
        QJ = _jac_from_aff(Q)

        # add Q and G
        R = ec._add_aff(Q, ec.G)
        RJ = ec._add_jac(QJ, ec.GJ)
        assert R == ec._aff_from_jac(RJ)

        # double Q
        R = ec._add_aff(Q, Q)
        RJ = ec._add_jac(QJ, QJ)
        assert R == ec._aff_from_jac(RJ)
Esempio n. 13
0
def test_negate():
    for ec in all_curves.values():

        # just a random point, not INF
        q = 1 + secrets.randbelow(ec.n - 1)
        Q = _mult_aff(q, ec.G, ec)
        minus_Q = ec.negate(Q)
        assert ec.add(Q, minus_Q) == INF

        # Jacobian coordinates
        QJ = _jac_from_aff(Q)
        minus_QJ = ec.negate(QJ)
        assert ec._add_jac(QJ, minus_QJ) == INFJ

        # negate of INF is INF
        minus_INF = ec.negate(INF)
        assert minus_INF == INF

        # negate of INFJ is INFJ
        minus_INFJ = ec.negate(INFJ)
        assert minus_INFJ == INFJ

    with pytest.raises(TypeError, match="not a point"):
        ec.negate("notapoint")
Esempio n. 14
0
# No part of btclib including this file, may be copied, modified, propagated,
# or distributed except according to the terms contained in the LICENSE file.

import random
import time

from btclib.curve import _jac_from_aff
from btclib.curvemult import _mult_jac
from btclib.curves import secp256k1 as ec

random.seed(42)

# setup
qs = []
for _ in range(50):
    qs.append(random.getrandbits(ec.nlen) % ec.n)

start = time.time()
for q in qs:
    ec._mult_aff(q, ec.G)
elapsed1 = time.time() - start

start = time.time()
for q in qs:
    # starts from affine coordinates, ends with affine coordinates
    GJ = _jac_from_aff(ec.G)
    ec._aff_from_jac(_mult_jac(q, GJ))
elapsed2 = time.time() - start

print(elapsed2 / elapsed1)