Ejemplo n.º 1
0
    def test_ec_pubkey_parse(self):
        for flags in self.context_flags:
            # Create context
            ctx = secpy256k1.context_create(flags)

            # Parse variable length public key from bytes
            secp256k1_pubkey_tuple = secpy256k1.ec_pubkey_parse(
                ctx, self.pubkey)

            # First tuple entry returns a 1 for a fully valid public key
            self.assertEqual(secp256k1_pubkey_tuple[0], 1)

            # Second tuple entry returns a pointer to a secp256k1_pubkey
            self.assertEqual(secpy256k1.ffi.typeof(secp256k1_pubkey_tuple[1]),
                             secpy256k1.ffi.typeof('secp256k1_pubkey *'))

        # Errors if invalid context flag
        with self.assertRaises(TypeError) as err:
            secpy256k1.ec_pubkey_parse(0, self.pubkey)

        self.assertIn(
            'Invalid context. Must be secp256k1_context_struct pointer.',
            str(err.exception))

        # Errors if invalid seralized public key
        with self.assertRaises(ValueError) as err:
            secpy256k1.ec_pubkey_parse(ctx, 0)

        self.assertIn('Invalid pubkey. Must be 33- or 65-bytes.',
                      str(err.exception))
Ejemplo n.º 2
0
def verify_hash(pubkey: bytes, sig: bytes, digest: bytes) -> bool:
    '''
    Verifies a signature on a specific hash

    NB: ECDSA is NOT SECURE unless the verifier calculates the hash

    Args:
        pubkey (bytes): the public key in compressed or uncompressed form
        sig    (bytes): the der encoded signature
        digest (bytes): the 32 byte message digest
    Returns:
        (bool): True if valid signature, false otherwise
    '''
    if len(digest) != 32:
        raise ValueError('Digest must be 32 bytes')

    ctx = get_verify_context()

    pubkey_tuple = secpy256k1.ec_pubkey_parse(ctx, pubkey)

    if pubkey_tuple[0] != 1:
        raise Exception('unknown exception -- pubkey parse failed')

    sig_tuple = secpy256k1.ecdsa_signature_parse_der(ctx, sig)

    if sig_tuple[0] != 1:
        raise Exception('unknown exception -- sig parse failed')

    res = secpy256k1.ecdsa_verify(ctx, sig_tuple[1], digest, pubkey_tuple[1])

    return True if res == 1 else False
Ejemplo n.º 3
0
def tweak_pubkey_mul(pubkey: bytes,
                     tweak: bytes,
                     compressed: bool = True) -> bytes:
    '''
    Tweaks a pubkey by multiplying by a 32 byte tweak
    Args:
        pubkey (bytes): 32 byte pubkey
        tweak   (bytes): 32 byte tweak
    Returns:
        (bytes): 32 byte tweaked pubkey
    '''
    ctx = get_verify_context()

    if len(tweak) != 32:
        raise ValueError('tweak must be 32 bytes')

    pubkey_tuple = secpy256k1.ec_pubkey_parse(ctx, pubkey)

    if pubkey_tuple[0] != 1:
        raise Exception('unknown exception -- pubkey parse failed')

    tweaked_tuple = secpy256k1.ec_pubkey_tweak_mul(ctx, pubkey_tuple[1], tweak)

    if tweaked_tuple[0] != 1:
        raise Exception('unknown exception -- pubkey tweak mul failed')

    flag = (secpy256k1.lib.SECP256K1_EC_COMPRESSED
            if compressed else secpy256k1.lib.SECP256K1_EC_UNCOMPRESSED)
    pubkey_ser_tuple = secpy256k1.ec_pubkey_serialize(ctx, tweaked_tuple[1],
                                                      flag)

    if pubkey_ser_tuple[0] != 1:
        raise Exception('unknown exception -- pubkey ser failed')

    return bytes(secpy256k1.ffi.buffer(pubkey_ser_tuple[1]))
Ejemplo n.º 4
0
    def test_ecdsa_verify(self):
        verify_context = secpy256k1.context_create(
            secpy256k1.lib.SECP256K1_CONTEXT_VERIFY)

        parsed_sig_tuple = secpy256k1.ecdsa_signature_parse_compact(
            verify_context, self.compact_sig)

        secp256k1_pubkey_tuple = secpy256k1.ec_pubkey_parse(
            verify_context, self.pubkey)

        verify_res = secpy256k1.ecdsa_verify(verify_context,
                                             parsed_sig_tuple[1], self.msg,
                                             secp256k1_pubkey_tuple[1])

        self.assertEqual(verify_res, 1)
Ejemplo n.º 5
0
    def test_ec_privkey_tweak_add(self):
        # Create context
        secp256k1_ctx = secpy256k1.context_create(
            secpy256k1.lib.SECP256K1_CONTEXT_VERIFY)

        # Create COMPRESSED secp256k1_pubkey object to add tweak
        secp256k1_pubkey_tuple = secpy256k1.ec_pubkey_parse(
            secp256k1_ctx, self.pubkey)
        secp256k1_pubkey = secp256k1_pubkey_tuple[1]

        # Tweaked secp256k1_pubkey
        secp256k1_pubkey_tweak_tuple = secpy256k1.ec_pubkey_tweak_add(
            secp256k1_ctx, secp256k1_pubkey, self.tweak)

        # First tuple entry returns a 1 for a fully valid public key
        self.assertEqual(secp256k1_pubkey_tweak_tuple[0], 1)

        # Second tuple entry returns a tweaked secp256k1_pubkey pointer type
        self.assertEqual(
            secpy256k1.ffi.typeof(secp256k1_pubkey_tweak_tuple[1]),
            secpy256k1.ffi.typeof('secp256k1_pubkey *'))

        # Errors if invalid context
        with self.assertRaises(TypeError) as err:
            secpy256k1.ec_pubkey_tweak_add(0, self.pubkey, self.tweak)

        self.assertIn(
            'Invalid context. Must be secp256k1_context_struct pointer.',
            str(err.exception))

        # Errors if invalid pubkey
        with self.assertRaises(TypeError) as err:
            secpy256k1.ec_pubkey_tweak_add(secp256k1_ctx, self.pubkey,
                                           self.tweak)

        self.assertIn('Invalid pubkey. Must be secp256k1_pubkey pointer.',
                      str(err.exception))

        # Errors if invalid tweak
        with self.assertRaises(ValueError) as err:
            secpy256k1.ec_pubkey_tweak_add(secp256k1_ctx, secp256k1_pubkey,
                                           bytes.fromhex('00000001'))

        self.assertIn('Invalid tweak. Must be 32-bytes.', str(err.exception))
Ejemplo n.º 6
0
def compress_pubkey(pubkey: bytes) -> bytes:
    '''
    Converts an uncompressed pubkey to a compressed pubkey
    Args:
        pubkey (bytes): the 65 byte uncompressed key
    Returns:
        (bytes): the compressed (33 byte) pubkey
    '''
    ctx = get_verify_context()

    pubkey_tuple = secpy256k1.ec_pubkey_parse(ctx, pubkey)

    if pubkey_tuple[0] != 1:
        raise Exception('unknown exception -- pubkey parse failed')

    pubkey_ser_tuple = secpy256k1.ec_pubkey_serialize(
        ctx, pubkey_tuple[1], secpy256k1.lib.SECP256K1_EC_COMPRESSED)

    if pubkey_ser_tuple[0] != 1:
        raise Exception('unknown exception -- pubkey ser failed')

    return bytes(secpy256k1.ffi.buffer(pubkey_ser_tuple[1]))
Ejemplo n.º 7
0
    def test_ec_pubkey_serialize(self):
        for flags in self.context_flags:
            # Create context
            secp256k1_ctx = secpy256k1.context_create(flags)

            # Create COMPRESSED secp256k1_pubkey object to serialize
            secp256k1_pubkey_tuple = secpy256k1.ec_pubkey_parse(
                secp256k1_ctx, self.pubkey)
            secp256k1_pubkey = secp256k1_pubkey_tuple[1]

            # Serialize COMPRESSED pubkey
            pubkey_ser_tuple = secpy256k1.ec_pubkey_serialize(
                secp256k1_ctx, secp256k1_pubkey,
                secpy256k1.lib.SECP256K1_EC_COMPRESSED)
            pubkey_int = pubkey_ser_tuple[0]
            pubkey_ser = pubkey_ser_tuple[1]
            pubkeylen = pubkey_ser_tuple[2]

            # First tuple entry always returns 1
            self.assertEqual(pubkey_int, 1)

            # Second tuple entry returns type char[] pointer to COMPRESSED
            # public key byte array
            self.assertEqual(secpy256k1.ffi.typeof(pubkey_ser),
                             secpy256k1.ffi.typeof('char[]'))

            self.assertEqual(secpy256k1.ffi.sizeof(pubkey_ser), 33)

            # Third tuple entry returns type size_t* pointer to public key size
            self.assertEqual(secpy256k1.ffi.typeof(pubkeylen),
                             secpy256k1.ffi.typeof('size_t*'))

        # Errors if invalid context flag
        with self.assertRaises(TypeError) as err:
            secpy256k1.ec_pubkey_parse(0, self.pubkey)

        self.assertIn(
            'Invalid context. Must be secp256k1_context_struct pointer.',
            str(err.exception))

        # Errors if invalid seralized public key
        with self.assertRaises(ValueError) as err:
            secpy256k1.ec_pubkey_parse(secp256k1_ctx, 0)

        self.assertIn('Invalid pubkey. Must be 33- or 65-bytes.',
                      str(err.exception))

        for flags in self.context_flags:
            # Create context
            secp256k1_ctx = secpy256k1.context_create(flags)

            # Create UNCOMPRESSED secp256k1_pubkey object to serialize
            secp256k1_pubkey_tuple = secpy256k1.ec_pubkey_parse(
                secp256k1_ctx, self.uncomp_pubkey)
            secp256k1_pubkey = secp256k1_pubkey_tuple[1]

            # Serialize UNCOMPRESSED pubkey
            pubkey_ser_tuple = secpy256k1.ec_pubkey_serialize(
                secp256k1_ctx, secp256k1_pubkey,
                secpy256k1.lib.SECP256K1_EC_UNCOMPRESSED)
            pubkey_int = pubkey_ser_tuple[0]
            pubkey_ser = pubkey_ser_tuple[1]
            pubkeylen = pubkey_ser_tuple[2]

            # First tuple entry always returns 1
            self.assertEqual(pubkey_int, 1)

            # Second tuple entry returns type char[] pointer to UNCOMPRESSED
            # public key byte array
            self.assertEqual(secpy256k1.ffi.typeof(pubkey_ser),
                             secpy256k1.ffi.typeof('char[]'))

            self.assertEqual(secpy256k1.ffi.sizeof(pubkey_ser), 65)

            # Third tuple entry returns type size_t* pointer to public key size
            self.assertEqual(secpy256k1.ffi.typeof(pubkeylen),
                             secpy256k1.ffi.typeof('size_t*'))

        # Errors if invalid context flag
        with self.assertRaises(TypeError) as err:
            secpy256k1.ec_pubkey_parse(0, self.pubkey)

        self.assertIn(
            'Invalid context. Must be secp256k1_context_struct pointer.',
            str(err.exception))

        # Errors if invalid seralized public key
        with self.assertRaises(ValueError) as err:
            secpy256k1.ec_pubkey_parse(secp256k1_ctx, 0)

        self.assertIn('Invalid pubkey. Must be 33- or 65-bytes.',
                      str(err.exception))
Ejemplo n.º 8
0
    '0290999dbbf43034bffb1dd53eac1eb4c33a4ea1c4f48ba585cfde3830840f0555'
)  # noqa: E501
uncomp_pubkey = bytes.fromhex(
    '0490999dbbf43034bffb1dd53eac1eb4c33a4ea1c4f48ba585cfde3830840f05553a9d6d07e79ae2fbe0bc0b20c93e1f8e20d74b8a0a7028e32d9a6808b6c38df4'
)  # noqa: E501
tweak = b'\x66' * 32  # noqa: E501
msg = bytes.fromhex('deadbeef' * 8)

verify_context = secpy256k1.context_create(SECP256K1_CONTEXT_VERIFY)
sign_context = secpy256k1.context_create(SECP256K1_CONTEXT_SIGN)

# try cloning to make sure it doesn't error
secpy256k1.context_clone(verify_context)

# parse the pubkey to a secpy pubkey tuple
secp256k1_pubkey_tuple = secpy256k1.ec_pubkey_parse(verify_context, pubkey)

# serialize the pubkey
output_tuple = secpy256k1.ec_pubkey_serialize(verify_context,
                                              secp256k1_pubkey_tuple[1],
                                              SECP256K1_EC_COMPRESSED)

ser_pub = output_tuple[1]
pubkey_ser = bytes(secpy256k1.ffi.buffer(ser_pub))
print('\n\npubkey_ser', pubkey_ser.hex())

# check pubkey tweak function
tweaked_pubkey_tuple = secpy256k1.ec_pubkey_tweak_add(
    verify_context,
    secpy256k1.ec_pubkey_parse(verify_context, pubkey)[1], tweak)
tweaked_pubkey = tweaked_pubkey_tuple[1]