Пример #1
0
 def test_bsecfld(self):
     secfld = mpc.SecFld(char=2, min_order=2**8)
     a = secfld(57)
     b = secfld(67)
     self.assertEqual(int(mpc.run(mpc.output(mpc.input(a, 0)))), 57)
     self.assertEqual(int(mpc.run(mpc.output(+a - -a))), 0)
     self.assertEqual(int(mpc.run(mpc.output(a * b))), 137)
     self.assertEqual(int(mpc.run(mpc.output(a * b / a))), 67)
     self.assertEqual(int(mpc.run(mpc.output(a**254 * a))), 1)
     self.assertEqual(int(mpc.run(mpc.output(a & b))), 1)
     self.assertEqual(int(mpc.run(mpc.output(a | b))), 123)
     self.assertEqual(int(mpc.run(mpc.output(a ^ b))), 122)
     self.assertEqual(int(mpc.run(mpc.output(~a))), 198)
     c = mpc.run(mpc.output(mpc.to_bits(secfld(0))))
     self.assertEqual(c, [0, 0, 0, 0, 0, 0, 0, 0])
     c = mpc.run(mpc.output(mpc.to_bits(secfld(1))))
     self.assertEqual(c, [1, 0, 0, 0, 0, 0, 0, 0])
     c = mpc.run(mpc.output(mpc.to_bits(secfld(255))))
     self.assertEqual(c, [1, 1, 1, 1, 1, 1, 1, 1])
     c = mpc.run(mpc.output(mpc.to_bits(secfld(255), 1)))
     self.assertEqual(c, [1])
     c = mpc.run(mpc.output(mpc.to_bits(secfld(255), 4)))
     self.assertEqual(c, [1, 1, 1, 1])
     self.assertEqual(mpc.run(mpc.output(mpc.matrix_sub([[a]], [[a]])[0])),
                      [0])
     self.assertEqual(
         mpc.run(mpc.output(mpc.matrix_prod([c], [[a] * 4], True)[0])), [0])
     self.assertEqual(
         mpc.run(mpc.output(mpc.matrix_prod([[a] * 4], [c], True)[0])), [0])
Пример #2
0
def sbox(x):
    """AES S-Box."""
    y = mpc.to_bits(x**254)
    z = mpc.matrix_prod([y], A, True)[0]
    w = mpc.vector_add(z, B)
    v = mpc.from_bits(w)
    return v
Пример #3
0
def sbox1(v):
    """AES inverse S-Box."""
    w = mpc.to_bits(v)
    z = mpc.vector_add(w, B)
    y = mpc.matrix_prod([z], A1, True)[0]
    x = mpc.from_bits(y)**254
    return x
Пример #4
0
async def linear_solve(A, B):
    secfld = type(A[0][0])
    d, e = len(A), len(B[0])
    await mpc.returnType(secfld, d * e + 1)

    R, detR = random_matrix_determinant(secfld, d)
    RA = mpc.matrix_prod(R, A)
    RA = await mpc.output([a for row in RA for a in row])
    RA = np.reshape(RA, (d, d))
    RB = mpc.matrix_prod(R, B)
    RB = await mpc.gather(RB)  # NB: RB is secret-shared

    invA_B, detRA = bareiss(secfld.field, np.concatenate((RA, RB), axis=1))
    detA = detRA / detR
    adjA_B = [secfld(a) * detA for row in invA_B for a in row]
    return adjA_B + [detA]
Пример #5
0
async def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-k',
                        '--order',
                        type=int,
                        metavar='K',
                        help='order K of hash chain, length n=2**K')
    parser.add_argument('--recursive',
                        action='store_true',
                        help='use recursive pebbler')
    parser.add_argument('--no-one-way',
                        action='store_true',
                        default=False,
                        help='use dummy one-way function')
    parser.add_argument('--no-random-seed',
                        action='store_true',
                        default=False,
                        help='use fixed seed')
    parser.set_defaults(order=1)
    args = parser.parse_args()

    await mpc.start()

    if args.recursive:
        Pebbler = P
    else:
        Pebbler = p

    IV = [[aes.secfld(3)] * 4] * 4  # IV as 4x4 array of GF(256) elements
    global f
    if args.no_one_way:
        D = aes.circulant_matrix([3, 0, 0, 0])
        f = lambda x: mpc.matrix_prod(D, x)
    else:
        K = aes.key_expansion(IV)
        f = lambda x: mpc.matrix_add(aes.encrypt(K, x), x)

    if args.no_random_seed:
        x0 = IV
    else:
        x0 = [[mpc.random.getrandbits(aes.secfld, 8) for _ in range(4)]
              for _ in range(4)]

    k = args.order
    print(f'Hash chain of length {2**k}:')
    r = 1
    for v in Pebbler(k, x0):
        if v is None:  # initial stage
            print(f'{r:4}', '-')
            await mpc.throttler(0.1
                                )  # raise barrier roughly every 10 AES calls
        else:  # output stage
            await aes.xprint(f'{r:4} x{2**(k+1) - 1 - r:<4} =', v)
        r += 1

    await mpc.shutdown()
Пример #6
0
def decrypt(K, s):
    """AES decryption of s given key schedule K."""
    Nr = len(K) - 1  # Nr is 10 or 14
    for i in range(Nr, 0, -1):
        s = mpc.matrix_add(s, K[i])
        if i < Nr:
            s = mpc.matrix_prod(C1, s)
        s = [s[j][-j:] + s[j][:-j] for j in range(4)]
        s = [[sbox1(x) for x in _] for _ in s]
    s = mpc.matrix_add(s, K[0])
    return s
Пример #7
0
def encrypt(K, s):
    """AES encryption of s given key schedule K."""
    Nr = len(K) - 1  # Nr is 10 or 14
    s = mpc.matrix_add(s, K[0])
    for i in range(1, Nr + 1):
        s = [[sbox(x) for x in _] for _ in s]
        s = [s[j][j:] + s[j][:j] for j in range(4)]
        if i < Nr:
            s = mpc.matrix_prod(C, s)
        s = mpc.matrix_add(s, K[i])
    return s
Пример #8
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
Пример #9
0
async def schmidt_multilateration(locations, toas):
    """Schmidt's multilateration algorithm."""
    # Transform sensor locations and ToA measurements
    # into linear system A w = b, using Schmidt's method:
    norm = [mpc.in_prod(p, p) for p in locations]
    A, b = [], []
    for i, j, k in itertools.combinations(range(len(locations)), 3):
        Delta = [toas[j] - toas[k], toas[k] - toas[i], toas[i] - toas[j]]
        XYZN = [
            locations[i] + [norm[i]], locations[j] + [norm[j]],
            locations[k] + [norm[k]]
        ]
        r_x, r_y, r_z, r_n = mpc.matrix_prod([Delta], XYZN)[0]
        A.append([2 * r_x, 2 * r_y, 2 * r_z])
        b.append(mpc.prod(Delta) + r_n)

    # Compute least-squares solution w satisfying A^T A w = A^T b:
    AT, bT = list(map(list, zip(*A))), [b]  # transpose of A and b
    ATA = mpc.matrix_prod(AT, AT, tr=True)  # A^T (A^T)^T = A^T A
    ATb = mpc.matrix_prod(AT, bT, tr=True)  # A^T (b^T)^T = A^T b
    w_det = linear_solve(ATA, ATb)
    x, y, z, det = await mpc.output(w_det)
    w = x / det, y / det, z / det
    return w
Пример #10
0
async def id3(T, R) -> asyncio.Future:
    sizes = [mpc.in_prod(T, v) for v in S[C]]
    i, mx = mpc.argmax(sizes)
    sizeT = mpc.sum(sizes)
    stop = (sizeT <= int(args.epsilon * len(T))) + (mx == sizeT)
    if not (R and await mpc.is_zero_public(stop)):
        i = await mpc.output(i)
        logging.info(f'Leaf node label {i}')
        tree = i
    else:
        T_R = [[mpc.schur_prod(T, v) for v in S[A]] for A in R]
        gains = [GI(mpc.matrix_prod(T_A, S[C], True)) for T_A in T_R]
        k = await mpc.output(mpc.argmax(gains, key=SecureFraction)[0])
        T_Rk = T_R[k]
        del T_R, gains  # release memory
        A = list(R)[k]
        logging.info(f'Attribute node {A}')
        if args.parallel_subtrees:
            subtrees = await mpc.gather(
                [id3(Tj, R.difference([A])) for Tj in T_Rk])
        else:
            subtrees = [await id3(Tj, R.difference([A])) for Tj in T_Rk]
        tree = A, subtrees
    return tree
Пример #11
0
async def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '-i',
        '--dataset',
        type=int,
        metavar='I',
        help=('dataset 0=uvlp (default), 1=wiki, 2=tb2x2, 3=woody, '
              '4=LPExample_R20, 5=sc50b, 6=kb2, 7=LPExample'))
    parser.add_argument('-l',
                        '--bit-length',
                        type=int,
                        metavar='L',
                        help='override preset bit length for dataset')
    parser.set_defaults(dataset=0, bit_length=0)
    args = parser.parse_args()

    settings = [('uvlp', 24, 37 / 3), ('wiki', 24, 20), ('tb2x2', 18, 10.5),
                ('woody', 36, 540), ('LPExample_R20', 52, 3.441176),
                ('sc50b', 52, 70), ('kb2', 96, 1749.9204734889486),
                ('LPExample', 96, 1188806595)]
    name, bit_length, exact_max = settings[args.dataset]
    if args.bit_length:
        bit_length = args.bit_length

    with open(os.path.join('data', 'lp', name + '.csv')) as file:
        T = list(csv.reader(file))
    m = len(T) - 1
    n = len(T[0]) - 1
    secfxp = mpc.SecFxp(bit_length)
    print(
        f'Using secure {bit_length}-bit fixed-point numbers: {secfxp.__name__}'
    )
    print(f'dataset: {name} with {m} constraints and {n} variables')
    T[0][-1] = '0'  # initialize optimal value
    for i in range(m + 1):
        for j in range(n + 1):
            T[i][j] = secfxp(float(T[i][j]), integral=False)

    c = T[0][:-1]  # maximize c.x subject to A.x <= b, x >= 0
    A = [T[i + 1][:-1] for i in range(m)]
    b = [T[i + 1][-1] for i in range(m)]

    await mpc.start()

    cobasis = [secfxp(j) for j in range(n)]
    basis = [secfxp(n + i) for i in range(m)]

    iteration = 0
    while True:
        # find index of pivot column
        p_col_index, minimum = argmin_int(T[0][:-1])

        if await mpc.output(minimum >= 0):
            break  # maximum reached

        # find index of pivot row
        p_col = mpc.matrix_prod([p_col_index], T, True)[0]
        constraints = [[T[i][-1], p_col[i], p_col[i] > 0.0001]
                       for i in range(1, m + 1)]
        p_row_index, (_, pivot, _) = argmin_rat(constraints)

        # reveal progress a bit
        iteration += 1
        mx = await mpc.output(T[0][-1])
        p = await mpc.output(pivot)
        logging.info(f'Iteration {iteration}: {mx} pivot={p}')

        # swap basis entries
        delta = mpc.in_prod(basis, p_row_index) - mpc.in_prod(
            cobasis, p_col_index)
        cobasis = mpc.vector_add(cobasis, mpc.scalar_mul(delta, p_col_index))
        basis = mpc.vector_sub(basis, mpc.scalar_mul(delta, p_row_index))

        # update tableau Tij = Tij - (Til - bool(i==k))/Tkl * (Tkj + bool(j==l))
        p_col_index.append(secfxp(0))
        p_row_index.insert(0, secfxp(0))
        p_col = mpc.vector_sub(p_col, p_row_index)
        p_col = mpc.scalar_mul(1 / pivot, p_col)
        p_row = mpc.matrix_prod([p_row_index], T)[0]
        p_row = mpc.vector_add(p_row, p_col_index)
        T = mpc.gauss(T, secfxp(1), p_col, p_row)

    mx = await mpc.output(T[0][-1])
    rel_error = (mx - exact_max) / exact_max
    print(f'max = {mx} (error {rel_error:.3%}) in {iteration} iterations')

    logging.info('Solution x')
    x = [secfxp(0) for _ in range(n)]
    for i in range(m):
        u = mpc.unit_vector(basis[i], m + n)[:n]
        v = mpc.scalar_mul(T[i + 1][-1], u)
        x = mpc.vector_add(x, v)
    cx = mpc.in_prod(c, x)
    Ax = mpc.matrix_prod([x], A, True)[0]
    approx = lambda a: 1.01 * a + 0.0001
    Ax_bounded_by_b = mpc.all(Ax[i] <= approx(b[i]) for i in range(m))
    x_nonnegative = mpc.all(x[j] >= 0 for j in range(n))

    logging.info('Dual solution y')
    y = [secfxp(0) for _ in range(m)]
    for j in range(n):
        u = mpc.unit_vector(cobasis[j], m + n)[n:]
        v = mpc.scalar_mul(T[0][j], u)
        y = mpc.vector_sub(y, v)
    yb = mpc.in_prod(y, b)
    yA = mpc.matrix_prod([y], A)[0]
    approx = lambda a: mpc.if_else(a < 0, 1 / 1.01, 1.01) * a + 0.0001
    yA_bounded_by_c = mpc.all(yA[j] <= approx(c[j]) for j in range(n))
    y_nonpositive = mpc.all(y[i] <= 0 for i in range(m))

    cx_eq_yb = abs(cx - yb) <= 0.01 * abs(cx)
    check = mpc.all([
        cx_eq_yb, Ax_bounded_by_b, x_nonnegative, yA_bounded_by_c,
        y_nonpositive
    ])
    check = bool(await mpc.output(check))
    print(
        f'verification c.x == y.b, A.x <= b, x >= 0, y.A <= c, y <= 0: {check}'
    )

    x = await mpc.output(x)
    print(f'solution = {x}')

    await mpc.shutdown()
Пример #12
0
def tensormatrix_prod(x, W, b):
    logging.info('- - - - - - - - fc      - - - - - - -')
    W, b = W.tolist(), b.tolist()
    return [mpc.vector_add(mpc.matrix_prod([z.tolist()], W)[0], b) for z in x]
Пример #13
0
async def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--data', help='filename for tableau')
    parser.add_argument('options', nargs='*')
    parser.set_defaults(data='default')
    args = parser.parse_args()

    if not args.options:
        certificate_filename = f'c{mpc.pid}.cert'
        logging.info('Setting certificate file to default = %s',
                     certificate_filename)
    else:
        certificate_filename = args.options[0]
    T = load_tableau(args.data)
    l = mpc.options.bit_length
    m = len(T) - 1
    n = len(T[0]) - 1
    secint = mpc.SecInt(l, n=m + n)
    for i in range(m + 1):
        for j in range(n + 1):
            T[i][j] = secint(T[i][j])

    Zp = secint.field
    N = Zp.nth
    w = Zp.root
    w_powers = [Zp(1)]
    for _ in range(N - 1):
        w_powers.append(w_powers[-1] * w)
    assert w_powers[-1] * w == 1

    basis = [secint(w_powers[-(i + n)]) for i in range(m)]
    cobasis = [secint(w_powers[-j]) for j in range(n)]
    prev_pivot = secint(1)

    await mpc.start()

    iteration = 0
    logging.info('%d Termination?...', iteration)
    p_col_index, minimum = argmin_int(T[-1][:-1])
    while await mpc.output(minimum < 0):
        iteration += 1

        logging.info('%d Determining pivot...', iteration)
        p_col = mpc.matrix_prod([p_col_index], T, True)[0]
        constraints = [(T[i][-1] + (p_col[i] <= 0), p_col[i])
                       for i in range(m)]
        p_row_index, (_, pivot) = argmin_rat(constraints)

        logging.info('%d Updating tableau...', iteration)
        #  T[i,j] = T[i,j]*p/p' - (C[i]/p' - p_row_index[i])*(R[j] + p * p_col_index[j])
        p_row = mpc.matrix_prod([p_row_index], T)[0]
        delta_row = mpc.scalar_mul(prev_pivot, p_col_index)
        delta_row.append(secint(0))
        p_row = mpc.vector_add(p_row, delta_row)
        prev_p_inv = 1 / prev_pivot
        p_col = mpc.scalar_mul(prev_p_inv, p_col)
        p_col = mpc.vector_sub(p_col, p_row_index + [secint(0)])
        T = mpc.gauss(T, pivot * prev_p_inv, p_col, p_row)
        prev_pivot = pivot

        # swap basis entries
        delta = mpc.in_prod(basis, p_row_index) - mpc.in_prod(
            cobasis, p_col_index)
        p_row_index = mpc.scalar_mul(delta, p_row_index)
        basis = mpc.vector_sub(basis, p_row_index)
        p_col_index = mpc.scalar_mul(delta, p_col_index)
        cobasis = mpc.vector_add(cobasis, p_col_index)

        logging.info('%d Termination?...', iteration)
        p_col_index, minimum = argmin_int(T[-1][:-1])

    logging.info('Termination...')
    mx = await mpc.output(T[-1][-1])
    cd = await mpc.output(prev_pivot)
    print(' max(f) = %d / %d = %f' %
          (mx.value, cd.value, float(mx.value) / cd.value))

    logging.info('Computing solution...')
    sum_x_powers = [secint(0) for _ in range(N)]
    for i in range(m):
        x_powers = pow_list(T[i][-1] / N, basis[i], N)
        sum_x_powers = mpc.vector_add(sum_x_powers, x_powers)
    solution = [None] * n
    for j in range(n):
        coefs = [w_powers[(j * k) % N] for k in range(N)]
        solution[j] = mpc.lin_comb(coefs, sum_x_powers)
    solution = await mpc.output(solution)

    logging.info('Computing dual solution...')
    sum_x_powers = [secint(0) for _ in range(N)]
    for j in range(n):
        x_powers = pow_list(T[-1][j] / N, cobasis[j], N)
        sum_x_powers = mpc.vector_add(sum_x_powers, x_powers)
    dual_solution = [None] * m
    for i in range(m):
        coefs = [w_powers[((n + i) * k) % N] for k in range(N)]
        dual_solution[i] = mpc.lin_comb(coefs, sum_x_powers)
    dual_solution = await mpc.output(dual_solution)

    await mpc.shutdown()

    logging.info('Writing output to %s.', certificate_filename)
    with open(os.path.join('data', 'lp', certificate_filename), 'w') as f:
        f.write('# tableau = \n' + args.data + '\n')
        f.write('# bit-length = \n' + str(mpc.options.bit_length) + '\n')
        f.write('# security parameter = \n' + str(mpc.options.sec_param) +
                '\n')
        f.write('# threshold = \n' + str(mpc.threshold) + '\n')
        f.write('# common denominator = \n' + str(cd.value) + '\n')
        f.write('# solution = \n')
        f.write('\t'.join(str(x.value) for x in solution) + '\n')
        f.write('# dual solution = \n')
        f.write('\t'.join(str(x.value) for x in dual_solution) + '\n')
Пример #14
0
    def test_secfxp(self):
        secfxp = mpc.SecFxp()
        c = mpc.to_bits(secfxp(0),
                        0)  # mpc.output() only works for nonempty lists
        self.assertEqual(c, [])
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(0))))
        self.assertEqual(c, [0.0] * 32)
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(1))))
        self.assertEqual(c, [0.0] * 16 + [1.0] + [0.0] * 15)
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(0.5))))
        self.assertEqual(c, [0.0] * 15 + [1.0] + [0.0] * 16)
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(8113))))
        self.assertEqual(c, [0.0] * 16 + [
            float(b) for b in [1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0]
        ])
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(2**15 - 1))))
        self.assertEqual(c, [float(b) for b in [0] * 16 + [1] * 15 + [0]])
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(-1))))
        self.assertEqual(c, [float(b) for b in [0] * 16 + [1] * 16])
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(-2**15))))
        self.assertEqual(c, [float(b) for b in [0] * 31 + [1]])

        for f in [8, 16, 32, 64]:
            secfxp = mpc.SecFxp(2 * f)
            c = mpc.run(mpc.output(secfxp(1) + secfxp(1)))
            self.assertEqual(c.frac_length, f)
            self.assertEqual(c, 2)
            c = mpc.run(mpc.output(secfxp(2**-f) + secfxp(1)))
            if f != 64:  # NB: 1 + 2**-64 == 1 in Python
                self.assertEqual(c, 1 + 2**-f)
            self.assertEqual(mpc.run(mpc.output(secfxp(0.5) * secfxp(2.0))), 1)
            self.assertEqual(mpc.run(mpc.output(secfxp(2.0) * secfxp(0.5))), 1)

            s = [10.7, -3.4, 0.1, -0.11]
            self.assertEqual(mpc.run(mpc.output(list(map(secfxp, s)))), s)

            s = [10.5, -3.25, 0.125, -0.125]
            a, b, c, d = list(map(secfxp, s))
            t = [v * v for v in s]
            self.assertEqual(mpc.run(mpc.output([a * a, b * b, c * c, d * d])),
                             t)
            x = [a, b, c, d]
            self.assertEqual(mpc.run(mpc.output(mpc.schur_prod(x, x))), t)
            self.assertEqual(mpc.run(mpc.output(mpc.schur_prod(x, x[:]))), t)
            t = sum(t)
            self.assertEqual(mpc.run(mpc.output(mpc.in_prod(x, x))), t)
            self.assertEqual(mpc.run(mpc.output(mpc.in_prod(x, x[:]))), t)
            self.assertEqual(
                mpc.run(mpc.output(mpc.matrix_prod([x], [x], True)[0])), [t])
            t = [_ for a, b, c, d in [s] for _ in [a + b, a * b, a - b]]
            self.assertEqual(mpc.run(mpc.output([a + b, a * b, a - b])), t)
            t = [
                _ for a, b, c, d in [s]
                for _ in [(a + b)**2, (a + b)**2 + 3 * c]
            ]
            self.assertEqual(
                mpc.run(mpc.output([(a + b)**2, (a + b)**2 + 3 * c])), t)
            t = [int(_) for a, b, c, d in [s] for _ in [a < b, b < c, c < d]]
            self.assertEqual(mpc.run(mpc.output([a < b, b < c, c < d])), t)
            t = int(s[0] < s[1] and s[1] < s[2])
            self.assertEqual(mpc.run(mpc.output((a < b) & (b < c))), t)
            t = int(s[0] < s[1] or s[1] < s[2])
            self.assertEqual(mpc.run(mpc.output((a < b) | (b < c))), t)
            t = (int(s[0] < s[1]) ^ int(s[1] < s[2]))
            self.assertEqual(mpc.run(mpc.output((a < b) ^ (b < c))), t)
            t = (int(not s[0] < s[1]) ^ int(s[1] < s[2]))
            self.assertEqual(mpc.run(mpc.output(~(a < b) ^ b < c)), t)
            t = [int(s[0] > 1), int(10 * s[1] < 5), int(10 * s[0] == 5)]
            self.assertEqual(
                mpc.run(mpc.output([a > 1, 10 * b < 5, 10 * a == 5])), t)

            s[3] = -0.120
            d = secfxp(s[3])
            t = s[3] / 0.25
            self.assertAlmostEqual(mpc.run(mpc.output(d / 0.25)).signed(),
                                   t,
                                   delta=1)
            t = s[3] / s[2] + s[0]
            self.assertAlmostEqual(mpc.run(mpc.output(d / c + a)).signed(),
                                   t,
                                   delta=1)
            t = round(t * (1 << f))
            self.assertAlmostEqual(mpc.run(mpc.output(d / c + a)), t, delta=1)
            t = ((s[0] + s[1])**2 + 3 * s[2]) / s[2]
            self.assertAlmostEqual(mpc.run(mpc.output(
                ((a + b)**2 + 3 * c) / c)).signed(),
                                   t,
                                   delta=2)
            t = 1 / s[3]
            self.assertAlmostEqual((mpc.run(mpc.output(1 / d))).signed(),
                                   t,
                                   delta=1)
            t = s[2] / s[3]
            self.assertAlmostEqual(mpc.run(mpc.output(c / d)).signed(),
                                   t,
                                   delta=1)
            t = -s[3] / s[2]
            t = round(t * (1 << f))
            self.assertAlmostEqual(mpc.run(mpc.output(-d / c)), t, delta=1)
            t = s[2] / s[3]
            t = round(t * (1 << f))
            self.assertAlmostEqual(mpc.run(mpc.output(d / c)), t, delta=1)

            self.assertEqual(mpc.run(mpc.output(mpc.sgn(+a))), int(s[0] > 0))
            self.assertEqual(mpc.run(mpc.output(mpc.sgn(-a))), -int(s[0] > 0))
            self.assertEqual(mpc.run(mpc.output(mpc.sgn(secfxp(0)))), 0)
            self.assertEqual(mpc.run(mpc.output(abs(secfxp(-1.5)))), 1.5)

            self.assertEqual(mpc.run(mpc.output(mpc.min(a, b, c, d))), min(s))
            self.assertEqual(mpc.run(mpc.output(mpc.min(a, 0))), min(s[0], 0))
            self.assertEqual(mpc.run(mpc.output(mpc.min(0, b))), min(0, s[1]))
            self.assertEqual(mpc.run(mpc.output(mpc.max(a, b, c, d))), max(s))
            self.assertEqual(mpc.run(mpc.output(mpc.max(a, 0))), max(s[0], 0))
            self.assertEqual(mpc.run(mpc.output(mpc.max(0, b))), max(0, s[1]))
            self.assertEqual(
                mpc.run(mpc.output(list(mpc.min_max(a, b, c, d)))),
                [min(s), max(s)])

            self.assertEqual(mpc.run(mpc.output(secfxp(5) % 2)), 1)
            self.assertEqual(mpc.run(mpc.output(secfxp(1) % 2**(1 - f))), 0)
            self.assertEqual(mpc.run(mpc.output(secfxp(2**-f) % 2**(1 - f))),
                             2**-f)
            self.assertEqual(
                mpc.run(mpc.output(secfxp(2 * 2**-f) % 2**(1 - f))), 0)
            self.assertEqual(mpc.run(mpc.output(secfxp(1) // 2**(1 - f))),
                             2**(f - 1))
            self.assertEqual(mpc.run(mpc.output(secfxp(27.0) % 7.0)), 6.0)
            self.assertEqual(mpc.run(mpc.output(secfxp(-27.0) // 7.0)), -4.0)
            self.assertEqual(
                mpc.run(mpc.output(list(divmod(secfxp(27.0), 6.0)))),
                [4.0, 3.0])
            self.assertEqual(mpc.run(mpc.output(secfxp(21.5) % 7.5)), 6.5)
            self.assertEqual(mpc.run(mpc.output(secfxp(-21.5) // 7.5)), -3.0)
            self.assertEqual(
                mpc.run(mpc.output(list(divmod(secfxp(21.5), 0.5)))),
                [43.0, 0.0])
Пример #15
0
async def main():
    global secint

    parser = argparse.ArgumentParser()
    parser.add_argument('-b',
                        '--batch-size',
                        type=int,
                        metavar='B',
                        help='number of images to classify')
    parser.add_argument(
        '-o',
        '--offset',
        type=int,
        metavar='O',
        help='offset for batch (otherwise random in [0,10000-B])')
    parser.add_argument(
        '-d',
        '--d-k-star',
        type=int,
        metavar='D',
        help='k=D=0,1,2 for Legendre-based comparison using d_k^*')
    parser.add_argument('--no-legendre',
                        action='store_true',
                        help='disable Legendre-based comparison')
    parser.add_argument('--no-vectorization',
                        action='store_true',
                        help='disable vectorization of comparisons')
    parser.set_defaults(batch_size=1, offset=-1, d_k_star=1)
    args = parser.parse_args()

    batch_size = args.batch_size
    offset = args.offset
    if args.no_legendre:
        secint = mpc.SecInt(14)  # using vectorized MPyC integer comparison
    else:
        if args.d_k_star == 0:
            secint = mpc.SecInt(
                14, p=3546374752298322551)  # Legendre-0 range [-134, 134]
            bsgn = bsgn_0
            vector_bsgn = vector_bsgn_0
        elif args.d_k_star == 1:
            secint = mpc.SecInt(
                14, p=9409569905028393239)  # Legendre-1 range [-383, 383]
            bsgn = bsgn_1
            vector_bsgn = vector_bsgn_1
        else:
            secint = mpc.SecInt(
                14, p=15569949805843283171)  # Legendre-2 range [-594, 594]
            bsgn = bsgn_2
            vector_bsgn = vector_bsgn_2

    one_by_one = args.no_vectorization

    await mpc.start()

    if offset < 0:
        offset = random.randrange(10001 - batch_size) if mpc.pid == 0 else None
        offset = await mpc.transfer(offset, senders=0)

    logging.info('--------------- INPUT   -------------')
    print(
        f'Type = {secint.__name__}, range = ({offset}, {offset + batch_size})')
    # read batch_size labels and images at given offset
    df = gzip.open(os.path.join('data', 'cnn', 't10k-labels-idx1-ubyte.gz'))
    d = df.read()[8 + offset:8 + offset + batch_size]
    labels = list(map(int, d))
    print('Labels:', labels)
    df = gzip.open(os.path.join('data', 'cnn', 't10k-images-idx3-ubyte.gz'))
    d = df.read()[16 + offset * 28**2:16 + (offset + batch_size) * 28**2]
    L = np.array(list(d)).reshape(batch_size, 28**2)
    if batch_size == 1:
        x = np.array(L[0]).reshape(28, 28)
        print(
            np.array2string(np.vectorize(lambda a: int(bool((a / 255))))(x),
                            separator=''))

    L = np.vectorize(lambda a: secint(int(a)))(L).tolist()

    logging.info('--------------- LAYER 1 -------------')
    logging.info('- - - - - - - - fc      - - - - - - -')
    L = mpc.matrix_prod(L, load_W('fc1'))
    L = mpc.matrix_add(L, [load_b('fc1')] * len(L))
    logging.info('- - - - - - - - bsgn    - - - - - - -')
    if one_by_one:
        L = np.vectorize(lambda a: (a >= 0) * 2 - 1)(L).tolist()
    else:
        L = [vector_sge(_) for _ in L]
    await mpc.barrier()

    logging.info('--------------- LAYER 2 -------------')
    logging.info('- - - - - - - - fc      - - - - - - -')
    L = mpc.matrix_prod(L, load_W('fc2'))
    L = mpc.matrix_add(L, [load_b('fc2')] * len(L))
    await mpc.barrier()
    logging.info('- - - - - - - - bsgn    - - - - - - -')
    if args.no_legendre:
        secint.bit_length = 10
        if one_by_one:
            activate = np.vectorize(lambda a: (a >= 0) * 2 - 1)
            L = activate(L).tolist()
        else:
            L = [vector_sge(_) for _ in L]
    else:
        if one_by_one:
            activate = np.vectorize(bsgn)
            L = activate(L).tolist()
        else:
            L = [vector_bsgn(_) for _ in L]
    await mpc.barrier()

    logging.info('--------------- LAYER 3 -------------')
    logging.info('- - - - - - - - fc      - - - - - - -')
    L = mpc.matrix_prod(L, load_W('fc3'))
    L = mpc.matrix_add(L, [load_b('fc3')] * len(L))
    await mpc.barrier()
    logging.info('- - - - - - - - bsgn    - - - - - - -')
    if args.no_legendre:
        secint.bit_length = 10
        if one_by_one:
            activate = np.vectorize(lambda a: (a >= 0) * 2 - 1)
            L = activate(L).tolist()
        else:
            L = [vector_sge(_) for _ in L]
    else:
        if one_by_one:
            activate = np.vectorize(bsgn)
            L = activate(L).tolist()
        else:
            L = [vector_bsgn(_) for _ in L]
    await mpc.barrier()

    logging.info('--------------- LAYER 4 -------------')
    logging.info('- - - - - - - - fc      - - - - - - -')
    L = mpc.matrix_prod(L, load_W('fc4'))
    L = mpc.matrix_add(L, [load_b('fc4')] * len(L))
    await mpc.barrier()

    logging.info('--------------- OUTPUT  -------------')
    if args.no_legendre:
        secint.bit_length = 14
    for i in range(batch_size):
        prediction = await mpc.output(mpc.argmax(L[i])[0])
        error = '******* ERROR *******' if prediction != labels[i] else ''
        print(
            f'Image #{offset+i} with label {labels[i]}: {prediction} predicted. {error}'
        )
        print(await mpc.output(L[i]))

    await mpc.shutdown()
Пример #16
0
    def test_secfxp(self):
        secfxp = mpc.SecFxp()
        self.assertEqual(
            mpc.run(mpc.output(mpc.input(secfxp(7.75), senders=0))), 7.75)
        c = mpc.to_bits(secfxp(0),
                        0)  # mpc.output() only works for nonempty lists
        self.assertEqual(c, [])
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(0))))
        self.assertEqual(c, [0.0] * 32)
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(1))))
        self.assertEqual(c, [0.0] * 16 + [1.0] + [0.0] * 15)
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(0.5))))
        self.assertEqual(c, [0.0] * 15 + [1.0] + [0.0] * 16)
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(8113))))
        self.assertEqual(c, [0.0] * 16 +
                         [1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0])
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(2**15 - 1))))
        self.assertEqual(c, [0] * 16 + [1] * 15 + [0])
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(-1))))
        self.assertEqual(c, [0] * 16 + [1] * 16)
        c = mpc.run(mpc.output(mpc.to_bits(secfxp(-2**15))))
        self.assertEqual(c, [0] * 31 + [1])

        for f in [8, 16, 32, 64]:
            secfxp = mpc.SecFxp(2 * f)
            c = mpc.run(mpc.output(secfxp(1) + secfxp(1)))
            self.assertEqual(c, 2)
            c = mpc.run(mpc.output(secfxp(2**-f) + secfxp(1)))
            if f != 64:  # NB: 1 + 2**-64 == 1 in Python
                self.assertEqual(c, 1 + 2**-f)
            self.assertEqual(mpc.run(mpc.output(secfxp(0.5) * secfxp(2.0))), 1)
            self.assertEqual(mpc.run(mpc.output(secfxp(2.0) * secfxp(0.5))), 1)
            c = mpc.run(
                mpc.output(
                    secfxp(2**(f // 2 - 1) - 0.5) *
                    secfxp(-2**(f // 2) + 0.5)))
            self.assertEqual(c, -2**(f - 1) + 1.5 * 2**(f // 2 - 1) - 0.25)

            s = [10.75, -3.375, 0.125, -0.125]
            self.assertEqual(mpc.run(mpc.output(list(map(secfxp, s)))), s)

            s = [10.5, -3.25, 0.125, -0.125]
            a, b, c, d = list(map(secfxp, s))
            t = [v * v for v in s]
            self.assertEqual(mpc.run(mpc.output([a * a, b * b, c * c, d * d])),
                             t)
            x = [a, b, c, d]
            self.assertEqual(mpc.run(mpc.output(mpc.schur_prod(x, x))), t)
            self.assertEqual(mpc.run(mpc.output(mpc.schur_prod(x, x[:]))), t)
            t = sum(t)
            self.assertEqual(mpc.run(mpc.output(mpc.in_prod(x, x))), t)
            self.assertEqual(mpc.run(mpc.output(mpc.in_prod(x, x[:]))), t)
            self.assertEqual(
                mpc.run(mpc.output(mpc.matrix_prod([x], [x], True)[0])), [t])
            u = mpc.unit_vector(secfxp(3), 4)
            self.assertEqual(
                mpc.run(mpc.output(mpc.matrix_prod([x], [u], True)[0])),
                [s[3]])
            self.assertEqual(
                mpc.run(mpc.output(mpc.matrix_prod([u], [x], True)[0])),
                [s[3]])
            self.assertEqual(
                mpc.run(mpc.output(mpc.gauss([[a]], b, [a], [b])[0])), [0])
            t = [_ for a, b, c, d in [s] for _ in [a + b, a * b, a - b]]
            self.assertEqual(mpc.run(mpc.output([a + b, a * b, a - b])), t)
            t = [
                _ for a, b, c, d in [s]
                for _ in [(a + b)**2, (a + b)**2 + 3 * c]
            ]
            self.assertEqual(
                mpc.run(mpc.output([(a + b)**2, (a + b)**2 + 3 * c])), t)
            t = [_ for a, b, c, d in [s] for _ in [a < b, b < c, c < d]]
            self.assertEqual(mpc.run(mpc.output([a < b, b < c, c < d])), t)
            t = s[0] < s[1] and s[1] < s[2]
            self.assertEqual(mpc.run(mpc.output((a < b) & (b < c))), t)
            t = s[0] < s[1] or s[1] < s[2]
            self.assertEqual(mpc.run(mpc.output((a < b) | (b < c))), t)
            t = (int(s[0] < s[1]) ^ int(s[1] < s[2]))
            self.assertEqual(mpc.run(mpc.output((a < b) ^ (b < c))), t)
            t = (int(not s[0] < s[1]) ^ int(s[1] < s[2]))
            self.assertEqual(mpc.run(mpc.output(~(a < b) ^ b < c)), t)
            t = [s[0] > 1, 10 * s[1] < 5, 10 * s[0] == 5]
            self.assertEqual(
                mpc.run(mpc.output([a > 1, 10 * b < 5, 10 * a == 5])), t)

            s[3] = -0.120
            d = secfxp(s[3])
            t = s[3] / 0.25
            self.assertAlmostEqual(mpc.run(mpc.output(d / 0.25)),
                                   t,
                                   delta=2**(1 - f))
            t = round(s[3] / s[2] + s[0])
            self.assertEqual(round(mpc.run(mpc.output(d / c + a))), t)
            t = ((s[0] + s[1])**2 + 3 * s[2]) / s[2]
            self.assertAlmostEqual(mpc.run(mpc.output(
                ((a + b)**2 + 3 * c) / c)),
                                   t,
                                   delta=2**(8 - f))
            t = 1 / s[3]
            self.assertAlmostEqual(mpc.run(mpc.output(1 / d)),
                                   t,
                                   delta=2**(6 - f))
            t = s[2] / s[3]
            self.assertAlmostEqual(mpc.run(mpc.output(c / d)),
                                   t,
                                   delta=2**(3 - f))
            t = -s[3] / s[2]
            self.assertAlmostEqual(mpc.run(mpc.output(-d / c)),
                                   t,
                                   delta=2**(3 - f))

            self.assertEqual(mpc.run(mpc.output(mpc.sgn(+a))), s[0] > 0)
            self.assertEqual(mpc.run(mpc.output(mpc.sgn(-a))), -(s[0] > 0))
            self.assertEqual(mpc.run(mpc.output(mpc.sgn(secfxp(0)))), 0)
            self.assertEqual(mpc.run(mpc.output(abs(secfxp(-1.5)))), 1.5)

            self.assertEqual(mpc.run(mpc.output(mpc.min(a, b, c, d))), min(s))
            self.assertEqual(mpc.run(mpc.output(mpc.min(a, 0))), min(s[0], 0))
            self.assertEqual(mpc.run(mpc.output(mpc.min(0, b))), min(0, s[1]))
            self.assertEqual(mpc.run(mpc.output(mpc.max(a, b, c, d))), max(s))
            self.assertEqual(mpc.run(mpc.output(mpc.max(a, 0))), max(s[0], 0))
            self.assertEqual(mpc.run(mpc.output(mpc.max(0, b))), max(0, s[1]))
            self.assertEqual(
                mpc.run(mpc.output(list(mpc.min_max(a, b, c, d)))),
                [min(s), max(s)])
            self.assertEqual(mpc.run(mpc.output(mpc.argmin([a, b, c, d])[0])),
                             1)
            self.assertEqual(
                mpc.run(mpc.output(mpc.argmin([a, b], key=operator.neg)[1])),
                max(s))
            self.assertEqual(mpc.run(mpc.output(mpc.argmax([a, b, c, d])[0])),
                             0)
            self.assertEqual(
                mpc.run(mpc.output(mpc.argmax([a, b], key=operator.neg)[1])),
                min(s))

            self.assertEqual(mpc.run(mpc.output(secfxp(5) % 2)), 1)
            self.assertEqual(mpc.run(mpc.output(secfxp(1) % 2**(1 - f))), 0)
            self.assertEqual(mpc.run(mpc.output(secfxp(2**-f) % 2**(1 - f))),
                             2**-f)
            self.assertEqual(
                mpc.run(mpc.output(secfxp(2 * 2**-f) % 2**(1 - f))), 0)
            self.assertEqual(mpc.run(mpc.output(secfxp(1) // 2**(1 - f))),
                             2**(f - 1))
            self.assertEqual(mpc.run(mpc.output(secfxp(27.0) % 7.0)), 6.0)
            self.assertEqual(mpc.run(mpc.output(secfxp(-27.0) // 7.0)), -4.0)
            self.assertEqual(
                mpc.run(mpc.output(list(divmod(secfxp(27.0), 6.0)))),
                [4.0, 3.0])
            self.assertEqual(mpc.run(mpc.output(secfxp(21.5) % 7.5)), 6.5)
            self.assertEqual(mpc.run(mpc.output(secfxp(-21.5) // 7.5)), -3.0)
            self.assertEqual(
                mpc.run(mpc.output(list(divmod(secfxp(21.5), 0.5)))),
                [43.0, 0.0])
Пример #17
0
async def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '-i',
        '--dataset',
        type=int,
        metavar='I',
        help=('dataset 0=uvlp (default), 1=wiki, 2=tb2x2, 3=woody, '
              '4=LPExample_R20, 5=sc50b, 6=kb2, 7=LPExample'))
    parser.add_argument('-l',
                        '--bit-length',
                        type=int,
                        metavar='L',
                        help='override preset bit length for dataset')
    parser.set_defaults(dataset=0, bit_length=0)
    args = parser.parse_args()

    settings = [('uvlp', 8, 1, 2), ('wiki', 6, 1, 2), ('tb2x2', 6, 1, 2),
                ('woody', 8, 1, 3), ('LPExample_R20', 70, 1, 5),
                ('sc50b', 104, 10, 55), ('kb2', 536, 100000, 106),
                ('LPExample', 110, 1, 178)]
    name, bit_length, scale, n_iter = settings[args.dataset]
    if args.bit_length:
        bit_length = args.bit_length

    with open(os.path.join('data', 'lp', name + '.csv')) as file:
        T = list(csv.reader(file))
    m = len(T) - 1
    n = len(T[0]) - 1
    secint = mpc.SecInt(bit_length, n=m +
                        n)  # force existence of Nth root of unity, N>=m+n
    print(f'Using secure {bit_length}-bit integers: {secint.__name__}')
    print(
        f'dataset: {name} with {m} constraints and {n} variables (scale factor {scale})'
    )
    T[0][-1] = '0'  # initialize optimal value
    for i in range(m + 1):
        g = 0
        for j in range(n + 1):
            T[i][j] = int(scale * float(T[i][j]))  # scale to integer
            g = math.gcd(g, T[i][j])
        g = max(g, 1) if i else 1  # skip cost row
        for j in range(n + 1):
            T[i][j] = secint(T[i][j] // g)

    c = T[0][:-1]  # maximize c.x subject to A.x <= b, x >= 0
    A = [T[i + 1][:-1] for i in range(m)]
    b = [T[i + 1][-1] for i in range(m)]

    Zp = secint.field
    N = Zp.nth
    w = Zp.root  # w is an Nth root of unity in Zp, where N >= m + n
    w_powers = [Zp(1)]
    for _ in range(N - 1):
        w_powers.append(w_powers[-1] * w)
    assert w_powers[-1] * w == 1

    await mpc.start()

    cobasis = [secint(w_powers[-j]) for j in range(n)]
    basis = [secint(w_powers[-(i + n)]) for i in range(m)]
    previous_pivot = secint(1)

    iteration = 0
    while True:
        # find index of pivot column
        p_col_index, minimum = argmin_int(T[0][:-1])
        if await mpc.output(minimum >= 0):
            break  # maximum reached

        # find index of pivot row
        p_col = mpc.matrix_prod([p_col_index], T, True)[0]
        constraints = [[T[i][-1] + (p_col[i] <= 0), p_col[i]]
                       for i in range(1, m + 1)]
        p_row_index, (_, pivot) = argmin_rat(constraints)

        # reveal progress a bit
        iteration += 1
        mx = await mpc.output(T[0][-1])
        cd = await mpc.output(previous_pivot)
        p = await mpc.output(pivot)  # NB: no await in f-strings in Python 3.6
        logging.info(
            f'Iteration {iteration}/{n_iter}: {mx / cd} pivot={p / cd}')

        # swap basis entries
        delta = mpc.in_prod(basis, p_row_index) - mpc.in_prod(
            cobasis, p_col_index)
        cobasis = mpc.vector_add(cobasis, mpc.scalar_mul(delta, p_col_index))
        basis = mpc.vector_sub(basis, mpc.scalar_mul(delta, p_row_index))

        # update tableau Tij = Tij*Tkl/Tkl' - (Til/Tkl' - bool(i==k)) * (Tkj + bool(j==l)*Tkl')
        p_col_index.append(secint(0))
        p_row_index.insert(0, secint(0))
        pp_inv = 1 / previous_pivot
        p_col = mpc.scalar_mul(pp_inv, p_col)
        p_col = mpc.vector_sub(p_col, p_row_index)
        p_row = mpc.matrix_prod([p_row_index], T)[0]
        p_row = mpc.vector_add(p_row,
                               mpc.scalar_mul(previous_pivot, p_col_index))
        T = mpc.gauss(T, pivot * pp_inv, p_col, p_row)
        previous_pivot = pivot

    mx = await mpc.output(T[0][-1])
    cd = await mpc.output(previous_pivot
                          )  # common denominator for all entries of T
    print(
        f'max = {mx} / {cd} / {scale} = {mx / cd / scale} in {iteration} iterations'
    )

    logging.info('Solution x')
    sum_x_powers = [secint(0) for _ in range(N)]
    for i in range(m):
        x_powers = pow_list(T[i + 1][-1] / N, basis[i], N)
        sum_x_powers = mpc.vector_add(sum_x_powers, x_powers)
    x = [None] * n
    for j in range(n):
        coefs = [w_powers[(j * k) % N] for k in range(N)]
        x[j] = mpc.in_prod(coefs, sum_x_powers)
    cx = mpc.in_prod(c, x)
    Ax = mpc.matrix_prod([x], A, True)[0]
    Ax_bounded_by_b = mpc.all(Ax[i] <= b[i] * cd for i in range(m))
    x_nonnegative = mpc.all(x[j] >= 0 for j in range(n))

    logging.info('Dual solution y')
    sum_x_powers = [secint(0) for _ in range(N)]
    for j in range(n):
        x_powers = pow_list(T[0][j] / N, cobasis[j], N)
        sum_x_powers = mpc.vector_add(sum_x_powers, x_powers)
    y = [None] * m
    for i in range(m):
        coefs = [w_powers[((n + i) * k) % N] for k in range(N)]
        y[i] = mpc.in_prod(coefs, sum_x_powers)
        y[i] = -y[i]
    yb = mpc.in_prod(y, b)
    yA = mpc.matrix_prod([y], A)[0]
    yA_bounded_by_c = mpc.all(yA[j] <= c[j] * cd for j in range(n))
    y_nonpositive = mpc.all(y[i] <= 0 for i in range(m))

    cx_eq_yb = cx == yb
    check = mpc.all([
        cx_eq_yb, Ax_bounded_by_b, x_nonnegative, yA_bounded_by_c,
        y_nonpositive
    ])
    check = bool(await mpc.output(check))
    print(
        f'verification c.x == y.b, A.x <= b, x >= 0, y.A <= c, y <= 0: {check}'
    )

    x = await mpc.output(x)
    print(f'solution = {[a / cd for a in x]}')

    await mpc.shutdown()