#[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 #[test] /// Maximum of encrypted sub-samples only, aligned lengths. fn t_max_non_triv_aligned() { println!("Non-Triv Aligned ..."); t_impl_max_with_mode(EncrVsTriv::ENCR, true); } #[test] /// Maximum of encrypted sub-samples only, different lengths. fn t_max_non_triv_difflen() { println!("Non-Triv Misaligned ..."); t_impl_max_with_mode(EncrVsTriv::ENCR, false); } #[test] /// Maximum of trivial sub-samples only, aligned lengths. fn t_max_all_triv_aligned() { println!("All-Triv Aligned ..."); t_impl_max_with_mode(EncrVsTriv::TRIV, true); } #[test] /// Maximum of trivial sub-samples only, different lengths. fn t_max_all_triv_difflen() { println!("All-Triv Misaligned ..."); t_impl_max_with_mode(EncrVsTriv::TRIV, false); } #[test] /// Maximum of mixed sub-samples, aligned lengths. fn t_max_some_triv_aligned() { println!("Mixed Aligned ..."); t_impl_max_with_mode(EncrVsTriv::ENCRTRIV, true); } #[test] /// Maximum of mixed sub-samples, different lengths. fn t_max_some_triv_difflen() { println!("Mixed Misaligned ..."); t_impl_max_with_mode(EncrVsTriv::ENCRTRIV, false); } // Special #[test] /// Maximum of two empty samples fn t_max_both_empty() { println!("Both Empty ..."); // encrypt -> homomorphic eval -> decrypt (in plain: 0) let c1 = ParmCiphertext::empty(); let c2 = ParmCiphertext::empty(); let c_he = ParmArithmetics::max(&common::TEST_PC, &c1, &c2); let m_he = common::TEST_PU.decrypt(&c_he).expect("ParmesanUserovo::decrypt failed."); let m_pl = 0; println!(" max = {} (exp. {})", m_he, m_pl); // compare results assert_eq!(m_he, m_pl); } #[test] /// Maximum of empty and non-empty sample fn t_max_empty_nonempty() { println!("Empty & Non-Empty Mixed ..."); // generate random vector(s) let m1_vec: Vec = Vec::new(); let m2_vec = gen_rand_vec(common::TESTS_BITLEN_MAX); // 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 = {} ({}-bit: {:?})\n m2 = {} ({}-bit: {:?})", m1, 0, m1_vec, m2, common::TESTS_BITLEN_MAX, m2_vec); // encrypt -> homomorphic eval -> decrypt let c1 = encrypt_with_mode(&m1_vec, EncrVsTriv::ENCRTRIV); let c2 = encrypt_with_mode(&m2_vec, EncrVsTriv::ENCRTRIV); let c_he = ParmArithmetics::max(&common::TEST_PC, &c1, &c2); let m_he = common::TEST_PU.decrypt(&c_he).expect("ParmesanUserovo::decrypt failed."); // plain eval let m_pl = ParmArithmetics::max(&common::TEST_PC, &m1, &m2); println!(" max = {} (exp. {})", m_he, m_pl); // compare results assert_eq!(m_he, m_pl); } #[test] fn t_max_fail() { println!("Failing cases ..."); // init failing vector(s) (set 1) //~ // let m1_vec = vec![-1, 0, -1, 0, -1, -1]; //~ // let m2_vec = vec![1, 1, 1, 1, 0, 1, -1]; //~ let m1_vec = vec![-1, -1, 1, 0]; //~ let m2_vec = vec![0, 1, 0]; // init failing vector(s) (set 2) let m1_vec = vec![-1, 0, -1]; let m2_vec = vec![0, 0, 1, 1, -1]; // 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 = {} ({}-bit: {:?})\n m2 = {} ({}-bit: {:?})", m1, 0, m1_vec, m2, common::TESTS_BITLEN_MAX, m2_vec); // encrypt -> homomorphic eval -> decrypt let c1 = encrypt_with_mode(&m1_vec, EncrVsTriv::ENCRTRIV); let c2 = encrypt_with_mode(&m2_vec, EncrVsTriv::ENCRTRIV); let c_he = ParmArithmetics::max(&common::TEST_PC, &c1, &c2); let m_he = common::TEST_PU.decrypt(&c_he).expect("ParmesanUserovo::decrypt failed."); // plain eval let m_pl = ParmArithmetics::max(&common::TEST_PC, &m1, &m2); println!(" max = {} (exp. {})", m_he, m_pl); // compare results assert_eq!(m_he, m_pl); } // ----------------------------------------------------------------------------- // Test Implementations /// Implementation for three variants of vector to be evaluated. fn t_impl_max_with_mode( mode: EncrVsTriv, aligned: bool, ) { // for mis-aligned length generation let mut rng = rand::thread_rng(); for _ in 0..common::TESTS_REPEAT_MAX { // generate random vector(s) let bl1 = if aligned {common::TESTS_BITLEN_MAX} else {rng.gen_range(0..=common::TESTS_BITLEN_MAX)}; let bl2 = if aligned {common::TESTS_BITLEN_MAX} else {rng.gen_range(0..=common::TESTS_BITLEN_MAX)}; let m1_vec = gen_rand_vec(bl1); let m2_vec = gen_rand_vec(bl2); // 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 = {} ({}-bit: {:?})\n m2 = {} ({}-bit: {:?})", m1, bl1, m1_vec, m2, bl2, m2_vec); // encrypt -> homomorphic eval -> decrypt let c1 = encrypt_with_mode(&m1_vec, mode); let c2 = encrypt_with_mode(&m2_vec, mode); let c_he = ParmArithmetics::max(&common::TEST_PC, &c1, &c2); let m_he = common::TEST_PU.decrypt(&c_he).expect("ParmesanUserovo::decrypt failed."); // plain eval let m_pl = ParmArithmetics::max(&common::TEST_PC, &m1, &m2); println!(" max = {} (exp. {})", m_he, m_pl); // compare results assert_eq!(m_he, m_pl); } }