#[macro_use] extern crate lazy_static; use rand::Rng; use parmesan::userovo::encryption; use parmesan::arithmetics::ParmArithmetics; use parmesan::ciphertexts::{ParmCiphertext, ParmCiphertextImpl}; #[allow(dead_code)] mod common; use common::*; // ----------------------------------------------------------------------------- // Test Cases // Add Const #[test] /// Addition of a constant to encrypted sub-samples only. fn t_add_const_non_triv() { println!("Non-Triv ..."); t_impl_add_const_with_mode(EncrVsTriv::ENCR); } #[test] /// Addition of a constant to trivial sub-samples only. fn t_add_const_all_triv() { println!("All-Triv ..."); t_impl_add_const_with_mode(EncrVsTriv::TRIV); } #[test] /// Addition of a constant to mixed sub-samples. fn t_add_const_some_triv() { println!("Mixed ..."); t_impl_add_const_with_mode(EncrVsTriv::ENCRTRIV); } // Corner Cases //TODO add others #[test] /// Corner case with trivial zeros overlap, encrypted sub-samples only. fn t_add_zeros_overlap() { println!("Zeros Overlap ..."); // 00███00 // 000██00000000 t_impl_add_triv_zeros_with_mode( 2, 3, 2, EncrVsTriv::ENCR, 3, 2, 8, ) } #[test] /// Corner cases with trivial zeros, encrypted sub-samples only. fn t_add_mul_fail() { println!("From Mul Fail ..."); // ██00 // 0██0 t_impl_add_triv_zeros_with_mode( 0, 2, 2, EncrVsTriv::ENCR, 1, 2, 1, ) } // ----------------------------------------------------------------------------- // Test Implementations /// Implementation for three variants of vector to be evaluated. fn t_impl_add_const_with_mode( mode: EncrVsTriv, ) { // for mis-aligned length generation let mut rng = rand::thread_rng(); for _ in 0..common::TESTS_REPEAT_ADD_CONST { // generate random vector(s) let bl_e = rng.gen_range(0..=common::TESTS_BITLEN_ADD_CONST); let bl_c = rng.gen_range(0..=common::TESTS_BITLEN_ADD_CONST); let me_vec = gen_rand_vec(bl_e); let mc_vec = gen_rand_vec(bl_c); // convert to integer(s) let me = encryption::convert_from_vec(&me_vec).expect("convert failed."); let mc = encryption::convert_from_vec(&mc_vec).expect("convert failed."); println!(" m = {} ({}-bit: {:?}), const = {} ({}-bit: {:?})", me, bl_e, me_vec, mc, bl_c, mc_vec); // encrypt -> homomorphic eval -> decrypt let c = encrypt_with_mode(&me_vec, mode); let c_he = ParmArithmetics::add_const(&common::TEST_PC, &c, mc); let m_he = common::TEST_PU.decrypt(&c_he).expect("ParmesanUserovo::decrypt failed."); // plain eval let m_pl = ParmArithmetics::add_const(&common::TEST_PC, &me, mc); println!(" add const = {} (exp. {})", m_he, m_pl); // compare results assert_eq!(m_he, m_pl); } } /// Implementation for manually provided cases of triv zeros. fn t_impl_add_triv_zeros_with_mode( ltriv_x: usize, ct_len_x: usize, rtriv_x: usize, mode: EncrVsTriv, ltriv_y: usize, ct_len_y: usize, rtriv_y: usize, ) { for _ in 0..common::TESTS_REPEAT_ADD_TRIV_0 { // generate random vectors & respective ciphertexts with given number of trivial zeros let (m1_vec, c1) = t_gen_ct_with_triv_zeros( ltriv_x, ct_len_x, rtriv_x, mode, ); let (m2_vec, c2) = t_gen_ct_with_triv_zeros( ltriv_y, ct_len_y, rtriv_y, mode, ); // convert to integer(s) let m1 = encryption::convert_from_vec(&m1_vec).expect("convert failed."); let m2 = encryption::convert_from_vec(&m2_vec).expect("convert failed."); println!(" m1 = {} ({:?} |{}█{}|), m2 = {} ({:?} |{}█{}|)", m1, m1_vec, ltriv_x, rtriv_x, m2, m2_vec, ltriv_y, rtriv_y); // homomorphic eval -> decrypt let c_he_a = ParmArithmetics::add(&common::TEST_PC, &c1, &c2); let c_he_s = ParmArithmetics::sub(&common::TEST_PC, &c1, &c2); let m_he_a = common::TEST_PU.decrypt(&c_he_a).expect("ParmesanUserovo::decrypt failed."); let m_he_s = common::TEST_PU.decrypt(&c_he_s).expect("ParmesanUserovo::decrypt failed."); // plain eval let m_pl_a = ParmArithmetics::add(&common::TEST_PC, &m1, &m2); let m_pl_s = ParmArithmetics::sub(&common::TEST_PC, &m1, &m2); println!(" add = {} (exp. {})", m_he_a, m_pl_a); println!(" sub = {} (exp. {})", m_he_s, m_pl_s); // compare results assert_eq!(m_he_a, m_pl_a); assert_eq!(m_he_s, m_pl_s); } } // ----------------------------------------------------------------------------- // Aux Functions /// Generation of ciphertexts with left/right triv zeros fn t_gen_ct_with_triv_zeros( ltriv: usize, ct_len: usize, rtriv: usize, mode: EncrVsTriv, ) -> (Vec, ParmCiphertext) { // right triv zeros let mut m_vec = vec![0; rtriv]; // generate random vector (for inner ciphertext) let mut i_vec = gen_rand_vec(ct_len); // left triv zeros let mut l_vec = vec![0; ltriv]; // stick ciphertext together let mut c = ParmCiphertext::triv(rtriv, &common::TEST_PC); let mut ci = encrypt_with_mode(&i_vec, mode); c.append(&mut ci); let mut cl = ParmCiphertext::triv(ltriv, &common::TEST_PC); c.append(&mut cl); // stick plaintext together m_vec.append(&mut i_vec); m_vec.append(&mut l_vec); (m_vec, c) } // ############################################################################# //~ #[test] //~ fn add_cc_1() { //~ // ================================= //~ // test : addition of two elements x and y such as x and y generated randomly //~ // { wlen } //~ // x : |0|0|.. -|-|-|-|1|1|0|1 //~ // y : 0|0|0|..|-|1|0|0|1|0|1 //~ //================================== //~ for _i in 0..10 { //~ let mut rng = rand::thread_rng(); //~ let x_len = rng.gen_range(6..32); //~ let x_wlen = rng.gen_range(4..x_len); //~ let x_triv_len = rng.gen_range(2..x_wlen); //~ let y_len = rng.gen_range(6..32); //~ let y_wlen = rng.gen_range(4..y_len); //~ let y_triv_len = rng.gen_range(2..y_wlen); //~ add_cc_nz(x_len, x_wlen, x_triv_len, y_len, y_wlen, y_triv_len).unwrap(); //~ } //~ } //~ #[test] //~ fn add_cc_2() { //~ // ================================= //~ // test : addition of two elements x and y such as : |x|> wlen > |y| //~ // { wlen } //~ // x : |0|0|.. -|-|-|-|1|0|0 //~ // y : 0|0|..|-|1|0|0 //~ //================================== //~ for _i in 0..10 { //~ let mut rng = rand::thread_rng(); //~ let x_len = rng.gen_range(10..32); //~ let x_wlen = rng.gen_range(8..x_len); //~ let x_triv_len = rng.gen_range(2..x_wlen); //~ let y_len = rng.gen_range(6..x_wlen); //~ let y_wlen = rng.gen_range(4..y_len); //~ let y_triv_len = rng.gen_range(2..y_wlen); //~ add_cc(x_len, x_wlen, x_triv_len, y_len, y_wlen, y_triv_len).unwrap(); //~ } //~ } //~ #[test] //~ fn add_cc_3() { //~ // ================================= //~ // Addition corner case 3 : |y| > |x| > wlen //~ // test : addition of two elements x and y such as : |y|> |x| >wlen //~ // { wlen } //~ // x : |0|0|... -|-|-|-|1|0|0 //~ // y : 0|0|0|0|0|-..|-|-|-|1|0|0 //~ //================================== //~ let mut rng = rand::thread_rng(); //~ // generate 10 random ciphertexts for x and y and call add_cc to test them //~ for _i in 0..10 { //~ let x_len = rng.gen_range(8..32); //~ let x_wlen = rng.gen_range(6..x_len); //~ let x_triv_len = rng.gen_range(2..x_wlen); //~ let y_len = rng.gen_range(x_len - 1..32); //~ let y_wlen = rng.gen_range(4..x_wlen); //~ let y_triv_len = rng.gen_range(2..y_wlen); //~ add_cc(x_len, x_wlen, x_triv_len, y_len, y_wlen, y_triv_len).unwrap(); //~ } //~ } //~ #[test] //~ fn add_cc_4() { //~ // ================================= //~ // test : addition of two elements x and y such as : |x|> |y|> wlen //~ // { wlen } //~ // x :|0|0|0|0|0|-|-|-|-|1|0|0 //~ // y : 0|0|-..|-|-|-|1|0|0 //~ //================================== //~ let mut rng = rand::thread_rng(); //~ // generate 10 random ciphertexts for x and y and call add_cc to test them //~ for _i in 0..10 { //~ let x_len = rng.gen_range(10..12); //~ let y_len = rng.gen_range(8..x_len); //~ let y_wlen = rng.gen_range(6..y_len); //~ let x_wlen = rng.gen_range(4..y_wlen); //~ let x_triv_len = rng.gen_range(2..x_wlen); //~ let y_triv_len = rng.gen_range(2..y_wlen); //~ add_cc(x_len, x_wlen, x_triv_len, y_len, y_wlen, y_triv_len).unwrap(); //~ } //~ } //~ #[test] //~ fn add_cc_5() { //~ // ================================= //~ // Addition corner case 4 : |y| > wlen > |x| //~ // test : addition of two elements x and y such as : |y|> wlen > |x| //~ // { wlen } //~ // x : |0|0|-|-|1|0|0|0 //~ // y :|0|0|-...|-|-|-|1|0|1 //~ //================================== //~ let mut rng = rand::thread_rng(); //~ // generate 10 random ciphertexts for x and y and call add_cc to test them //~ for _i in 0..10 { //~ let x_len = rng.gen_range(6..31); //~ let y_len = rng.gen_range(x_len..32); //~ let y_wlen = rng.gen_range(x_len..y_len); //~ let x_wlen = rng.gen_range(3..x_len); //~ let x_triv_len = rng.gen_range(2..x_wlen); //~ let y_triv_len = rng.gen_range(2..y_wlen); //~ add_cc(x_len, x_wlen, x_triv_len, y_len, y_wlen, y_triv_len).unwrap(); //~ } //~ }