예제 #1
0
def _pubkey_recovery(ec: Curve, c: int, sig: ECDS) -> Sequence[Point]:
    """Private function provided for testing purposes only."""
    # ECDSA public key recovery operation according to SEC 1
    # http://www.secg.org/sec1-v2.pdf
    # See SEC 1 v.2 section 4.1.6

    r, s = _to_sig(ec, sig)

    # precomputations
    r1 = mod_inv(r, ec.n)
    r1s = r1 * s
    r1e = -r1 * c
    keys: Sequence[Point] = list()
    for j in range(ec.h):  # 1
        x = r + j * ec.n  # 1.1
        try:  #TODO: check test reporting 1, 2, 3, or 4 keys
            x %= ec._p
            R = x, ec.y_odd(x, 1)  # 1.2, 1.3, and 1.4
            # skip 1.5: in this function, c is an input
            Q = double_mult(ec, r1s, R, r1e, ec.G)  # 1.6.1
            if Q[1] != 0 and _verhlp(ec, c, Q, sig):  # 1.6.2
                keys.append(Q)
            R = ec.opposite(R)  # 1.6.3
            Q = double_mult(ec, r1s, R, r1e, ec.G)
            if Q[1] != 0 and _verhlp(ec, c, Q, sig):  # 1.6.2
                keys.append(Q)  # 1.6.2
        except Exception:  # R is not a curve point
            pass
    return keys
예제 #2
0
def point_from_octets(ec: Curve, o: octets) -> Point:
    """Return a tuple (Px, Py) that belongs to the curve

       SEC 1 v.2, section 2.3.4
    """
    if isinstance(o, str):
        o = bytes.fromhex(o)

    bsize = len(o)  # bytes
    if bsize == 1 and o[0] == 0x00:  # infinity point
        return Point()

    if bsize == ec.psize + 1:  # compressed point
        if o[0] not in (0x02, 0x03):
            m = f"{ec.psize+1} bytes, but not a compressed point"
            raise ValueError(m)
        Px = int.from_bytes(o[1:], 'big')
        try:
            Py = ec.y_odd(Px, o[0] % 2)  # also check Px validity
            return Point(Px, Py)
        except:
            raise ValueError("point not on curve")
    else:  # uncompressed point
        if bsize != 2 * ec.psize + 1:
            m = f"wrong byte-size ({bsize}) for a point: it "
            m += f"should have be {ec.psize+1} or {2*ec.psize+1}"
            raise ValueError(m)
        if o[0] != 0x04:
            raise ValueError("not an uncompressed point")
        Px = int.from_bytes(o[1:ec.psize + 1], 'big')
        P = Point(Px, int.from_bytes(o[ec.psize + 1:], 'big'))
        if ec.is_on_curve(P):
            return P
        else:
            raise ValueError("point not on curve")
예제 #3
0
def second_generator(ec: Curve, hf) -> Point:
    """Nothing-Up-My-Sleeve (NUMS) second generator H wrt ec.G 

       source: https://github.com/ElementsProject/secp256k1-zkp/blob/secp256k1-zkp/src/modules/rangeproof/main_impl.h
       idea: https://crypto.stackexchange.com/questions/25581/second-generator-for-secp256k1-curve
       Get the hash of G, then coerce it to a point (hx, hy).
       The resulting point could not be a curvepoint: in this case keep on
       incrementing hx until a valid curve point (hx, hy) is obtained.
    """
    G_bytes = octets_from_point(ec, ec.G, False)
    hd = hf(G_bytes).digest()
    hx = int_from_bits(ec, hd)
    isCurvePoint = False
    while not isCurvePoint:
        try:
            hy = ec.y_odd(hx, False)
            isCurvePoint = True
        except:
            hx += 1
    return Point(hx, hy)