Esempio n. 1
0
    def test_gec(self):
        """GEC 2: Test Vectors for SEC 1, section 2

            http://read.pudn.com/downloads168/doc/772358/TestVectorsforSEC%201-gec2.pdf
        """
        # 2.1.1 Scheme setup
        ec = secp160r1
        hf = sha1

        # 2.1.2 Key Deployment for U
        dU = 971761939728640320549601132085879836204587084162
        self.assertEqual(format(dU,
                                str(ec.psize) + 'x'),
                         'aa374ffc3ce144e6b073307972cb6d57b2a4e982')
        QU = mult(ec, dU)
        self.assertEqual(QU,
                         (466448783855397898016055842232266600516272889280,
                          1110706324081757720403272427311003102474457754220))
        self.assertEqual(
            octets_from_point(ec, QU, True).hex(),
            '0251b4496fecc406ed0e75a24a3c03206251419dc0')

        # 2.1.3 Signing Operation for U
        msg = b'abc'
        k = 702232148019446860144825009548118511996283736794
        exp_sig = (0xCE2873E5BE449563391FEB47DDCBA2DC16379191,
                   0x3480EC1371A091A464B31CE47DF0CB8AA2D98B54)
        sig = dsa.sign(ec, hf, msg, dU, k)
        r, s = sig
        self.assertEqual(r, exp_sig[0])
        self.assertIn(s, (exp_sig[1], ec.n - exp_sig[1]))

        # 2.1.4 Verifying Operation for V
        self.assertTrue(dsa.verify(ec, hf, msg, QU, sig))
        self.assertTrue(dsa._verify(ec, hf, msg, QU, sig))
Esempio n. 2
0
def test_rfc6979_tv() -> None:

    fname = "rfc6979.json"
    filename = path.join(path.dirname(__file__), "test_data", fname)
    with open(filename, "r") as f:
        test_dict = json.load(f)

    for ec_name in test_dict:
        ec = CURVES[ec_name]
        test_vectors = test_dict[ec_name]
        for x, x_U, y_U, hf, msg, k, r, s in test_vectors:
            x = int(x, 16)
            # test RFC6979 implementation
            k2 = rfc6979(msg, x, ec, eval("hashlib." + hf))
            assert k == hex(k2)
            # test RFC6979 usage in DSA
            sig = dsa.sign(msg, x, k2, False, ec, eval("hashlib." + hf))
            assert r == hex(sig[0])
            assert s == hex(sig[1])
            # test that RFC6979 is the default nonce for DSA
            sig = dsa.sign(msg, x, k=None, low_s=False, ec=ec, hf=eval("hashlib." + hf))
            assert r == hex(sig[0])
            assert s == hex(sig[1])
            # test key-pair coherence
            U = mult(x, ec.G, ec)
            assert (int(x_U, 16), int(y_U, 16)) == U
            # test signature validity
            dsa.assert_as_valid(msg, U, sig, ec, hf=eval("hashlib." + hf))
Esempio n. 3
0
def test_negate() -> None:
    for ec in all_curves.values():

        # just a random point, not INF
        q = 1 + secrets.randbelow(ec.n - 1)
        Q = mult(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_jac(QJ)
        assert ec._jac_equality(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_jac(INFJ)
        assert ec._jac_equality(minus_INFJ, INFJ)

    with pytest.raises(TypeError, match="not a point"):
        ec.negate(ec.GJ)  # type: ignore

    with pytest.raises(TypeError, match="not a Jacobian point"):
        ec.negate_jac(ec.G)  # type: ignore
Esempio n. 4
0
def test_crack_prvkey() -> None:

    ec = CURVES["secp256k1"]

    q = 0x19E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725
    x_Q = mult(q)[0]

    msg1_str = "Paolo is afraid of ephemeral random numbers"
    msg1 = hf(msg1_str.encode()).digest()
    k, _ = ssa._det_nonce(msg1, q)
    sig1 = ssa._sign(msg1, q, k)

    msg2_str = "and Paolo is right to be afraid"
    msg2 = hf(msg2_str.encode()).digest()
    # reuse same k
    sig2 = ssa._sign(msg2, q, k)

    qc, kc = ssa._crack_prvkey(msg1, sig1, msg2, sig2, x_Q)
    assert q in (qc, ec.n - qc)
    assert k in (kc, ec.n - kc)

    with pytest.raises(ValueError, match="not the same r in signatures"):
        ssa._crack_prvkey(msg1, sig1, msg2, (16, sig1[1]), x_Q)

    with pytest.raises(ValueError, match="identical signatures"):
        ssa._crack_prvkey(msg1, sig1, msg1, sig1, x_Q)
Esempio n. 5
0
def test_point_from_bip340pubkey() -> None:

    q, x_Q = ssa.gen_keys()
    P = mult(q)
    # Integer (int)
    assert ssa.point_from_bip340pubkey(x_Q) == P
    # Integer (bytes)
    assert ssa.point_from_bip340pubkey(x_Q.to_bytes(32, byteorder="big")) == P
    # Integer (hex-str)
    assert ssa.point_from_bip340pubkey(
        x_Q.to_bytes(32, byteorder="big").hex()) == P
    # tuple Point
    assert ssa.point_from_bip340pubkey(P) == P
    # 33 bytes
    assert ssa.point_from_bip340pubkey(bytes_from_point(P)) == P
    # 33 bytes hex-string
    assert ssa.point_from_bip340pubkey(bytes_from_point(P).hex()) == P
    # 65 bytes
    assert ssa.point_from_bip340pubkey(bytes_from_point(P,
                                                        compressed=False)) == P
    # 65 bytes hex-string
    assert ssa.point_from_bip340pubkey(
        bytes_from_point(P, compressed=False).hex()) == P

    xpub_data = BIP32KeyData.deserialize(
        "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"
    )
    xpub_data.key = bytes_from_point(P)
    # BIP32KeyData
    assert ssa.point_from_bip340pubkey(xpub_data) == P
    # BIP32Key encoded str
    xpub = xpub_data.serialize()
    assert ssa.point_from_bip340pubkey(xpub) == P
    # BIP32Key str
    assert ssa.point_from_bip340pubkey(xpub.decode("ascii")) == P
    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))
Esempio n. 7
0
    def test_key_deployment(self):
        """ GEC 2: Test Vectors for SEC 1, section 4.1

            http://read.pudn.com/downloads168/doc/772358/TestVectorsforSEC%201-gec2.pdf
        """

        # 4.1.1
        # ec = secp160r1
        # hf = sha1

        # 4.1.2
        dU = 971761939728640320549601132085879836204587084162
        self.assertEqual(format(dU, str(ec.psize)+'x'),
                         'aa374ffc3ce144e6b073307972cb6d57b2a4e982')
        QU = mult(ec, dU, ec.G)
        self.assertEqual(QU, (466448783855397898016055842232266600516272889280, 1110706324081757720403272427311003102474457754220))
        self.assertEqual(octets_from_point(ec, QU, True).hex(),
                         '0251b4496fecc406ed0e75a24a3c03206251419dc0')

        # 4.1.3
        dV = 399525573676508631577122671218044116107572676710
        self.assertEqual(format(dV, str(ec.psize)+'x'),
                         '45fb58a92a17ad4b15101c66e74f277e2b460866')
        QV = mult(ec, dV, ec.G)
        self.assertEqual(QV, (420773078745784176406965940076771545932416607676, 221937774842090227911893783570676792435918278531))
        self.assertEqual(octets_from_point(ec, QV, True).hex(),
                         '0349b41e0e9c0369c2328739d90f63d56707c6e5bc')

        # expected results
        z_exp = 1155982782519895915997745984453282631351432623114
        zstr = 'ca7c0f8c3ffa87a96e1b74ac8e6af594347bb40a'
        keydatasize = 20
        keying_data_exp = '744ab703f5bc082e59185f6d049d2d367db245c2'

        # 4.1.4
        z, _ = mult(ec, dU, QV)
        self.assertEqual(z, z_exp)
        self.assertEqual(format(z, str(ec.psize)+'x'), zstr)
        keyingdata = dh.kdf(octets_from_int(z, ec.psize), keydatasize, ec, hf)
        self.assertEqual(keyingdata.hex(), keying_data_exp)

        # 4.1.5
        z, _ = mult(ec, dV, QU)
        self.assertEqual(z, z_exp)
        self.assertEqual(format(z, str(ec.psize)+'x'), zstr)
        keyingdata = dh.kdf(octets_from_int(z, ec.psize), keydatasize, ec, hf)
        self.assertEqual(keyingdata.hex(), keying_data_exp)
Esempio n. 8
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. 9
0
    def test_all_curves(self):
        for ec in all_curves:
            self.assertEqual(mult(ec, 0, ec.G), Inf)
            self.assertEqual(mult(ec, 0, ec.G), Inf)

            self.assertEqual(mult(ec, 1, ec.G), ec.G)
            self.assertEqual(mult(ec, 1, ec.G), ec.G)

            Gy_odd = ec.y_odd(ec.G[0], True)
            self.assertEqual(Gy_odd % 2, 1)
            Gy_even = ec.y_odd(ec.G[0], False)
            self.assertEqual(Gy_even % 2, 0)
            self.assertTrue(ec.G[1] in (Gy_odd, Gy_even))

            Gbytes = octets_from_point(ec, ec.G, True)
            G2 = point_from_octets(ec, Gbytes)
            self.assertEqual(ec.G, G2)

            Gbytes = octets_from_point(ec, ec.G, False)
            G2 = point_from_octets(ec, Gbytes)
            self.assertEqual(ec.G, G2)

            P = ec.add(Inf, ec.G)
            self.assertEqual(P, ec.G)
            P = ec.add(ec.G, Inf)
            self.assertEqual(P, ec.G)
            P = ec.add(Inf, Inf)
            self.assertEqual(P, Inf)

            P = ec.add(ec.G, ec.G)
            self.assertEqual(P, mult(ec, 2, ec.G))

            P = mult(ec, ec.n-1, ec.G)
            self.assertEqual(ec.add(P, ec.G), Inf)
            self.assertEqual(mult(ec, ec.n, ec.G), Inf)

            self.assertEqual(mult(ec, 0, Inf), Inf)
            self.assertEqual(mult(ec, 1, Inf), Inf)
            self.assertEqual(mult(ec, 25, Inf), Inf)

            ec_repr = repr(ec)
            if ec in low_card_curves or ec.psize < 24:
                ec_repr = ec_repr[:-1] + ", False)"
            ec2 = eval(ec_repr)
            self.assertEqual(str(ec), str(ec2))
Esempio n. 10
0
def pubkey_bytes_from_prvkey(prvkey, compressed=True):
    PubKey = mult(ec, prvkey, ec.G)
    if compressed:
        prefix = b'\x02' if (PubKey[1] % 2 == 0) else b'\x03'
        return prefix + PubKey[0].to_bytes(32, byteorder='big')
    else:
        prefix = b'\x04'
        return prefix + PubKey[0].to_bytes(32, byteorder='big') + \
                        PubKey[1].to_bytes(32, byteorder='big')
Esempio n. 11
0
def pubkey_bytes_from_prvkey(prvkey, compressed=True):
    PubKey = mult(prvkey)
    if compressed:
        prefix = b"\x02" if (PubKey[1] % 2 == 0) else b"\x03"
        return prefix + PubKey[0].to_bytes(32, byteorder="big")
    else:
        prefix = b"\x04"
        return (prefix + PubKey[0].to_bytes(32, byteorder="big") +
                PubKey[1].to_bytes(32, byteorder="big"))
def key_agreement(dUV: int, QVU: Point, keydatasize: int, ec: Curve,
                  hf) -> bytes:
    P = mult(ec, dUV, QVU)
    if P[1] == 0:
        "invalid (zero) private key"
    z = P[0]
    zbytes = octets_from_int(z, ec.psize)
    k = kdf(zbytes, keydatasize, ec, hf)
    return k
Esempio n. 13
0
def _tweak(c: bytes, ec: Curve, hf, k: int) -> Tuple[Point, int]:
    """tweak kG

    returns:
    - point kG to tweak
    - tweaked private key k + h(kG||c), the corresponding pubkey is a commitment to kG, c
    """
    R = mult(ec, k, ec.G)
    e = hf(octets_from_point(ec, R, True) + c).digest()
    e = int.from_bytes(e, 'big')
    return R, (e + k) % ec.n
Esempio n. 14
0
    def test_low_cardinality(self):
        """test all msg/key pairs of low cardinality elliptic curves"""

        # ec.n has to be prime to sign
        prime = [11, 13, 17, 19]

        # all possible hashed messages
        hsize = 32
        H = [i.to_bytes(hsize, 'big') for i in range(max(prime) * 2)]

        # only low card curves or it would take forever
        for ec in low_card_curves:
            if ec._p in prime:  # only few curves or it would take too long
                # Schnorr-bip only applies to curve whose prime p = 3 %4
                if not ec.pIsThreeModFour:
                    self.assertRaises(ValueError, ssa.sign, ec, hf, H[0], 1,
                                      None)
                    continue
                for q in range(ec.n):  # all possible private keys
                    if q == 0:  # invalid prvkey=0
                        self.assertRaises(ValueError, ssa.sign, ec, hf, H[0],
                                          q, None)
                        self.assertRaises(ValueError, rfc6979, ec, hf, H[0], q)
                        continue
                    Q = mult(ec, q, ec.G)  # public key
                    for h in H:  # all possible hashed messages
                        # k = 0
                        self.assertRaises(ValueError, ssa.sign, ec, hf, h, q,
                                          0)
                        k = rfc6979(ec, hf, h, q)
                        K = mult(ec, k, ec.G)
                        if legendre_symbol(K[1], ec._p) != 1:
                            k = ec.n - k

                        e = ssa._e(ec, hf, K[0], Q, h)
                        s = (k + e * q) % ec.n
                        # valid signature
                        sig = ssa.sign(ec, hf, h, q, k)
                        self.assertEqual((K[0], s), sig)
                        # valid signature must validate
                        self.assertTrue(ssa._verify(ec, hf, h, Q, sig))
Esempio n. 15
0
def sign(ec: Curve,
         hf: Callable[[Any], Any],
         mhd: bytes,
         d: int,
         k: Optional[int] = None) -> ECSS:
    """ ECSSA signing operation according to bip-schnorr

        This signature scheme supports 32-byte messages.
        Differently from ECDSA, the 32-byte message can be a
        digest of other messages, but it does not need to.

        https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr.mediawiki
    """

    # 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)

    # The message mhd: a 32-byte array
    _ensure_msg_size(hf, mhd)

    # The secret key d: an integer in the range 1..n-1.
    if not 0 < d < ec.n:
        raise ValueError(f"private key {hex(d)} not in [1, n-1]")
    P = mult(ec, d, ec.G)

    # Fail if k' = 0.
    if k is None:
        k = rfc6979(ec, hf, mhd, d)
    if not 0 < k < ec.n:
        raise ValueError(f"ephemeral key {hex(k)} not in [1, n-1]")

    # Let R = k'G.
    RJ = _mult_jac(ec, k, ec.GJ)

    # break the simmetry: any criteria might have been used,
    # jacobi is the proposed bitcoin standard
    # Let k = k' if jacobi(y(R)) = 1, otherwise let k = n - k'.
    if legendre_symbol(RJ[1] * RJ[2] % ec._p, ec._p) != 1:
        k = ec.n - k

    Z2 = RJ[2] * RJ[2]
    r = (RJ[0] * mod_inv(Z2, ec._p)) % ec._p

    # Let e = int(hf(bytes(x(R)) || bytes(dG) || mhd)) mod n.
    e = _e(ec, hf, r, P, mhd)

    s = (k +
         e * d) % ec.n  # s=0 is ok: in verification there is no inverse of s
    # The signature is bytes(x(R) || bytes((k + ed) mod n)).
    return r, s
Esempio n. 16
0
    def test_low_cardinality(self):
        """test all msg/key pairs of low cardinality elliptic curves"""

        # ec.n has to be prime to sign
        prime = [11, 13, 17, 19]

        for ec in low_card_curves:  # only low card or it would take forever
            if ec._p in prime:  # only few curves or it would take too long
                for d in range(1, ec.n):  # all possible private keys
                    P = mult(ec, d, ec.G)  # public key
                    for e in range(ec.n):  # all possible int from hash
                        for k in range(1, ec.n):  # all possible ephemeral keys
                            R = mult(ec, k, ec.G)

                            r = R[0] % ec.n
                            if r == 0:
                                self.assertRaises(ValueError, dsa._sign, ec, e,
                                                  d, k)
                                continue

                            s = mod_inv(k, ec.n) * (e + d * r) % ec.n
                            if s == 0:
                                self.assertRaises(ValueError, dsa._sign, ec, e,
                                                  d, k)
                                continue

                            # bitcoin canonical 'low-s' encoding for ECDSA
                            if s > ec.n / 2:
                                s = ec.n - s

                            # valid signature
                            sig = dsa._sign(ec, e, d, k)
                            self.assertEqual((r, s), sig)
                            # valid signature must validate
                            self.assertTrue(dsa._verhlp(ec, e, P, sig))

                            keys = dsa._pubkey_recovery(ec, e, sig)
                            self.assertIn(P, keys)
                            for Q in keys:
                                self.assertTrue(dsa._verhlp(ec, e, Q, sig))
def sign(msg: bytes,
                   k: List[int],
                   sign_key_idx: List[int],
                   sign_keys: List[int],
                   pubk_rings: Dict[int, List[Point]]) -> Tuple[bytes, Dict[int, List[int]]]:
    """ Borromean ring signature - signing algorithm

        https://github.com/ElementsProject/borromean-signatures-writeup
        https://github.com/Blockstream/borromean_paper/blob/master/borromean_draft_0.01_9ade1e49.pdf

        inputs:
        - msg: msg to be signed (bytes)
        - sign_key_idx: list of indexes representing each signing key per ring
        - sign_keys: list containing the whole set of signing keys (one per ring)
        - pubk_rings: dictionary of lists where internal lists represent single rings of pubkeys
    """

    s: Dict[int, List[int]] = defaultdict(list)
    e: Dict[int, List[int]] = defaultdict(list)
    m = _get_msg_format(msg, pubk_rings)
    e0bytes = m
    ring_size = len(pubk_rings)
    # step 1
    for i in range(ring_size):
        keys_size = len(pubk_rings[i])
        s[i] = [0]*keys_size
        e[i] = [0]*keys_size
        j_star = sign_key_idx[i]
        start_idx = (j_star + 1) % keys_size
        R = octets_from_point(ec, mult(ec, k[i], ec.G), True)
        if start_idx != 0:
            for j in range(start_idx, keys_size):
                s[i][j] = random.getrandbits(256)
                e[i][j] = int_from_bits(ec, _hash(m, R, i, j))
                assert 0 < e[i][j] < ec.n, "sign fail: how did you do that?!?"
                T = double_mult(ec, s[i][j], ec.G, -e[i][j], pubk_rings[i][j])
                R = octets_from_point(ec, T, True)
        e0bytes += R
    e0 = hf(e0bytes).digest()
    # step 2
    for i in range(ring_size):
        e[i][0] = int_from_bits(ec, _hash(m, e0, i, 0))
        assert 0 < e[i][0] < ec.n, "sign fail: how did you do that?!?"
        j_star = sign_key_idx[i]
        for j in range(1, j_star+1):
            s[i][j-1] = random.getrandbits(256)
            T = double_mult(ec, s[i][j-1], ec.G, -e[i][j-1], pubk_rings[i][j-1])
            R = octets_from_point(ec, T, True)
            e[i][j] = int_from_bits(ec, _hash(m, R, i, j))
            assert 0 < e[i][j] < ec.n, "sign fail: how did you do that?!?"
        s[i][j_star] = k[i] + sign_keys[i]*e[i][j_star]
    return e0, s
Esempio n. 18
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. 19
0
def test_is_on_curve() -> None:
    for ec in all_curves.values():

        with pytest.raises(ValueError, match="point must be a tuple"):
            ec.is_on_curve("not a point")  # type: ignore

        with pytest.raises(ValueError, match="x-coordinate not in 0..p-1: "):
            ec.y(ec.p)

        # just a random point, not INF
        q = 1 + secrets.randbelow(ec.n - 1)
        Q = mult(q, ec.G, ec)
        with pytest.raises(ValueError, match="y-coordinate not in 1..p-1: "):
            ec.is_on_curve((Q[0], ec.p))
Esempio n. 20
0
def test_ecdh() -> None:
    ec = CURVES["secp256k1"]
    hf = sha256

    a, A = dsa.gen_keys()  # Alice
    b, B = dsa.gen_keys()  # Bob

    # Alice computes the shared secret using Bob's public key
    shared_secret_a = mult(a, B)

    # Bob computes the shared secret using Alice's public key
    shared_secret_b = mult(b, A)

    assert shared_secret_a == shared_secret_b
    assert shared_secret_a == mult(a * b, ec.G)

    # hash the shared secret to remove weak bits
    shared_secret_field_element = shared_secret_a[0]
    z = shared_secret_field_element.to_bytes(ec.psize, "big")

    shared_info = b"deadbeef"

    hsize = hf().digest_size
    for size in (hsize - 1, hsize, hsize + 1):
        shared_key = ansi_x9_63_kdf(z, size, hf, None)
        assert len(shared_key) == size
        assert shared_key == diffie_hellman(a, B, size, None, ec, hf)
        assert shared_key == diffie_hellman(b, A, size, None, ec, hf)
        shared_key = ansi_x9_63_kdf(z, size, hf, shared_info)
        assert len(shared_key) == size
        assert shared_key == diffie_hellman(a, B, size, shared_info, ec, hf)
        assert shared_key == diffie_hellman(b, A, size, shared_info, ec, hf)

    max_size = hsize * (2 ** 32 - 1)
    size = max_size + 1
    with pytest.raises(BTClibValueError, match="cannot derive a key larger than "):
        ansi_x9_63_kdf(z, size, hf, None)
Esempio n. 21
0
def verify_commit(c: bytes, ec: Curve, hf, receipt: Receipt) -> bool:
    w, R = receipt
    # w in [1..n-1] dsa
    # w in [1..p-1] ssa
    # different verify functions?

    # verify R is a good point?

    ch = hf(c).digest()
    e = hf(octets_from_point(ec, R, True) + ch).digest()
    e = int_from_bits(ec, e)
    W = ec.add(R, mult(ec, e, ec.G))
    # different verify functions?
    # return w == W[0] # ECSS
    return w == W[0] % ec.n  # ECDS, FIXME: ECSSA
    def test_signtocontract(self):
        prv = 0x1
        pub = mult(ec, prv, ec.G)
        m = "to be signed".encode()
        c = "to be committed".encode()

        dsa_sig, dsa_receipt = ecdsa_commit_sign(c, ec, hf, m, prv, None)
        self.assertTrue(dsa.verify(ec, hf, m, pub, dsa_sig))
        self.assertTrue(verify_commit(c, ec, hf, dsa_receipt))

        # 32 bytes message for ECSSA
        m = hf(m).digest()
        ssa_sig, ssa_receipt = ecssa_commit_sign(c, ec, hf, m, prv, None)
        self.assertTrue(ssa.verify(ec, hf, m, pub, ssa_sig))
        self.assertTrue(verify_commit(c, ec, hf, ssa_receipt))
    def test_pubkey_recovery(self):
        ec = secp112r2
        hf = sha256
        q = 0x1
        Q = mult(ec, q, ec.G)
        msg = 'Satoshi Nakamoto'.encode()
        sig = dsa.sign(ec, hf, msg, q)

        self.assertTrue(dsa.verify(ec, hf, msg, Q, sig))
        self.assertTrue(dsa._verify(ec, hf, msg, Q, sig))

        keys = dsa.pubkey_recovery(ec, hf, msg, sig)
        self.assertIn(Q, keys)
        for Q in keys:
            self.assertTrue(dsa.verify(ec, hf, msg, Q, sig))
            self.assertTrue(dsa._verify(ec, hf, msg, Q, sig))
Esempio n. 24
0
    def test_boscoster(self):
        ec = secp256k1

        k: List[int] = list()
        ksum = 0
        for i in range(11):
            k.append(random.getrandbits(ec.nlen) % ec.n)
            ksum += k[i]

        P = [ec.G] * len(k)
        boscoster = multi_mult(ec, k, P)
        self.assertEqual(boscoster, mult(ec, ksum, ec.G))

        # mismatch between scalar length and Points length
        P = [ec.G] * (len(k)-1)
        self.assertRaises(ValueError, multi_mult, ec, k, P)
Esempio n. 25
0
def test_add_double_aff_jac() -> None:
    "Test consistency between affine and Jacobian add/double methods."
    for ec in all_curves.values():

        # just a random point, not INF
        q = 1 + secrets.randbelow(ec.n - 1)
        Q = mult(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._double_aff(Q)
        RJ = ec._double_jac(QJ)
        assert R == ec._aff_from_jac(RJ)
        assert R == ec._add_aff(Q, Q)
        assert ec._jac_equality(RJ, ec._add_jac(QJ, QJ))
Esempio n. 26
0
def test_aff_jac_conversions() -> None:
    for ec in all_curves.values():

        # just a random point, not INF
        q = 1 + secrets.randbelow(ec.n - 1)
        Q = mult(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")  # type: ignore
Esempio n. 27
0
def test_aff_jac_conversions() -> None:
    for ec in all_curves.values():

        # just a random point, not INF
        q = 1 + secrets.randbelow(ec.n - 1)
        Q = mult(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
        y_Q = ec._y_aff_from_jac(QJ)
        assert Q[1] == y_Q

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

        with pytest.raises(BTClibValueError, match="INF has no x-coordinate"):
            ec._x_aff_from_jac(INFJ)

        with pytest.raises(BTClibValueError, match="INF has no y-coordinate"):
            ec._y_aff_from_jac(INFJ)
    def test_borromean(self):
        ec = secp256k1
        ring_number = 4
        ring_dim = [random.randint(1, 4) for ring in range(ring_number)]
        borromean.signing_indexes = [random.randrange(ring_dim[ring])
                           for ring in range(ring_number)]
        priv_keys = {}
        Pub_keys = {}
        borromean.signing_keys = []
        for i in range(ring_number):
            priv_keys[i] = [0]*ring_dim[i]
            Pub_keys[i] = [0]*ring_dim[i]
            for j in range(ring_dim[i]):
                priv_keys[i][j] = j+1
                Pub_keys[i][j] = mult(ec, priv_keys[i][j], ec.G)
            borromean.signing_keys.append(priv_keys[i][borromean.signing_indexes[i]])
        msg = 'Borromean ring borromean.signature'.encode()
        sig = borromean.sign(msg, list(range(1, 5)), borromean.signing_indexes, borromean.signing_keys, Pub_keys)
        self.assertTrue(borromean.verify(msg, sig[0], sig[1], Pub_keys))

        self.assertFalse(borromean.verify(0, sig[0], sig[1], Pub_keys))
Esempio n. 29
0
def test_pubkey_recovery() -> None:

    ec = CURVES["secp112r2"]

    q = 0x10
    Q = mult(q, ec.G, ec)

    msg = "Satoshi Nakamoto"
    low_s = True
    sig = dsa.sign(msg, q, low_s, ec)
    assert dsa.verify(msg, Q, sig, ec)
    dersig = dsa.serialize(*sig, ec)
    assert dsa.verify(msg, Q, dersig, ec)
    r, s = dsa.deserialize(dersig)
    assert (r, s) == sig

    keys = dsa.recover_pubkeys(msg, sig, ec)
    assert len(keys) == 4
    assert Q in keys
    for Q in keys:
        assert dsa.verify(msg, Q, sig, ec)
Esempio n. 30
0
 def test_shamir(self):
     ec = ec23_31
     for k1 in range(ec.n):
         for k2 in range(ec.n):
             shamir = double_mult(ec, k1, ec.G, k2, ec.G)
             std = ec.add(mult(ec, k1, ec.G),
                          mult(ec, k2, ec.G))
             self.assertEqual(shamir, std)
             shamir = double_mult(ec, k1, Inf, k2, ec.G)
             std = ec.add(mult(ec, k1, Inf),
                          mult(ec, k2, ec.G))
             self.assertEqual(shamir, std)
             shamir = double_mult(ec, k1, ec.G, k2, Inf)
             std = ec.add(mult(ec, k1, ec.G),
                          mult(ec, k2, Inf))
             self.assertEqual(shamir, std)