示例#1
0
def test_batch_validation():

    ec = secp256k1

    hsize = hf().digest_size
    hlen = hsize * 8

    ms = []
    Qs = []
    sigs = []
    ms.append(secrets.randbits(hlen).to_bytes(hsize, "big"))
    q = 1 + secrets.randbelow(ec.n - 1)
    # bytes version
    Qs.append(mult(q, ec.G, ec)[0].to_bytes(ec.psize, "big"))
    sigs.append(ssa.sign(ms[0], q, None, ec, hf))
    # test with only 1 sig
    ssa._batch_verify(ms, Qs, sigs, ec, hf)
    for _ in range(3):
        mhd = secrets.randbits(hlen).to_bytes(hsize, "big")
        ms.append(mhd)
        q = 1 + secrets.randbelow(ec.n - 1)
        # Point version
        Qs.append(mult(q, ec.G, ec))
        sigs.append(ssa.sign(mhd, q, None, ec, hf))
    ssa._batch_verify(ms, Qs, sigs, ec, hf)
    assert ssa.batch_verify(ms, Qs, sigs, ec, hf)

    ms.append(ms[0])
    sigs.append(sigs[1])
    Qs.append(Qs[0])
    assert not ssa.batch_verify(ms, Qs, sigs, ec, hf)
    err_msg = "signature verification precondition failed"
    with pytest.raises(ValueError, match=err_msg):
        ssa._batch_verify(ms, Qs, sigs, ec, hf)
    sigs[-1] = sigs[0]  # valid again

    ms[-1] = ms[0][:-1]
    err_msg = "invalid size: 31 bytes instead of 32"
    with pytest.raises(ValueError, match=err_msg):
        ssa._batch_verify(ms, Qs, sigs, ec, hf)
    ms[-1] = ms[0]  # valid again

    ms.append(ms[0])  # add extra message
    err_msg = "mismatch between number of pubkeys "
    with pytest.raises(ValueError, match=err_msg):
        ssa._batch_verify(ms, Qs, sigs, ec, hf)
    ms.pop()  # valid again

    sigs.append(sigs[0])  # add extra sig
    err_msg = "mismatch between number of pubkeys "
    with pytest.raises(ValueError, match=err_msg):
        ssa._batch_verify(ms, Qs, sigs, ec, hf)
    sigs.pop()  # valid again

    err_msg = "field prime is not equal to 3 mod 4: "
    with pytest.raises(ValueError, match=err_msg):
        ssa._batch_verify(ms, Qs, sigs, secp224k1, hf)
示例#2
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(dU, ec.G, ec)
        self.assertEqual(QU,
                         (466448783855397898016055842232266600516272889280,
                          1110706324081757720403272427311003102474457754220))
        self.assertEqual(
            octets_from_point(QU, True, ec).hex(),
            '0251b4496fecc406ed0e75a24a3c03206251419dc0')

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

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

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

        # 4.1.5
        z, _ = mult(dV, QU, ec)  # x coordinate only
        self.assertEqual(z, z_exp)
        self.assertEqual(format(z, str(ec.psize) + 'x'), zstr)
        keyingdata = dh.ansi_x963_kdf(octets_from_int(z, ec.psize), size, ec,
                                      hf)
        self.assertEqual(keyingdata.hex(), keying_data_exp)
示例#3
0
    def test_signature(self):
        q = 0x1
        Q = mult(q)
        msg = b'Satoshi Nakamoto'
        sig = dsa.sign(msg, q)
        # https://bitcointalk.org/index.php?topic=285142.40
        # Deterministic Usage of DSA and ECDSA (RFC 6979)
        exp_sig = (
            0x934b1ea10a4b3c1757e2b0c017d0b6143ce3c9a7e6a4a49860d7a6ab210ee3d8,
            0x2442ce9d2b916064108014783e923ec36b49743e2ffa1c4496f01a512aafd9e5)
        r, s = sig
        self.assertEqual(sig[0], exp_sig[0])
        self.assertIn(sig[1], (exp_sig[1], secp256k1.n - exp_sig[1]))

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

        # malleability
        malleated_sig = (r, secp256k1.n - s)
        self.assertTrue(dsa.verify(msg, Q, malleated_sig))
        self.assertTrue(dsa._verify(msg, Q, malleated_sig))

        keys = dsa.pubkey_recovery(msg, sig)
        self.assertTrue(len(keys) == 2)
        self.assertIn(Q, keys)

        fmsg = b'Craig Wright'
        self.assertFalse(dsa.verify(fmsg, Q, sig))
        self.assertFalse(dsa._verify(fmsg, Q, sig))

        fdsasig = (sig[0], sig[1], sig[1])
        self.assertFalse(dsa.verify(msg, Q, fdsasig))
        self.assertRaises(TypeError, dsa._verify, msg, Q, fdsasig)

        fq = 0x4
        fQ = mult(fq)
        self.assertFalse(dsa.verify(msg, fQ, sig))
        self.assertFalse(dsa._verify(msg, fQ, sig))

        # r not in [1, n-1]
        invalid_dassig = 0, sig[1]
        self.assertFalse(dsa.verify(msg, Q, invalid_dassig))

        # s not in [1, n-1]
        invalid_dassig = sig[0], 0
        self.assertFalse(dsa.verify(msg, Q, invalid_dassig))

        # pubkey = Inf
        self.assertRaises(ValueError, dsa._verify, msg, (1, 0), sig)
        #dsa._verify(msg, (1, 0), sig)

        # private key not in [1, n-1]
        self.assertRaises(ValueError, dsa.sign, msg, 0)
        #dsa.sign(msg, 0)

        # ephemeral key not in [1, n-1]
        self.assertRaises(ValueError, dsa.sign, msg, 1, 0)
示例#4
0
def test_key_deployment():
    """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
    assert format(dU,
                  str(ec.nsize) +
                  "x") == "aa374ffc3ce144e6b073307972cb6d57b2a4e982"
    QU = mult(dU, ec.G, ec)
    assert QU == (
        466448783855397898016055842232266600516272889280,
        1110706324081757720403272427311003102474457754220,
    )
    assert (bytes_from_point(
        QU, ec).hex() == "0251b4496fecc406ed0e75a24a3c03206251419dc0")

    # 4.1.3
    dV = 399525573676508631577122671218044116107572676710
    assert format(dV,
                  str(ec.nsize) +
                  "x") == "45fb58a92a17ad4b15101c66e74f277e2b460866"

    QV = mult(dV, ec.G, ec)
    assert QV == (
        420773078745784176406965940076771545932416607676,
        221937774842090227911893783570676792435918278531,
    )
    assert (bytes_from_point(
        QV, ec).hex() == "0349b41e0e9c0369c2328739d90f63d56707c6e5bc")

    # expected results
    z_exp = 1155982782519895915997745984453282631351432623114
    zstr = "ca7c0f8c3ffa87a96e1b74ac8e6af594347bb40a"
    size = 20
    keying_data_exp = "744ab703f5bc082e59185f6d049d2d367db245c2"

    # 4.1.4
    z, _ = mult(dU, QV, ec)  # x coordinate only
    assert z == z_exp
    assert format(z, str(ec.psize) + "x") == zstr
    keyingdata = dh.ansi_x963_kdf(z.to_bytes(ec.psize, "big"), size, ec, hf)
    assert keyingdata.hex() == keying_data_exp

    # 4.1.5
    z, _ = mult(dV, QU, ec)  # x coordinate only
    assert z == z_exp
    assert format(z, str(ec.psize) + "x") == zstr
    keyingdata = dh.ansi_x963_kdf(z.to_bytes(ec.psize, "big"), size, ec, hf)
    assert keyingdata.hex() == keying_data_exp
示例#5
0
    def test_batch_validation(self):
        hsize = hf().digest_size
        hlen = hsize * 8

        ms = []
        Qs = []
        sigs = []
        ms.append(secrets.randbits(hlen).to_bytes(hsize, 'big'))
        q = 1 + secrets.randbelow(ec.n - 1)
        # bytes version
        Qs.append(mult(q, ec.G, ec)[0].to_bytes(ec.psize, 'big'))
        sigs.append(ssa.sign(ms[0], q, None, ec, hf))
        # test with only 1 sig
        ssa._batch_verify(ms, Qs, sigs, ec, hf)
        for _ in range(3):
            mhd = secrets.randbits(hlen).to_bytes(hsize, 'big')
            ms.append(mhd)
            q = 1 + secrets.randbelow(ec.n - 1)
            # Point version
            Qs.append(mult(q, ec.G, ec))
            sigs.append(ssa.sign(mhd, q, None, ec, hf))
        ssa._batch_verify(ms, Qs, sigs, ec, hf)
        self.assertTrue(ssa.batch_verify(ms, Qs, sigs, ec, hf))

        # invalid sig
        ms.append(ms[0])
        sigs.append(sigs[1])
        Qs.append(Qs[0])
        self.assertFalse(ssa.batch_verify(ms, Qs, sigs, ec, hf))
        self.assertRaises(AssertionError, ssa._batch_verify, ms, Qs, sigs, ec,
                          hf)
        # ssa._batch_verify(ms, Qs, sigs, ec, hf)
        sigs[-1] = sigs[0]  # valid again

        # Invalid size: 31 bytes instead of 32
        ms[-1] = ms[0][:-1]
        self.assertRaises(ValueError, ssa._batch_verify, ms, Qs, sigs, ec, hf)
        # ssa._batch_verify(ms, Qs, sigs, ec, hf)
        ms[-1] = ms[0]  # valid again

        # mismatch between number of pubkeys (5) and number of messages (6)
        ms.append(ms[0])  # add extra message
        self.assertRaises(ValueError, ssa._batch_verify, ms, Qs, sigs, ec, hf)
        # ssa._batch_verify(ms, Qs, sigs, ec, hf)
        ms.pop()  # valid again

        # mismatch between number of pubkeys (5) and number of signatures (6)
        sigs.append(sigs[0])  # add extra sig
        self.assertRaises(ValueError, ssa._batch_verify, ms, Qs, sigs, ec, hf)
        # ssa._batch_verify(ms, Qs, sigs, ec, hf)
        sigs.pop()  # valid again

        # field prime p is not equal to 3 (mod 4)
        self.assertRaises(ValueError, ssa._batch_verify, ms, Qs, sigs,
                          secp224k1, hf)
示例#6
0
文件: test_dh.py 项目: eehlers/btclib
    def test_ecdh(self):
        size = 20

        dU = 0x1
        QU = mult(dU, ec.G, ec)
        dV = 0x2
        QV = mult(dV, ec.G, ec)

        keyingdataU = dh.diffie_hellman(dh.ansi_x963_kdf, dU, QV, size, ec, hf)
        keyingdataV = dh.diffie_hellman(dh.ansi_x963_kdf, dV, QU, size, ec, hf)
        self.assertEqual(keyingdataU, keyingdataV)
示例#7
0
    def test_ecssa(self):
        """Basic tests"""
        q = 0x1
        Q = mult(q)
        msg = sha256(b'Satoshi Nakamoto').digest()
        sig = ssa.sign(msg, q, None)
        # no source for the following... but
        # https://bitcointalk.org/index.php?topic=285142.40
        # same r because of rfc6979
        exp_sig = (
            0x934B1EA10A4B3C1757E2B0C017D0B6143CE3C9A7E6A4A49860D7A6AB210EE3D8,
            0x2DF2423F70563E3C4BD0E00BDEF658081613858F110ECF937A2ED9190BF4A01A)
        self.assertEqual(sig[0], exp_sig[0])
        self.assertEqual(sig[1], exp_sig[1])

        ssa._verify(msg, Q, sig)
        self.assertTrue(ssa.verify(msg, Q, sig))
        self.assertTrue(ssa._verify(msg, Q, sig))

        fmsg = sha256(b'Craig Wright').digest()
        self.assertFalse(ssa.verify(fmsg, Q, sig))
        self.assertFalse(ssa._verify(fmsg, Q, sig))

        fssasig = (sig[0], sig[1], sig[1])
        self.assertFalse(ssa.verify(msg, Q, fssasig))
        self.assertRaises(TypeError, ssa._verify, msg, Q, fssasig)

        # y(sG - eP) is not a quadratic residue
        fq = 0x2
        fQ = mult(fq)
        self.assertFalse(ssa.verify(msg, fQ, sig))
        self.assertRaises(ValueError, ssa._verify, msg, fQ, sig)

        fq = 0x4
        fQ = mult(fq)
        self.assertFalse(ssa.verify(msg, fQ, sig))
        self.assertFalse(ssa._verify(msg, fQ, sig))

        # not ec.pIsThreeModFour
        self.assertFalse(ssa.verify(msg, Q, sig, secp224k1))
        self.assertRaises(ValueError, ssa._verify, msg, Q, sig, secp224k1)

        # verify: message of wrong size
        wrongmsg = msg[:-1]
        self.assertFalse(ssa.verify(wrongmsg, Q, sig))
        self.assertRaises(ValueError, ssa._verify, wrongmsg, Q, sig)
        #ssa._verify(wrongmsg, Q, sig)

        # sign: message of wrong size
        self.assertRaises(ValueError, ssa.sign, wrongmsg, q, None)
        #ssa.sign(wrongmsg, q, None)

        # invalid (zero) challenge e
        self.assertRaises(ValueError, ssa._pubkey_recovery, 0, sig)
示例#8
0
def test_ecdh():
    size = 20

    dU = 0x1
    QU = mult(dU, ec.G, ec)
    dV = 0x2
    QV = mult(dV, ec.G, ec)

    keyingdataU = dh.diffie_hellman(dh.ansi_x963_kdf, dU, QV, size, ec, hf)
    keyingdataV = dh.diffie_hellman(dh.ansi_x963_kdf, dV, QU, size, ec, hf)
    assert keyingdataU == keyingdataV
示例#9
0
    def test_batch_validation(self):
        ec = secp256k1
        hf = sha256
        m = []
        sig = []
        Q = []

        hsize = hf().digest_size
        hlen = hsize * 8
        m.append(random.getrandbits(hlen).to_bytes(hsize, byteorder='big'))
        q = (1 + random.getrandbits(ec.nlen)) % ec.n
        sig.append(ssa.sign(m[0], q, None, ec, hf))
        Q.append(mult(q, ec.G, ec))
        # test with only 1 sig
        self.assertTrue(ssa.batch_verify(m, Q, sig, ec, hf))
        for i in range(1, 4):
            m.append(random.getrandbits(hlen).to_bytes(hsize, byteorder='big'))
            q = (1 + random.getrandbits(ec.nlen)) % ec.n
            sig.append(ssa.sign(m[i], q, None, ec, hf))
            Q.append(mult(q, ec.G, ec))
        self.assertTrue(ssa.batch_verify(m, Q, sig, ec, hf))

        # invalid sig
        m.append(m[0])
        sig.append(sig[1])
        Q.append(Q[0])
        self.assertFalse(ssa.batch_verify(m, Q, sig, ec, hf))
        #ssa._batch_verify(m, Q, sig, ec, hf)
        sig[-1] = sig[0]  # valid again

        # invalid 31 bytes message
        m[-1] = m[0][:-1]
        self.assertFalse(ssa.batch_verify(m, Q, sig, ec, hf))
        #ssa._batch_verify(m, Q, sig, ec, hf)
        m[-1] = m[0]  # valid again

        # mismatch between number of pubkeys and number of messages
        m.append(m[0])  # add extra message
        self.assertRaises(ValueError, ssa._batch_verify, m, Q, sig, ec, hf)
        #ssa._batch_verify(m, Q, sig, ec, hf)
        m.pop()  # valid again

        # mismatch between number of pubkeys and number of signatures
        sig.append(sig[0])  # add extra sig
        self.assertRaises(ValueError, ssa._batch_verify, m, Q, sig, ec, hf)
        #ssa._batch_verify(m, Q, sig, ec, hf)
        sig.pop()  # valid again

        # curve prime p must be equal to 3 (mod 4)
        ec = secp224k1
        self.assertRaises(ValueError, ssa._batch_verify, m, Q, sig, ec, hf)
示例#10
0
def test_crack_prvkey():

    ec = secp256k1

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

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

    msg2 = "and Paolo is right to be afraid"
    msg2 = hf(msg2.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)
示例#11
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))
示例#12
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(dU, ec.G, ec)
        self.assertEqual(QU,
                         (466448783855397898016055842232266600516272889280,
                          1110706324081757720403272427311003102474457754220))
        self.assertEqual(
            bytes_from_point(QU, True, ec).hex(),
            '0251b4496fecc406ed0e75a24a3c03206251419dc0')

        # 2.1.3 Signing Operation for U
        msg = b'abc'
        k = 702232148019446860144825009548118511996283736794
        exp_sig = (0xCE2873E5BE449563391FEB47DDCBA2DC16379191,
                   0x3480EC1371A091A464B31CE47DF0CB8AA2D98B54)
        sig = dsa.sign(msg, dU, k, ec, hf)
        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(msg, QU, sig, ec, hf))
示例#13
0
def test_rfc6979_tv():

    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, ec, eval("hashlib." + hf))
            assert r == hex(sig[0])
            assert s in (hex(sig[1]), hex(ec.n - sig[1]))
            # test that RFC6979 is the default nonce for DSA
            sig = dsa.sign(msg, x, k=None, ec=ec, hf=eval("hashlib." + hf))
            assert r == hex(sig[0])
            assert s in (hex(sig[1]), hex(ec.n - 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))
示例#14
0
    def test_crack_prvkey(self):
        q = 0x6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725DEADBEEF
        x_Q = mult(q)[0]
        k = 1010101010101010101

        msg1 = "Paolo is afraid of ephemeral random numbers"
        msg1 = hf(msg1.encode()).digest()
        sig1 = ssa.sign(msg1, q, k)
        # print(f'\nmsg1: {msg1.hex().upper()}')
        # print(f'  r1: {hex(sig1[0]).upper()}')
        # print(f'  s1: {hex(sig1[1]).upper()}')

        msg2 = "and Paolo is right to be afraid"
        msg2 = hf(msg2.encode()).digest()
        sig2 = ssa.sign(msg2, q, k)
        # print(f'\nmsg2: {msg2.hex().upper()}')
        # print(f'  r2: {hex(sig2[0]).upper()}')
        # print(f'  s2: {hex(sig2[1]).upper()}')

        qc, kc = ssa.crack_prvkey(msg1, sig1, msg2, sig2, x_Q)
        self.assertIn(q, (qc, ec.n - qc))
        self.assertIn(k, (kc, ec.n - kc))

        self.assertRaises(ValueError, ssa.crack_prvkey, msg1, sig1, msg2,
                          (16, sig1[1]), x_Q)
        self.assertRaises(ValueError, ssa.crack_prvkey, msg1, sig1, msg1, sig1,
                          x_Q)
示例#15
0
    def test_all_curves(self):
        for ec in all_curves.values():
            self.assertEqual(mult(0, ec.G, ec), INF)
            self.assertEqual(mult(0, ec.G, ec), INF)

            self.assertEqual(mult(1, ec.G, ec), ec.G)
            self.assertEqual(mult(1, ec.G, ec), 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 = bytes_from_point(ec.G, ec)
            G2 = point_from_octets(Gbytes, ec)
            self.assertEqual(ec.G, G2)

            Gbytes = bytes_from_point(ec.G, ec, False)
            G2 = point_from_octets(Gbytes, ec)
            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(2, ec.G, ec))

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

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

            ec_repr = repr(ec)
            if ec in low_card_curves.values() or ec.psize < 24:
                ec_repr = ec_repr[:-1] + ", False)"
            ec2 = eval(ec_repr)
            self.assertEqual(str(ec), str(ec2))
示例#16
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')
示例#17
0
    def test_ecssa(self):
        """Basic tests"""
        q = 0x1
        Q = mult(q)
        mhd = hf(b'Satoshi Nakamoto').digest()
        sig = ssa.sign(mhd, q, None)
        ssa._verify(mhd, Q, sig, ec, hf)
        self.assertTrue(ssa.verify(mhd, Q, sig))

        fmhd = hf(b'Craig Wright').digest()
        self.assertRaises(AssertionError, ssa._verify, fmhd, Q, sig, ec, hf)

        fssasig = (sig[0], sig[1], sig[1])
        self.assertRaises(ValueError, ssa._verify, mhd, Q, fssasig, ec, hf)

        # y(sG - eP) is not a quadratic residue
        fq = 0x2
        fQ = mult(fq)
        self.assertRaises(ValueError, ssa._verify, mhd, fQ, sig, ec, hf)

        fq = 0x4
        fQ = mult(fq)
        self.assertRaises(AssertionError, ssa._verify, mhd, fQ, sig, ec, hf)

        # not ec.pIsThreeModFour
        self.assertRaises(ValueError, ssa._verify, mhd, Q, sig, secp224k1, hf)

        # verify: message of wrong size
        wrongmhd = mhd[:-1]
        self.assertRaises(ValueError, ssa._verify, wrongmhd, Q, sig, ec, hf)
        #ssa._verify(wrongmhd, Q, sig)

        # sign: message of wrong size
        self.assertRaises(ValueError, ssa.sign, wrongmhd, q, None)
        #ssa.sign(wrongmhd, q, None)

        # invalid (zero) challenge e
        self.assertRaises(ValueError, ssa._recover_pubkeys, 0, sig[0], sig[1],
                          ec)
        #ssa._recover_pubkeys(0, sig)

        # not a BIP340 public key
        self.assertRaises(ValueError, ssa.to_bip340_pubkey_tuple,
                          ["not", "a BIP340", "public key"])
示例#18
0
    def test_low_cardinality(self):
        """test low-cardinality curves for all msg/key pairs."""
        # ec.n has to be prime to sign
        prime = [11, 13, 17, 19]

        # for dsa it is possible to directy iterate on all
        # possible values for e;
        # for ssa we have to iterate over all possible hash values
        hsize = hf().digest_size
        H = [i.to_bytes(hsize, 'big') for i in range(max(prime) * 4)]
        # 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
                # BIP340 Schnorr only applies to curve whose prime p = 3 %4
                if not ec.pIsThreeModFour:
                    self.assertRaises(ValueError, ssa.sign, H[0], 1, None, ec)
                    continue
                for q in range(1, ec.n):  # all possible private keys
                    Q = mult(q, ec.G, ec)  # public key
                    if not ec.has_square_y(Q):
                        q = ec.n - q
                    for h in H:  # all possible hashed messages
                        k = ssa.k(h, q, ec, hf)
                        K = mult(k, ec.G, ec)
                        if not ec.has_square_y(K):
                            k = ec.n - k
                        x_K = K[0]

                        try:
                            c = ssa._challenge(x_K, Q[0], h, ec, hf)
                        except Exception:
                            pass
                        else:
                            s = (k + c * q) % ec.n
                            sig = ssa.sign(h, q, None, ec)
                            self.assertEqual((x_K, s), sig)
                            # valid signature must validate
                            self.assertIsNone(ssa._verify(h, Q, sig, ec, hf))

                            if c != 0:  # FIXME
                                x_Q = ssa._recover_pubkeys(c, x_K, s, ec)
                                self.assertEqual(Q[0], x_Q)
示例#19
0
    def test_octets2point(self):
        for ec in all_curves.values():
            Q = mult(ec.p, ec.G, ec)  # just a random point, not INF

            Q_bytes = b'\x03' if Q[1] & 1 else b'\x02'
            Q_bytes += Q[0].to_bytes(ec.psize, byteorder='big')
            R = point_from_octets(Q_bytes, ec)
            self.assertEqual(R, Q)
            self.assertEqual(bytes_from_point(R, ec), Q_bytes)

            Q_hex_str = Q_bytes.hex()
            R = point_from_octets(Q_hex_str, ec)
            self.assertEqual(R, Q)

            Q_bytes = b'\x04' + Q[0].to_bytes(ec.psize, byteorder='big')
            Q_bytes += Q[1].to_bytes(ec.psize, byteorder='big')
            R = point_from_octets(Q_bytes, ec)
            self.assertEqual(R, Q)
            self.assertEqual(bytes_from_point(R, ec, False), Q_bytes)

            Q_hex_str = Q_bytes.hex()
            R = point_from_octets(Q_hex_str, ec)
            self.assertEqual(R, Q)

            # scalar in point multiplication can be int, str, or bytes
            t = tuple()
            self.assertRaises(TypeError, mult, t, ec.G, ec)

            # not a compressed point
            Q_bytes = b'\x01' * (ec.psize + 1)
            self.assertRaises(ValueError, point_from_octets, Q_bytes, ec)
            # not a point
            Q_bytes += b'\x01'
            self.assertRaises(ValueError, point_from_octets, Q_bytes, ec)
            # not an uncompressed point
            Q_bytes = b'\x01' * 2 * (ec.psize + 1)
            self.assertRaises(ValueError, point_from_octets, Q_bytes, ec)

        # invalid x coordinate
        ec = CURVES['secp256k1']
        x = 0xEEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34
        xstr = format(x, '32X')
        self.assertRaises(ValueError, point_from_octets, "03" + xstr, ec)
        self.assertRaises(ValueError, point_from_octets, "04" + 2 * xstr, ec)
        self.assertRaises(ValueError, bytes_from_point, (x, x), ec)
        self.assertRaises(ValueError, bytes_from_point, (x, x), ec, False)

        # Point must be a tuple[int, int]
        P = x, x, x
        self.assertRaises(ValueError, ec.is_on_curve, P)

        # y-coordinate not in (0, p)
        P = x, ec.p + 1
        self.assertRaises(ValueError, ec.is_on_curve, P)
示例#20
0
def test_assorted_mult2():
    ec = ec23_31
    H = second_generator(ec)
    for k1 in range(-ec.n + 1, ec.n):
        K1 = mult(k1, ec.G, ec)
        for k2 in range(ec.n):
            K2 = mult(k2, H, ec)

            shamir = double_mult(k1, ec.G, k2, ec.G, ec)
            assert shamir == mult(k1 + k2, ec.G, ec)

            shamir = double_mult(k1, INF, k2, H, ec)
            assert shamir == K2
            shamir = double_mult(k1, ec.G, k2, INF, ec)
            assert shamir == K1

            shamir = double_mult(k1, ec.G, k2, H, ec)
            K1K2 = ec.add(K1, K2)
            assert K1K2 == shamir

            k3 = 1 + secrets.randbelow(ec.n - 1)
            K3 = mult(k3, ec.G, ec)
            K1K2K3 = ec.add(K1K2, K3)
            boscoster = multi_mult([k1, k2, k3], [ec.G, H, ec.G], ec)
            assert K1K2K3 == boscoster

            k4 = 1 + secrets.randbelow(ec.n - 1)
            K4 = mult(k4, H, ec)
            K1K2K3K4 = ec.add(K1K2K3, K4)
            points = [ec.G, H, ec.G, H]
            boscoster = multi_mult([k1, k2, k3, k4], points, ec)
            assert K1K2K3K4 == boscoster
            assert K1K2K3 == multi_mult([k1, k2, k3, 0], points, ec)
            assert K1K2 == multi_mult([k1, k2, 0, 0], points, ec)
            assert K1 == multi_mult([k1, 0, 0, 0], points, ec)
            assert INF == 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.G, H, ec.G], ec)
示例#21
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(d, ec.G, ec)  # 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(k, ec.G, ec)

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

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

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

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

                            keys = dsa._pubkey_recovery(e, sig, ec)
                            self.assertIn(P, keys)
                            for Q in keys:
                                self.assertTrue(dsa._verhlp(e, Q, sig, ec))
示例#22
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, byteorder='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, H[0], 1, None, ec)
                    continue
                for q in range(ec.n):  # all possible private keys
                    if q == 0:  # invalid prvkey=0
                        self.assertRaises(ValueError, ssa.sign, H[0], q, None,
                                          ec)
                        self.assertRaises(ValueError, rfc6979, H[0], q, ec)
                        continue
                    Q = mult(q, ec.G, ec)  # public key
                    for h in H:  # all possible hashed messages
                        # k = 0
                        self.assertRaises(ValueError, ssa.sign, h, q, 0, ec)
                        k = rfc6979(h, q, ec)
                        K = mult(k, ec.G, ec)
                        if legendre_symbol(K[1], ec._p) != 1:
                            k = ec.n - k

                        e = ssa._e(K[0], Q, h, ec)
                        s = (k + e * q) % ec.n
                        # valid signature
                        sig = ssa.sign(h, q, k, ec)
                        self.assertEqual((K[0], s), sig)
                        # valid signature must validate
                        self.assertTrue(ssa._verify(h, Q, sig, ec))
示例#23
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)
示例#24
0
    def test_signtocontract(self):
        prv = 0x1
        pub = mult(prv)
        m = b"to be signed"
        c = b"to be committed"

        dsa_sig, dsa_receipt = ecdsa_commit_sign(c, m, prv, None)
        self.assertIsNone(dsa._verify(m, pub, dsa_sig, ec, sha256))
        self.assertTrue(verify_commit(c, dsa_receipt))

        # 32 bytes message for ECSSA
        m = sha256(m).digest()
        ssa_sig, ssa_receipt = ecssa_commit_sign(c, m, prv, None)
        self.assertIsNone(ssa._verify(m, pub, ssa_sig, ec, sha256))
        self.assertTrue(verify_commit(c, ssa_receipt))
示例#25
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")
示例#26
0
    def test_boscoster(self):
        ec = secp256k1

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

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

        # mismatch between scalar length and Points length
        P = [ec.G] * (len(k) - 1)
        self.assertRaises(ValueError, multi_mult, k, P, ec)
示例#27
0
    def test_pubkey_recovery(self):
        ec = secp112r2
        q = 0x10
        Q = mult(q, ec.G, ec)
        msg = b'Satoshi Nakamoto'
        sig = dsa.sign(msg, q, None, ec)

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

        keys = dsa.pubkey_recovery(msg, sig, ec)
        self.assertEqual(len(keys), 4)
        self.assertIn(Q, keys)
        for Q in keys:
            self.assertTrue(dsa.verify(msg, Q, sig, ec))
            self.assertTrue(dsa._verify(msg, Q, sig, ec))
示例#28
0
def test_invalid_schnorr():
    sighash = bytes.fromhex("00" * 32)
    sig = ssa.serialize(*ssa._sign(sighash, 1))
    pubkey = bytes_from_point(mult(1))
    pubkey_hash = hash256(pubkey)
    script = Script([
        [0x00, 0x00, pubkey],
        [0x01, 0x00, sig],
        [0x02, 0x00, pubkey_hash],  # push pubkey_hash
        [0x03, 0x02, b"\x00"],  # hash of pub key from unlocking script
        [0xFF, 0x01, b"\x03\x02"],  # check equality
        [0xFF, 0x04, b"\xff"],  # exit if not equal
        [0xFF, 0x03, b"\x00\x01"],  # schnorr verify
        [0xFF, 0x04, b"\xff"],
    ]  # exit if not equal])  # push signature
                    )
    assert script.execute(memory={0x100: sighash})
示例#29
0
    def test_pubkey_recovery(self):
        ec = secp112r2
        q = 0x10
        Q = mult(q, ec.G, ec)
        msg = 'Satoshi Nakamoto'
        k = sighash = None
        sig = dsa.sign(msg, q, k, ec)
        self.assertTrue(dsa.verify(msg, Q, sig, ec))
        dersig = der.serialize(*sig, sighash, ec)
        self.assertTrue(dsa.verify(msg, Q, dersig, ec))
        r, s, _ = der.deserialize(dersig)
        self.assertEqual((r, s), sig)

        keys = dsa.recover_pubkeys(msg, dersig, ec)
        self.assertEqual(len(keys), 4)
        self.assertIn(Q, keys)
        for Q in keys:
            self.assertTrue(dsa.verify(msg, Q, sig, ec))
示例#30
0
 def test_shamir(self):
     ec = ec23_31
     for k1 in range(ec.n):
         for k2 in range(ec.n):
             shamir = double_mult(k1, ec.G, k2, ec.G, ec)
             std = ec.add(mult(k1, ec.G, ec), mult(k2, ec.G, ec))
             self.assertEqual(shamir, std)
             shamir = double_mult(k1, INF, k2, ec.G, ec)
             std = ec.add(mult(k1, INF, ec), mult(k2, ec.G, ec))
             self.assertEqual(shamir, std)
             shamir = double_mult(k1, ec.G, k2, INF, ec)
             std = ec.add(mult(k1, ec.G, ec), mult(k2, INF, ec))
             self.assertEqual(shamir, std)