Example #1
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))
Example #2
0
    def test_schnorr_bip_tv(self):
        """Bip-Schnorr Test Vectors

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

        hf = sha256

        # test vector 1
        prv = int_from_bits(b'\x00' * 31 + b'\x01')
        pub = mult(prv)
        msg = b'\x00' * 32
        expected_sig = (
            0x787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF6,
            0x7031A98831859DC34DFFEEDDA86831842CCD0079E1F92AF177F7F22CC1DCED05)
        eph_prv = int.from_bytes(hf(prv.to_bytes(32, byteorder='big') +
                                    msg).digest(),
                                 byteorder='big')
        sig = ssa.sign(msg, prv, eph_prv)
        self.assertTrue(ssa._verify(msg, pub, sig))
        self.assertEqual(sig, expected_sig)
        e = ssa._e(sig[0], pub, msg)
        self.assertEqual(ssa._pubkey_recovery(e, sig), pub)

        # test vector 2
        prv = 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF
        pub = mult(prv)
        msg = bytes.fromhex(
            "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
        expected_sig = (
            0x2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D,
            0x1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD)
        eph_prv = int.from_bytes(hf(prv.to_bytes(32, byteorder='big') +
                                    msg).digest(),
                                 byteorder='big')
        sig = ssa.sign(msg, prv, eph_prv)
        self.assertTrue(ssa._verify(msg, pub, sig))
        self.assertEqual(sig, expected_sig)
        e = ssa._e(sig[0], pub, msg)
        self.assertEqual(ssa._pubkey_recovery(e, sig), pub)

        # test vector 3
        prv = 0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7
        pub = mult(prv)
        msg = bytes.fromhex(
            "5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C")
        expected_sig = (
            0x00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE,
            0x00880371D01766935B92D2AB4CD5C8A2A5837EC57FED7660773A05F0DE142380)
        eph_prv = int.from_bytes(hf(prv.to_bytes(32, byteorder='big') +
                                    msg).digest(),
                                 byteorder='big')
        sig = ssa.sign(msg, prv, eph_prv)
        self.assertTrue(ssa._verify(msg, pub, sig))
        self.assertEqual(sig, expected_sig)
        e = ssa._e(sig[0], pub, msg)
        self.assertEqual(ssa._pubkey_recovery(e, sig), pub)

        # test vector 4
        pub = point_from_octets(
            "03DEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34"
        )
        msg = bytes.fromhex(
            "4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703")
        sig = (
            0x00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63,
            0x02A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D)
        self.assertTrue(ssa._verify(msg, pub, sig))
        e = ssa._e(sig[0], pub, msg)
        self.assertEqual(ssa._pubkey_recovery(e, sig), pub)

        # test vector 5
        # test would fail if jacobi symbol of x(R) instead of y(R) is used
        pub = point_from_octets(
            "031B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F"
        )
        msg = bytes.fromhex(
            "0000000000000000000000000000000000000000000000000000000000000000")
        sig = (
            0x52818579ACA59767E3291D91B76B637BEF062083284992F2D95F564CA6CB4E35,
            0x30B1DA849C8E8304ADC0CFE870660334B3CFC18E825EF1DB34CFAE3DFC5D8187)
        self.assertTrue(ssa._verify(msg, pub, sig))
        e = ssa._e(sig[0], pub, msg)
        self.assertEqual(ssa._pubkey_recovery(e, sig), pub)

        # test vector 6
        # test would fail if msg is reduced
        pub = point_from_octets(
            "03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B"
        )
        msg = bytes.fromhex(
            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
        sig = (
            0x570DD4CA83D4E6317B8EE6BAE83467A1BF419D0767122DE409394414B05080DC,
            0xE9EE5F237CBD108EABAE1E37759AE47F8E4203DA3532EB28DB860F33D62D49BD)
        self.assertTrue(ssa._verify(msg, pub, sig))
        e = ssa._e(sig[0], pub, msg)
        self.assertEqual(ssa._pubkey_recovery(e, sig), pub)

        # new proposed test: test would fail if msg is reduced
        pub = point_from_octets(
            "03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B"
        )
        msg = bytes.fromhex(
            "000008D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A5000000")
        sig = (
            0x3598678C6C661F02557E2F5614440B53156997936FE54A90961CFCC092EF789D,
            0x41E4E4386E54C924251679ADD3D837367EECBFF248A3DE7C2DB4CE52A3D6192A)
        self.assertTrue(ssa._verify(msg, pub, sig))
        e = ssa._e(sig[0], pub, msg)
        self.assertEqual(ssa._pubkey_recovery(e, sig), pub)

        # new proposed test: genuine failure
        pub = point_from_octets(
            "03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B"
        )
        msg = bytes.fromhex(
            "0000000000000000000000000000000000000000000000000000000000000000")
        sig = (
            0x3598678C6C661F02557E2F5614440B53156997936FE54A90961CFCC092EF789D,
            0x41E4E4386E54C924251679ADD3D837367EECBFF248A3DE7C2DB4CE52A3D6192A)
        self.assertFalse(ssa._verify(msg, pub, sig))

        # new proposed test: P = infinite
        pub = 1, 0
        msg = bytes.fromhex(
            "5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C")
        sig = (
            0x00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE,
            0x00880371D01766935B92D2AB4CD5C8A2A5837EC57FED7660773A05F0DE142380)
        self.assertRaises(ValueError, ssa._verify, msg, pub, sig)

        # test vector 7
        # public key not on the curve
        # impossible to verify with btclib analytics as it at Point conversion
        self.assertRaises(
            ValueError, point_from_octets,
            "03EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34"
        )
        # msg = bytes.fromhex("4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703")
        # sig = (0x00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63, 0x02A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D)
        # self.assertRaises(ValueError, ssa._verify, msg, pub, sig)

        # test vector 8
        # Incorrect sig: incorrect R residuosity
        pub = point_from_octets(
            "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"
        )
        msg = bytes.fromhex(
            "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
        sig = (
            0x2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D,
            0xFA16AEE06609280A19B67A24E1977E4697712B5FD2943914ECD5F730901B4AB7)
        self.assertRaises(ValueError, ssa._verify, msg, pub, sig)

        # test vector 9
        # Incorrect sig: negated message hash
        pub = point_from_octets(
            "03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B"
        )
        msg = bytes.fromhex(
            "5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C")
        sig = (
            0x00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE,
            0xD092F9D860F1776A1F7412AD8A1EB50DACCC222BC8C0E26B2056DF2F273EFDEC)
        self.assertRaises(ValueError, ssa._verify, msg, pub, sig)

        # test vector 10
        # Incorrect sig: negated s value
        pub = point_from_octets(
            "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
        )
        msg = b'\x00' * 32
        sig = (
            0x787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF6,
            0x8FCE5677CE7A623CB20011225797CE7A8DE1DC6CCD4F754A47DA6C600E59543C)
        self.assertRaises(ValueError, ssa._verify, msg, pub, sig)

        # test vector 11
        # Incorrect sig: negated public key
        pub = point_from_octets(
            "03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"
        )
        msg = bytes.fromhex(
            "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
        sig = (
            0x2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D,
            0x1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD)
        self.assertRaises(ValueError, ssa._verify, msg, pub, sig)

        # test vector 12
        # sG - eP is infinite.
        # Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0
        pub = point_from_octets(
            "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"
        )
        msg = bytes.fromhex(
            "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
        sig = (
            0x0000000000000000000000000000000000000000000000000000000000000000,
            0x9E9D01AF988B5CEDCE47221BFA9B222721F3FA408915444A4B489021DB55775F)
        self.assertRaises(ValueError, ssa._verify, msg, pub, sig)

        # test vector 13
        # sG - eP is infinite.
        # Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1"""
        pub = point_from_octets(
            "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"
        )
        msg = bytes.fromhex(
            "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
        sig = (
            0x0000000000000000000000000000000000000000000000000000000000000001,
            0xD37DDF0254351836D84B1BD6A795FD5D523048F298C4214D187FE4892947F728)
        self.assertRaises(ValueError, ssa._verify, msg, pub, sig)

        # test vector 14
        # sig[0:32] is not an X coordinate on the curve
        pub = point_from_octets(
            "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"
        )
        msg = bytes.fromhex(
            "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
        sig = (
            0x4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D,
            0x1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD)
        self.assertFalse(ssa._verify(msg, pub, sig))

        # test vector 15
        # sig[0:32] is equal to field size
        pub = point_from_octets(
            "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"
        )
        msg = bytes.fromhex(
            "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
        sig = (
            0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2F,
            0x1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD)
        #self.assertRaises(ValueError, ssa._verify, msg, pub, sig)
        self.assertFalse(ssa._verify(msg, pub, sig))

        # test vector 16
        # sig[32:64] is equal to curve order
        pub = point_from_octets(
            "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"
        )
        msg = bytes.fromhex(
            "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
        sig = (
            0x2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D,
            0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141)
        self.assertRaises(ValueError, ssa._verify, msg, pub, sig)