diff --git a/src/ipre.cpp b/src/ipre.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5396fb29a5f51222309ea6c6b8e70a3f362717e5 --- /dev/null +++ b/src/ipre.cpp @@ -0,0 +1,72 @@ +#include "ipre.h" + +key setup(int size) { + key key{}; + pc_get_ord(key.modular); + gen(key.base); + bp_map(key.base, key.base, key.t_base); + key.A = matrix_zp_rand(2, size, key.modular); + key.B = matrix_zp_rand(B_SIZE, B_SIZE, key.modular); + key.Bi = matrix_transpose(matrix_inverse(key.B, B_SIZE, key.modular), B_SIZE, B_SIZE); + return key; +} + +ct enc(key key, const int *message, int size) { + // Declare the returned ciphertext and convert message to zp. + ct ct{}; + zp_vec x = vector_zp_from_int(message, size, key.modular); + + // Helper values. + int one[] = {1}, zero[] = {0}; + zp_vec one_vec = vector_zp_from_int(one, 1, key.modular); + zp_vec zero_vec = vector_zp_from_int(zero, 1, key.modular); + + // We generate s and compute sA + x. + zp_vec s = vector_zp_rand(2, key.modular); + zp_vec sA = matrix_multiply(s, key.A, 1, 2, size, key.modular); + zp_vec sAx = vector_add(sA, x, size); + ct.ctx = vector_raise(key.base, sAx, size); + + // We compute the function hiding inner product encryption key. + zp_mat AT = matrix_transpose(key.A, 2, size); + zp_vec xAT = matrix_multiply(x, AT, 1, size, 2, key.modular); + zp_vec xATs = vector_merge(xAT, s, 2, 2); + zp_vec xATs0 = vector_merge(xATs, zero_vec, 4, 1); + zp_vec xATs01 = vector_merge(xATs0, one_vec, 5, 1); + zp_vec xATs01_B = matrix_multiply(xATs01, key.B, 1, B_SIZE, B_SIZE, key.modular); + ct.ctc = vector_raise(key.base, xATs01_B, B_SIZE); + + // We compute the function hiding inner product encryption ciphertext. + zp_vec sAAT = matrix_multiply(sA, AT, 1, size, 2, key.modular); + zp_vec xATsAAT = vector_add(xAT, sAAT, 2); + zp_vec sxATsAAT = vector_merge(s, xATsAAT, 2, 2); + zp_vec sxATsAAT1 = vector_merge(sxATsAAT, one_vec, 4, 1); + zp_vec sxATsAAT10 = vector_merge(sxATsAAT1, zero_vec, 5, 1); + zp_vec sxATsAAT10_Bi = matrix_multiply(sxATsAAT10, key.Bi, 1, B_SIZE, B_SIZE, key.modular); + ct.ctk = vector_raise(key.base, sxATsAAT10_Bi, B_SIZE); + + return ct; +} + +int eval(key key, ct x, ct y, int size, int bound) { + // Decrypt components. + gt xy, ct; + inner_product(xy, x.ctx, y.ctx, size); + inner_product(ct, x.ctc, y.ctk, B_SIZE); + + // Decrypt final result. + gt_inv(ct, ct); + gt_mul(xy, xy, ct); + + // Get a G_t element holder. + gt output; + + // Iterate through a loop to find correct answer. + for (int i = 1; i <= bound; i++) { + gt_exp_dig(output, key.t_base, i); + if (gt_cmp(output, xy) == RLC_EQ) return i; + } + + // Otherwise return 0 as the output. + return 0; +} \ No newline at end of file diff --git a/tests/test_ipre.cpp b/tests/test_ipre.cpp new file mode 100644 index 0000000000000000000000000000000000000000..efbc89794568c92e7319afbe3275082816f356a4 --- /dev/null +++ b/tests/test_ipre.cpp @@ -0,0 +1,27 @@ +#include "ipre.h" + +int test_scheme() { + // Set x, y vectors. + int x[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 2}; + int y[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + // Initialize the scheme. + key key = setup(10); + // Encrypt the messages. + ct ct_x = enc(key, x, 10); + ct ct_y = enc(key, y, 10); + // Evaluate the two ciphertexts. + int output = eval(key, ct_x, ct_y, 10, 100); + + return output == 65; +} + +int main() { + // Init core and setup. + core_init(); + pc_param_set_any(); + + // Perform tests. + if (test_scheme() != 1) return 1; + + return 0; +} \ No newline at end of file