Beispiel #1
0
 def test_ell(P):
     Puc = deserialize(serialize(P, False))
     Pc = deserialize(serialize(P, True))
     assert point_eq(P, Puc), "%s\n%s\n%d %d" % (str(P), str(Puc), sgn0(
         P[1]), sgn0(Puc[1]))
     assert point_eq(
         P,
         Pc), "%s\n%s\n%d %d" % (str(P), str(Pc), sgn0(P[1]), sgn0(Pc[1]))
Beispiel #2
0
def _serialize_ell2(P, compressed):
    if not isinstance(P[0], Fq2):
        raise SerError("cannot serialize a point not on E2")
    if len(P) != 3:
        raise SerError("can only serialize Jacobian points")

    first_tag = 0xe0 if compressed else 0x60

    # handle point at infinity
    if P[2] == 0:
        return first_tag.to_bytes(
            1, "big") + b'\x00' * 47 + b'\xc0' + b'\x00' * (47 if compressed
                                                            else 143)

    (x, y) = from_jacobian(P)
    if pow(y, 2) != _gx2(x):
        raise SerError("cannot serialize invalid point")

    x_str = _to_bytes_F2(x)
    x_str[0] = x_str[0] | first_tag
    if not compressed:
        x_str[48] = x_str[48] | 0x80
        return struct.pack("=" + "B" * 192, *(x_str + _to_bytes_F2(y)))

    y_neg = sgn0(y) < 0
    tag_bits = 0xa0 if y_neg else 0x80
    x_str[48] = x_str[48] | tag_bits
    return struct.pack("=" + "B" * 96, *x_str)
Beispiel #3
0
def _deserialize_ell2(data, tag):
    assert len(data) > 48
    (tag2, data[48]) = (data[48] >> 5, data[48] & 0x1f)
    if tag2 not in (4, 5, 6):
        raise DeserError("invalid tag2 for Ell2 point: %d" % tag2)

    if tag2 == 6:
        # point at infinity
        expected_len = 192 if tag == 3 else 96
        if len(data) != expected_len:
            raise DeserError(
                "invalid point at infinity: length must be %d, got %d" %
                (expected_len, len(data)))
        if any(d != 0 for d in data):
            raise DeserError(
                "invalid: point at infinity must be all 0s other than tags")
        return (F2_zero, F2_one, F2_zero)

    if tag == 3:
        # uncompressed point on G2
        if len(data) != 192:
            raise DeserError(
                "invalid uncompressed point: length must be 192, got %d" %
                len(data))
        if tag2 == 5:
            raise DeserError("invalid uncompressed point: tag2 cannot be 5")
        x = _from_bytes_F2(data[:96])
        y = _from_bytes_F2(data[96:])

        if pow(y, 2) != _gx2(x):
            raise DeserError("invalid uncompressed point: not on curve")
        return (x, y, F2_one)

    if tag == 7:
        # compressed point on G2
        if len(data) != 96:
            raise DeserError(
                "invalid compressed point: length must be 96, got %d" %
                len(data))
        x = _from_bytes_F2(data)

        # recompute y
        gx = _gx2(x)
        y = sqrt_F2(gx)
        if y is None:
            raise DeserError("invalid compresesd point: g(x) is nonsquare")

        # fix sign of y
        y_neg = -1 if tag2 == 5 else 1
        y = y_neg * sgn0(y) * y

        return (x, y, F2_one)

    raise DeserError("invalid tag/tag2 for Ell2 point: %d/%d" % (tag, tag2))
Beispiel #4
0
def _deserialize_help(sp, from_bytes, clen, g, sqrt_fn, zero, one):
    data = list(struct.unpack("=" + "B" * len(sp), sp))
    (tag, data[0]) = (data[0] >> 5, data[0] & 0x1f)
    if tag in (0b001, 0b011, 0b111):
        raise DeserError("cannot deserialize value with invalid tag: %d" % tag)

    if tag == 0b000:
        # uncompressed point
        if len(data) != 2 * clen:
            raise DeserError(
                "invalid uncompresed point: length must be %d, got %d" %
                (2 * clen, len(data)))
        x = from_bytes(data[:clen])
        y = from_bytes(data[clen:])

        if pow(y, 2) != g(x):
            raise DeserError("invalid uncompressed point: not on curve")
        return (x, y, one)

    if tag in (0b010, 0b110):
        # point at infinity
        expected_len = 2 * clen if tag == 0b010 else clen
        if len(data) != expected_len:
            raise DeserError(
                "invalid point at infinity: length must be %d, got %d" %
                (expected_len, len(data)))
        if any(d != 0 for d in data):
            raise DeserError(
                "invalid point at infinity: must be all 0s other than tag")
        return (zero, one, zero)

    if tag in (0b100, 0b101):
        # compressed point
        if len(data) != clen:
            raise DeserError(
                "invalid compressed point: length must be %d, got %d" %
                (clen, len(data)))
        x = from_bytes(data)

        # recompute y
        gx = g(x)
        y = sqrt_fn(gx)
        if y is None or pow(y, 2) != gx:
            raise DeserError("invalid compressed point: g(x) is nonsquare")

        # fix sign of y
        y_neg = -1 if tag == 0b101 else 1
        y = y_neg * sgn0(y) * y
        return (x, y, one)

    raise DeserError("invalid tag %d" % tag)
Beispiel #5
0
def osswu_help(t):
    assert isinstance(t, Fq)

    # first, compute X0(t), detecting and handling exceptional case
    num_den_common = xi_1**2 * t**4 + xi_1 * t**2
    x0_num = EllP_b * (num_den_common + 1)
    x0_den = -EllP_a * num_den_common
    x0_den = EllP_a * xi_1 if x0_den == 0 else x0_den

    # g(X0(t))
    gx0_den = pow(x0_den, 3)
    gx0_num = EllP_b * gx0_den
    gx0_num += EllP_a * x0_num * pow(x0_den, 2)
    gx0_num += pow(x0_num, 3)

    # try taking sqrt of g(X0(t))
    # this uses the trick for combining division and sqrt from Section 5 of
    # Bernstein, Duif, Lange, Schwabe, and Yang, "High-speed high-security signatures."
    # J Crypt Eng 2(2):77--89, Sept. 2012. http://ed25519.cr.yp.to/ed25519-20110926.pdf
    tmp1 = gx0_num * gx0_den  # u v
    tmp2 = tmp1 * pow(gx0_den, 2)  # u v^3
    sqrt_candidate = tmp1 * pow(tmp2, (p - 3) // 4)

    # did we find it?
    if sqrt_candidate**2 * gx0_den == gx0_num:
        # found sqrt(g(X0(t))). Force sign of y to equal sign of t
        (x_num, y) = (x0_num, sqrt_candidate)

    else:
        x1_num = xi_1 * t**2 * x0_num
        y1 = sqrt_candidate * t**3 * sqrt_mxi_1_cubed
        (x_num, y) = (x1_num, y1)

    # set sign of y equal to sign of t
    y = sgn0(y) * sgn0(t) * y
    assert sgn0(y) == sgn0(t)
    return (x_num * x0_den, y * pow(x0_den, 3), x0_den)
Beispiel #6
0
def osswu2_help(t):
    assert isinstance(t, Fq2)

    # first, compute X0(t), detecting and handling exceptional case
    num_den_common = xi_2**2 * t**4 + xi_2 * t**2
    x0_num = Ell2p_b * (num_den_common + 1)
    x0_den = -Ell2p_a * num_den_common
    x0_den = Ell2p_a * xi_2 if x0_den == 0 else x0_den

    # compute num and den of g(X0(t))
    gx0_den = pow(x0_den, 3)
    gx0_num = Ell2p_b * gx0_den
    gx0_num += Ell2p_a * x0_num * pow(x0_den, 2)
    gx0_num += pow(x0_num, 3)

    # try taking sqrt of g(X0(t))
    # this uses the trick for combining division and sqrt from Section 5 of
    # Bernstein, Duif, Lange, Schwabe, and Yang, "High-speed high-security signatures."
    # J Crypt Eng 2(2):77--89, Sept. 2012. http://ed25519.cr.yp.to/ed25519-20110926.pdf
    tmp1 = pow(gx0_den, 7)  # v^7
    tmp2 = gx0_num * tmp1  # u v^7
    tmp1 = tmp1 * tmp2 * gx0_den  # u v^15
    sqrt_candidate = tmp2 * pow(tmp1, (p**2 - 9) // 16)

    # check if g(X0(t)) is square and return the sqrt if so
    for root in roots_of_unity:
        y0 = sqrt_candidate * root
        if y0**2 * gx0_den == gx0_num:
            # found sqrt(g(X0(t))). force sign of y to equal sign of t
            y0 = sgn0(y0) * sgn0(t) * y0
            assert sgn0(y0) == sgn0(t)
            return (x0_num * x0_den, y0 * pow(x0_den, 3), x0_den)

    # if we've gotten here, then g(X0(t)) is not square. convert srqt_candidate to sqrt(g(X1(t)))
    (x1_num, x1_den) = (xi_2 * t**2 * x0_num, x0_den)
    (gx1_num, gx1_den) = (xi_2**3 * t**6 * gx0_num, gx0_den)
    sqrt_candidate *= t**3
    for eta in etas:
        y1 = eta * sqrt_candidate
        if y1**2 * gx1_den == gx1_num:
            # found sqrt(g(X1(t))). force sign of y to equal sign of t
            y1 = sgn0(y1) * sgn0(t) * y1
            assert sgn0(y1) == sgn0(t)
            return (x1_num * x1_den, y1 * pow(x1_den, 3), x1_den)

    # if we got here, something is wrong
    raise RuntimeError("osswu2_help failed for unknown reasons")
Beispiel #7
0
def _deserialize_ell1(data, tag):
    if tag == 0:
        # uncompressed point
        if len(data) != 96:
            raise DeserError(
                "invalid uncompressed point: length must be 96, got %d" %
                len(data))
        x = _from_bytes_F1(data[:48])
        y = _from_bytes_F1(data[48:])
        if pow(y, 2) != _gx1(x):
            raise DeserError("invalid uncompressed point: not on curve")
        return (x, y, F1_one)

    if tag in (2, 6):
        # point at infinity
        expected_len = 96 if tag == 2 else 48
        if len(data) != expected_len:
            raise DeserError(
                "invalid point at infinity: length must be %d, got %d" %
                (expected_len, len(data)))
        if any(d != 0 for d in data):
            raise DeserError(
                "invalid: point at infinity must be all 0s other than tag")
        return (F1_zero, F1_one, F1_zero)

    if tag in (4, 5):
        # compressed point not at infinity
        if len(data) != 48:
            raise DeserError(
                "invalid compressed point: length must be 48, got %d" %
                len(data))
        x = _from_bytes_F1(data)

        # recompute y
        gx = _gx1(x)
        y = pow(gx, (p + 1) // 4)
        if pow(y, 2) != gx:
            raise DeserError("invalid compressed point: g(x) is nonsquare")

        # fix sign of y
        y_neg = -1 if tag == 5 else 1
        y = y_neg * sgn0(y) * y

        return (x, y, F1_one)

    raise DeserError("invalid tag for Ell1 point: %d" % tag)
Beispiel #8
0
def _serialize_help(P, compressed, to_bytes, clen, g):
    # point at infinity
    if P[2] == 0:
        if compressed:
            return b'\xc0' + b'\x00' * (clen - 1)
        return b'\x40' + b'\x00' * (2 * clen - 1)

    (x, y) = from_jacobian(P)
    if pow(y, 2) != g(x):
        raise SerError("cannot serialize invalid point")

    x_str = to_bytes(x)
    if not compressed:
        return struct.pack("=" + "B" * 2 * clen, *(x_str + to_bytes(y)))

    y_neg = sgn0(y) < 0
    tag_bits = 0xa0 if y_neg else 0x80
    x_str[0] = x_str[0] | tag_bits
    return struct.pack("=" + "B" * clen, *x_str)
Beispiel #9
0
def _serialize_ell1(P, compressed):
    if not isinstance(P[0], Fq):
        raise SerError("cannot serialize a point not on E1")
    if len(P) != 3:
        raise SerError("can only serialize Jacobian points")

    # handle point at infinity
    if P[2] == 0:
        if compressed:
            return b'\xc0' + b'\x00' * 47
        return b'\x40' + b'\x00' * 95

    (x, y) = from_jacobian(P)
    if pow(y, 2) != _gx1(x):
        raise SerError("cannot serialize invalid point")

    x_str = _to_bytes_F1(x)
    if not compressed:
        return struct.pack("=" + "B" * 96, *(x_str + _to_bytes_F1(y)))

    y_neg = sgn0(y) < 0
    tag_bits = 0xa0 if y_neg else 0x80
    x_str[0] = x_str[0] | tag_bits
    return struct.pack("=" + "B" * 48, *x_str)