Beispiel #1
0
    def __init__(self, H):
        assert isinstance(H, bytes)

        if not seclib:
            try:
                Hpoint = ser_to_point(H)
            except:
                raise ValueError("H could not be parsed")
            HGpoint = Hpoint + ecdsa.SECP256k1.generator
            if HGpoint == ecdsa.ellipticcurve.INFINITY:
                # this happens if H = -G
                raise InsecureHPoint(-1)
            self._ecdsa_H = Hpoint
            self._ecdsa_HG = HGpoint

            self.H = point_to_ser(Hpoint, comp=False)
            self.HG = point_to_ser(HGpoint, comp=False)
        else:
            ctx = seclib.ctx
            H_buf = create_string_buffer(64)
            res = seclib.secp256k1_ec_pubkey_parse(ctx, H_buf, H, c_size_t(len(H)))
            if not res:
                raise ValueError('H could not be parsed by the secp256k1 library')

            self._seclib_H = H_buf.raw

            G = point_to_ser(ecdsa.SECP256k1.generator, comp=False)
            G_buf = create_string_buffer(64)
            res = seclib.secp256k1_ec_pubkey_parse(ctx, G_buf, G, c_size_t(len(G)))
            assert res, "G point should always deserialize without issue"

            HG_buf = create_string_buffer(64)
            publist = (c_void_p*2)(*(cast(x, c_void_p) for x in (H_buf, G_buf)))
            res = seclib.secp256k1_ec_pubkey_combine(ctx, HG_buf, publist, 2)
            if res != 1:
                # this happens if H = -G
                raise InsecureHPoint(-1)

            self._seclib_HG = HG_buf.raw

            # now serialize H and HG as uncompressed bytes
            serpoint = create_string_buffer(65)
            sersize = c_size_t(65)

            res = seclib.secp256k1_ec_pubkey_serialize(ctx, serpoint, byref(sersize), H_buf, secp256k1.SECP256K1_EC_UNCOMPRESSED)
            assert res == 1
            assert sersize.value == 65
            self.H = serpoint.raw

            res = seclib.secp256k1_ec_pubkey_serialize(ctx, serpoint, byref(sersize), HG_buf, secp256k1.SECP256K1_EC_UNCOMPRESSED)
            assert res == 1
            assert sersize.value == 65
            self.HG = serpoint.raw
Beispiel #2
0
 def verify_tx_signature(signature, transaction, verification_key, utxo):
     '''Verify the signature for a specific utxo ("prevout_hash:n") given a
     transaction and verification key. Ensures that the signature is valid
     AND canonically encoded, so it will be accepted by network.
     '''
     tx_num = None
     for n, x in enumerate(transaction.inputs()):
         if (verification_key in x['pubkeys']
                 and utxo == "{}:{}".format(x['tx_hash'], x['tx_pos'])):
             tx_num = n
             break
     else:
         # verification_key / utxo combo not found in tx inputs, bail
         return False
     # calculate sighash digest (implicitly this is for sighash 0x41)
     pre_hash = Hash(bfh(transaction.serialize_preimage(tx_num)))
     order = generator_secp256k1.order()
     try:
         sigbytes = bfh(signature.decode())
     except ValueError:
         # not properly hex encoded or UnicodeDecodeError (garbage data)
         return False
     if not sigbytes or sigbytes[-1] != 0x41:
         return False
     DERsig = sigbytes[:
                       -1]  # lop off the sighash byte for the DER check below
     try:
         # ensure DER encoding is canonical, and extract r,s if OK
         r, s = CoinUtils.IsValidDERSignatureEncoding_With_Extract(DERsig)
     except AssertionError:
         return False
     if (s << 1) > order:
         # high S values are rejected by BCH network
         return False
     try:
         pubkey_point = ser_to_point(bfh(verification_key))
     except:
         # ser_to_point will fail if pubkey is off-curve, infinity, or garbage.
         return False
     vk = MyVerifyingKey.from_public_point(pubkey_point, curve=SECP256k1)
     try:
         return vk.verify_digest(DERsig,
                                 pre_hash,
                                 sigdecode=ecdsa.util.sigdecode_der)
     except:
         # verify_digest returns True on success, otherwise raises
         return False
Beispiel #3
0
def add_points(points_iterable):
    """ Adds one or more serialized points together. This is fastest if the
    points are already uncompressed. Returns uncompressed point.

    Note: intermediate sums are allowed to be the point at infinity, but not the
    final result.
    """
    plist = []
    if seclib:
        ctx = seclib.ctx
        for pser in points_iterable:
            P_buf = create_string_buffer(64)
            _b = bytes(pser)
            res = seclib.secp256k1_ec_pubkey_parse(ctx, P_buf, _b, c_size_t(len(_b)))
            if not res:
                raise ValueError('point could not be parsed by the secp256k1 library')
            plist.append(P_buf)
        if not plist:
            raise ValueError('empty list')

        num = len(plist)
        result_buf = create_string_buffer(64)
        publist = (c_void_p*num)(*(cast(x, c_void_p) for x in plist))
        res = seclib.secp256k1_ec_pubkey_combine(ctx, result_buf, publist, num)
        if res != 1:
            raise ResultAtInfinity

        serpoint = create_string_buffer(65)
        sersize = c_size_t(65)
        res = seclib.secp256k1_ec_pubkey_serialize(ctx, serpoint, byref(sersize), result_buf, secp256k1.SECP256K1_EC_UNCOMPRESSED)
        assert res == 1
        assert sersize.value == 65
        return serpoint.raw
    else:
        for pser in points_iterable:
            plist.append(ser_to_point(pser))
        if not plist:
            raise ValueError('empty list')
        Psum = sum(plist[1:], plist[0])
        if Psum == ecdsa.ellipticcurve.INFINITY:
            raise ResultAtInfinity
        return point_to_ser(Psum, comp=False)