Beispiel #1
0
def random_matrix_determinant(secfld, d):
    d_2 = d * (d - 1) // 2
    L = np.diagflat([secfld(1)] * d)
    L[np.tril_indices(d, -1)] = mpc._randoms(secfld, d_2)
    L[np.triu_indices(d, 1)] = [secfld(0)] * d_2
    diag = mpc._randoms(secfld, d)
    U = np.diagflat(diag)
    U[np.tril_indices(d, -1)] = [secfld(0)] * d_2
    U[np.triu_indices(d, 1)] = mpc._randoms(secfld, d_2)
    R = mpc.matrix_prod(L.tolist(), U.tolist())
    detR = mpc.prod(diag)  # detR != 0 with overwhelming probability
    return R, detR
Beispiel #2
0
async def vector_bsgn_1(x):
    """Compute bsgn_1(a) for all elements a of x in parallel."""
    stype = type(x[0])
    n = len(x)
    await mpc.returnType(stype, n)
    Zp = stype.field
    p = Zp.modulus
    legendre_p = lambda a: gmpy2.legendre(a.value, p)

    s = mpc.random_bits(Zp, 3 * n, signed=True)  # 3n random signs
    r = mpc._randoms(Zp, 3 * n)
    r = mpc.schur_prod(r, r)  # 3n random squares modulo p
    x, s, r = await mpc.gather(x, s, r)
    y = [b + 2 * i for b in (2 * a + 1 for a in x) for i in (-1, 0, 1)]
    y.extend(s[:n])
    s.extend(s[n:2 * n])
    r.extend(s[-n:])
    y = await mpc.schur_prod(y, s)
    y = await mpc.schur_prod(y, r)
    y = await mpc.output(y)
    h = [legendre_p(y[j]) for j in range(3 * n)]
    t = [s[j] * h[j] for j in range(3 * n)]
    z = [
        h[3 * j] * h[3 * j + 1] * h[3 * j + 2] * y[3 * n + j] for j in range(n)
    ]
    q = (p + 1) >> 1  # q = 1/2 mod p
    return [
        Zp((u.value + v.value + w.value - uvw.value) * q)
        for u, v, w, uvw in zip(*[iter(t)] * 3, z)
    ]
Beispiel #3
0
async def bsgn_1(a):
    """Compute binary sign of a securely.

    Binary sign of a (1 if a>=0 else -1) is obtained by securely computing
    (u+v+w - u*v*w)/2 with u=(2a-1 | p), v=(2a+1 | p), and w=(2a+3 | p).
    """
    stype = type(a)
    await mpc.returnType(stype)
    Zp = stype.field
    p = Zp.modulus
    legendre_p = lambda a: gmpy2.legendre(a.value, p)

    s = mpc.random_bits(Zp, 3, signed=True)  # 3 random signs
    r = mpc._randoms(Zp, 3)
    r = mpc.schur_prod(r, r)  # 3 random squares modulo p
    a, s, r = await mpc.gather(a, s, r)
    y = [b + 2 * i for b in (2 * a + 1, ) for i in (-1, 0, 1)]
    y.append(s[0])
    s.append(s[1])
    r.append(s[2])
    y = await mpc.schur_prod(y, s)
    y = await mpc.schur_prod(y, r)
    y = await mpc.output(y)
    h = [legendre_p(y[i]) for i in range(3)]
    u, v, w = [s[i] * h[i] for i in range(3)]
    uvw = h[0] * h[1] * h[2] * y[3]
    return (u + v + w - uvw) / 2
Beispiel #4
0
async def vector_bsgn_0(x):
    """Compute bsgn_0(a) for all elements a of x in parallel."""
    stype = type(x[0])
    n = len(x)
    await mpc.returnType(stype, n)
    Zp = stype.field
    p = Zp.modulus
    legendre_p = lambda a: gmpy2.legendre(a.value, p)

    s = mpc.random_bits(Zp, n, signed=True)  # n random signs
    r = mpc._randoms(Zp, n)
    r = mpc.schur_prod(r, r)  # n random squares modulo p
    x, s, r = await mpc.gather(x, s, r)
    y = [2 * a + 1 for a in x]
    y = await mpc.schur_prod(y, s)
    y = await mpc.schur_prod(y, r)
    y = await mpc.output(y)
    return [s[j] * legendre_p(y[j]) for j in range(n)]
Beispiel #5
0
async def vector_sge(x):
    """Compute binary signs securely for all elements of x in parallel.

    Vectorized version of MPyC's built-in secure comparison.
    Cf. mpc.sgn() with GE=True (and EQ=False).

    NB: mpc.prod() and mpc.is_zero_public() are not (yet) vectorized.
    """
    stype = type(x[0])
    n = len(x)
    await mpc.returnType(stype, n)
    Zp = stype.field
    l = stype.bit_length
    k = mpc.options.sec_param

    r_bits = await mpc.random_bits(Zp, (l + 1) * n)
    r_bits = [b.value for b in r_bits]
    r_modl = [0] * n
    for j in range(n):
        for i in range(l - 1, -1, -1):
            r_modl[j] <<= 1
            r_modl[j] += r_bits[l * j + i]
    r_divl = mpc._randoms(Zp, n, 1 << k)
    x = await mpc.gather(x)
    x_r = [a + ((1 << l) + b) for a, b in zip(x, r_modl)]
    c = await mpc.output([a + (b.value << l) for a, b in zip(x_r, r_divl)])

    c = [c.value % (1 << l) for c in c]
    e = [[None] * (l + 1) for _ in range(n)]
    for j in range(n):
        s_sign = (r_bits[l * n + j] << 1) - 1
        sumXors = 0
        for i in range(l - 1, -1, -1):
            c_i = (c[j] >> i) & 1
            e[j][i] = Zp(s_sign + r_bits[l * j + i] - c_i + 3 * sumXors)
            sumXors += 1 - r_bits[l * j + i] if c_i else r_bits[l * j + i]
        e[j][l] = Zp(s_sign - 1 + 3 * sumXors)
    e = await mpc.gather([mpc.prod(_) for _ in e])
    g = await mpc.gather([mpc.is_zero_public(stype(_)) for _ in e])
    UF = [1 - b if g else b for b, g in zip(r_bits[-n:], g)]
    z = [(a - (c + (b << l))) / (1 << l - 1) - 1
         for a, b, c in zip(x_r, UF, c)]
    return z
Beispiel #6
0
async def vector_bsgn_2(x):
    """Compute bsgn_2(a) for all elements a of x in parallel."""
    stype = type(x[0])
    n = len(x)
    await mpc.returnType(stype, n)
    Zp = stype.field
    p = Zp.modulus
    legendre_p = lambda a: gmpy2.legendre(a.value, p)

    s = mpc.random_bits(Zp, 6*n, signed=True)  # 6n random signs
    r = mpc._randoms(Zp, 6*n)
    r = mpc.schur_prod(r, r)  # 6n random squares modulo p
    x, s, r = await mpc.gather(x, s, r)
    y = [b + 2 * i for b in (2 * a + 1 for a in x) for i in (-2, -1, 0, 1, 2)]
    y = await mpc.schur_prod(y, s[:-n])
    y.extend(s[-n:])
    y = await mpc.schur_prod(y, r)
    y = await mpc.output(y)
    t = [sum(s[5*j + i] * legendre_p(y[5*j + i]) for i in range(5)) for j in range(n)]
    t = await mpc.output(await mpc.schur_prod(t, y[-n:]))
    return [c * legendre_p(d) for c, d in zip(s[-n:], t)]
Beispiel #7
0
async def bsgn_2(a):
    """Compute binary sign of a securely.

    Binary sign of a (1 if a>=0 else -1) is obtained by securely computing
    (t | p), with t = sum((2a+1+2i | p) for i=-2,-1,0,1,2).
    """
    stype = type(a)
    await mpc.returnType(stype)
    Zp = stype.field
    p = Zp.modulus
    legendre_p = lambda a: gmpy2.legendre(a.value, p)

    s = mpc.random_bits(Zp, 6, signed=True)  # 6 random signs
    r = mpc._randoms(Zp, 6)
    r = mpc.schur_prod(r, r)  # 6 random squares modulo p
    a, s, r = await mpc.gather(a, s, r)
    y = [b + 2 * i for b in (2 * a + 1, ) for i in (-2, -1, 0, 1, 2)]
    y = await mpc.schur_prod(y, s[:-1])
    y.append(s[-1])
    y = await mpc.schur_prod(y, r)
    y = await mpc.output(y)
    t = sum(s[i] * legendre_p(y[i]) for i in range(5))
    t = await mpc.output(t * y[-1])
    return s[-1] * legendre_p(t)