예제 #1
0
def prepare_first_box_MM(sk, root, unroot, ninv, beta, k):

    sk.goto_ntt(root)

    M = np.prod(beta)
    N = sk.modulus
    Ninv_M = goto_crt(xgcd(N, M)[1], beta, k)
    fb = {}
    for dim in range(sk.degree):
        print_progress(dim, tmp_sk.degree, 64)
        key = "fb_dim_"+str(dim)
        fb[key] = [[0]*32 for i in range(32)]
        s = sk.vector[dim]
        s = goto_crt(s, beta, k)
        for j in range(32):
            a = goto_crt(j, beta, k)
            for l in range(32):
                b = goto_crt(l, beta, k)

                fb[key][j][l] = int(
                    (int(((a[0] * s[0] + b[0])
                          * (-Ninv_M[0])) % beta[0])) +
                    (int(((a[1] * s[1] + b[1])
                          * (-Ninv_M[1])) % beta[1]) << 5) +
                    (int(((a[2] * s[2] + b[2])
                          * (-Ninv_M[2])) % beta[2]) << 10) +
                    (int(((a[3] * s[3] + b[3])
                          * (-Ninv_M[3])) % beta[3]) << 15) +
                    (int(((a[4] * s[4] + b[4])
                          * (-Ninv_M[4])) % beta[4]) << 20)
                )
    print_progress(tmp_sk.degree, tmp_sk.degree, 64)
    sk.goback_ntt(unroot, ninv)
    return fb
예제 #2
0
def prepare_second_box_MM3(sk, a1_r, a2_r, a1_ma, a2_ma, root,
                           unroot, ninv, beta, beta_p, k):

    # compute intermediate encoding values to limit
    # number of products in Montgomery
    rot = a2_r + a1_r * sk
    mask = -(a2_ma + a1_ma * sk)

    # create alternate key tmp_sk and fake key tmp_sz
    tmp_sk = sk * rot
    tmp_sz = sk * mask

    # go to ntt
    rot.goto_ntt(root)
    mask.goto_ntt(root)
    tmp_sk.goto_ntt(root)
    tmp_sz.goto_ntt(root)

    # prepare Montgomery parameters
    # N = tmp_sk.modulus
    M = np.prod(beta)
    M_p = np.prod(beta_p)
    Minv_M_p = goto_crt(xgcd(M, M_p)[1], beta_p, k)
    # N_M_p = goto_crt(N, beta_p, k)
    sb = {}
    for dim in range(tmp_sk.degree):
        key = "sb_dim_"+str(dim)
        sb[key] = [[0]*32 for i in range(32)]
        # go to crt
        s = tmp_sk.vector[dim]
        s = goto_crt(s, beta_p, k)
        sz = tmp_sz.vector[dim]
        sz = goto_crt(sz, beta_p, k)
        r = rot.vector[dim]
        r = goto_crt(r, beta_p, k)
        m = mask.vector[dim]
        m = goto_crt(m, beta_p, k)
        # parse all possible input values
        for j in range(32):
            a = goto_crt(j, beta_p, k)
            for l in range(32):
                b = goto_crt(l, beta_p, k)
                # compute decoding function
                sb[key][j][l] = int(
                    (int(((a[0] * s[0] + b[0] * r[0] + r[0] * m[0])
                          * Minv_M_p[0]) % beta_p[0])) +
                    (int(((a[1] * s[1] + b[1] * r[1] + r[1] * m[1])
                          * Minv_M_p[1]) % beta_p[1]) << 5) +
                    (int(((a[2] * s[2] + b[2] * r[2] + r[2] * m[2])
                          * Minv_M_p[2]) % beta_p[2]) << 10) +
                    (int(((a[3] * s[3] + b[3] * r[3] + r[3] * m[3])
                          * Minv_M_p[3]) % beta_p[3]) << 15) +
                    (int(((a[4] * s[4] + b[4] * r[4] + r[4] * m[4])
                          * Minv_M_p[4]) % beta_p[4]) << 20)
                )
        print_progress(dim, tmp_sk.degree, 64)
    return sb
예제 #3
0
    def mont_mult(cls, dim, a, b, N):
        # set up for Montgomery
        B = cls.white['beta']
        B_p = cls.white['beta_p']
        k = cls.white['k']
        # a and b in base M
        a_M = goto_crt(a, B, k)
        b_M = goto_crt(b, B, k)
        # a and b in base M'
        a_M_p = goto_crt(a, B_p, k)
        b_M_p = goto_crt(b, B_p, k)
        # base M
        M = np.prod(B)
        # base M'
        M_p = np.prod(B_p)
        # inv(N) mod M
        # Ninv_M = goto_crt(xgcd(N, M)[1], B, k)
        # inv(N) mod M'
        Minv_M_p = goto_crt(xgcd(M, M_p)[1], B_p, k)
        # N in base M'
        N_M_p = goto_crt(N, B_p, k)

        # start computing q
        # q = [((a_M[i] * s_M[i] + b_M[i]) *\
        #     (-Ninv_M[i]))%B[i] for i in range(k)]

        fb = cls.white['fb_dim_' + str(dim)]
        q = [0] * k
        q[0] = fb[a_M[0]][b_M[0]] % (1 << 5)
        q[1] = (fb[a_M[1]][b_M[1]] % (1 << 10)) >> 5
        q[2] = (fb[a_M[2]][b_M[2]] % (1 << 15)) >> 10
        q[3] = (fb[a_M[3]][b_M[3]] % (1 << 20)) >> 15
        q[4] = (fb[a_M[4]][b_M[4]]) >> 20

        # shift from base B to B'
        q = goback_crt(q, B, k)
        q = goto_crt(q, B_p, k)

        # compute r
        # r = [((a_M_p[i] * s_M_p[i] + b_M_p[i] + q[i]*N_M_p[i])\
        #     * Minv_M_p[i])%B_p[i] for i in range(k) ]

        sb = cls.white['sb_dim_' + str(dim)]
        r = [(q[i] * N_M_p[i] * Minv_M_p[i]) % B_p[i] for i in range(k)]
        r[0] += sb[a_M_p[0]][b_M_p[0]] % (1 << 5)
        r[1] += (sb[a_M_p[1]][b_M_p[1]] % (1 << 10)) >> 5
        r[2] += (sb[a_M_p[2]][b_M_p[2]] % (1 << 15)) >> 10
        r[3] += (sb[a_M_p[3]][b_M_p[3]] % (1 << 20)) >> 15
        r[4] += (sb[a_M_p[4]][b_M_p[4]]) >> 20

        # go back to B from B'
        r = goback_crt(r, B_p, k)

        return r * M
예제 #4
0
def prepare_second_box_MM(sk, root, unroot, ninv, beta, beta_p, k):

    sk.goto_ntt(root)

    # N = sk.modulus
    M = np.prod(beta)
    M_p = np.prod(beta_p)
    Minv_M_p = goto_crt(xgcd(M, M_p)[1], beta_p, k)
    # N_M_p = goto_crt(N, beta_p, k)
    sb = {}
    for dim in range(sk.degree):
        print_progress(dim, tmp_sk.degree, 64)
        key = "sb_dim_"+str(dim)
        sb[key] = [[0]*32 for i in range(32)]
        s = sk.vector[dim]
        s = goto_crt(s, beta_p, k)
        for j in range(32):
            a = goto_crt(j, beta_p, k)
            for l in range(32):
                b = goto_crt(l, beta_p, k)

                sb[key][j][l] = int(
                    (int(((a[0] * s[0] + b[0])
                          * Minv_M_p[0]) % beta_p[0])) +
                    (int(((a[1] * s[1] + b[1])
                          * Minv_M_p[1]) % beta_p[1]) << 5) +
                    (int(((a[2] * s[2] + b[2])
                          * Minv_M_p[2]) % beta_p[2]) << 10) +
                    (int(((a[3] * s[3] + b[3])
                          * Minv_M_p[3]) % beta_p[3]) << 15) +
                    (int(((a[4] * s[4] + b[4])
                          * Minv_M_p[4]) % beta_p[4]) << 20)
                )
    print_progress(tmp_sk.degree, tmp_sk.degree, 64)
    sk.goback_ntt(unroot, ninv)
    return sb
예제 #5
0
def write_data(degree, modulus, beta, beta_p, k, chal=0):
    # set WB keys
    pka, pkb, sk = key_gen(degree, modulus)

    # set homomorphic masks if chal 1
    one = np.zeros(degree)
    one[0] = 1
    a1_o, a2_o = encrypt(one, pka, pkb, degree, modulus)
    zero = np.zeros(degree)
    a1_z, a2_z = encrypt(zero, pka, pkb, degree, modulus)

    # set homomorphic masks if chal 2
    rotate = np.zeros(degree)
    rot = rand.randint(0, degree)
    rotate[rot] = 1
    a1_rot, a2_rot = encrypt(rotate, pka, pkb, degree, modulus)

    mask = np.zeros(degree)
    for i in range(degree):
        mask[i] = rand.randint(0, 1)
    a1_ma, a2_ma = encrypt(mask, pka, pkb, degree, modulus)

    # set root for NTT, this need to be static (put in pub data)
    root = find_primitive_root(2*degree, modulus-1, modulus)
    unroot = xgcd(root, modulus)[1]
    ninv = xgcd(degree, modulus)[1]

    # writing private data
    # private data should only be accessed for testing purposes
    # remove otherwise
    d = {'sk': sk.vector.tolist(),
         'a1_o': a1_o.vector.tolist(),
         'a2_o': a2_o.vector.tolist(),
         'a1_z': a1_z.vector.tolist(),
         'a2_z': a2_z.vector.tolist()
         }

    with open('private_data.json', 'w') as f:
        json.dump(d, f)

    # writing public encryption data
    d = {'degree': degree,
         'modulus': modulus,
         'pka': pka.vector.tolist(),
         'pkb': pkb.vector.tolist()
         }
    with open('pub_enc_data.json', 'w') as f:
        json.dump(d, f)

    # writing whiteboxed decryption data
    d = {'root': root,
         'unroot': unroot,
         'ninv': ninv,
         'beta': beta,
         'beta_p': beta_p,
         'k': k,
         'mask': mask.tolist(),
         'rotate': rot,
         'chal': chal
         }
    # f = open('wb_dec_data.json', 'w')
    # json.dump(d, f)
    # writing lookup tables for white montgomery multiplication (need 2 set)
    # if chal, no encodings
    if chal == 0:
        print("prepare_first_box_MM")
        d.update(prepare_first_box_MM(sk, root, unroot, ninv, beta, k))
        print("prepare_second_box_MM")
        d.update(prepare_second_box_MM(
            sk, root, unroot, ninv, beta, beta_p, k))
    elif chal == 1:
        print("prepare_first_box_MM2")
        d.update(prepare_first_box_MM2(
            sk, a1_o, a2_o, a1_z, a2_z,
            root, unroot, ninv, beta, k))
        print("prepare_second_box_MM2")
        d.update(prepare_second_box_MM2(
            sk, a1_o, a2_o, a1_z, a2_z,
            root, unroot, ninv, beta, beta_p, k))
    elif chal == 2:
        print("prepare_first_box_MM3")
        d.update(prepare_first_box_MM3(
            sk, a1_rot, a2_rot, a1_ma, a2_ma,
            root, unroot, ninv, beta, k))
        print("prepare_second_box_MM3")
        d.update(prepare_second_box_MM3(
            sk, a1_rot, a2_rot, a1_ma, a2_ma,
            root, unroot, ninv, beta, beta_p, k))
    with open('wb_dec_data.json', 'w') as f:
        json.dump(d, f)
예제 #6
0
def prepare_second_box_MM2(sk, a1_o, a2_o, a1_z, a2_z, root,
                           unroot, ninv, beta, beta_p, k):

    # compute intermediate encoding values to limit
    # number of products in Montgomery
    one = a2_o + a1_o * sk
    zero = -(a2_z + a1_z * sk)

    # create alternate key tmp_sk and fake key tmp_sz
    tmp_sk = sk * one
    tmp_sz = sk * zero

    # go to ntt
    one.goto_ntt(root)
    zero.goto_ntt(root)
    tmp_sk.goto_ntt(root)
    tmp_sz.goto_ntt(root)

    # prepare Montgomery parameters
    # N = tmp_sk.modulus
    M = np.prod(beta)
    M_p = np.prod(beta_p)
    Minv_M_p = goto_crt(xgcd(M, M_p)[1], beta_p, k)
    # N_M_p = goto_crt(N, beta_p, k)
    sb = {}
    for dim in range(tmp_sk.degree):
        print_progress(dim, tmp_sk.degree, 64)
        key = "sb_dim_"+str(dim)
        sb[key] = [[0]*32 for i in range(32)]
        # go to crt
        s = tmp_sk.vector[dim]
        s = goto_crt(s, beta_p, k)
        sz = tmp_sz.vector[dim]
        sz = goto_crt(sz, beta_p, k)
        o = one.vector[dim]
        o = goto_crt(o, beta_p, k)
        z = zero.vector[dim]
        z = goto_crt(z, beta_p, k)
        # parse all possible input values
        for j in range(32):
            a = goto_crt(j, beta_p, k)
            for l in range(32):
                b = goto_crt(l, beta_p, k)
                # compute decoding function
                sb[key][j][l] = int(
                    (int(((a[0] * s[0] + b[0] * o[0]
                           + a[0] * sz[0] + b[0] * z[0])
                          * Minv_M_p[0]) % beta_p[0])) +
                    (int(((a[1] * s[1] + b[1] * o[1]
                           + a[1] * sz[1] + b[1] * z[1])
                          * Minv_M_p[1]) % beta_p[1]) << 5) +
                    (int(((a[2] * s[2] + b[2] * o[2]
                           + a[2] * sz[2] + b[2] * z[2])
                          * Minv_M_p[2]) % beta_p[2]) << 10) +
                    (int(((a[3] * s[3] + b[3] * o[3]
                           + a[3] * sz[3] + b[3] * z[3])
                          * Minv_M_p[3]) % beta_p[3]) << 15) +
                    (int(((a[4] * s[4] + b[4] * o[4]
                           + a[4] * sz[4] + b[4] * z[4])
                          * Minv_M_p[4]) % beta_p[4]) << 20)
                )
    print_progress(tmp_sk.degree, tmp_sk.degree, 64)
    return sb