add example
Janmajaya Mall janmajayamall@protonmail.com
Tue, 11 Jun 2024 17:31:01 +0530
7 files changed,
98 insertions(+),
16 deletions(-)
A
examples/fheuint8.rs
@@ -0,0 +1,71 @@
+use bin_rs::*; +use itertools::Itertools; +use rand::{thread_rng, RngCore}; + +fn plain_circuit(a: u8, b: u8, c: u8) -> u8 { + (a + b) * c +} + +fn fhe_circuit(fhe_a: &FheUint8, fhe_b: &FheUint8, fhe_c: &FheUint8) -> FheUint8 { + &(fhe_a + fhe_b) * fhe_c +} + +fn main() { + set_parameter_set(ParameterSelector::MultiPartyLessThan16); + let no_of_parties = 2; + let client_keys = (0..no_of_parties) + .into_iter() + .map(|_| gen_client_key()) + .collect_vec(); + + // set Multi-Party seed + let mut seed = [0u8; 32]; + thread_rng().fill_bytes(&mut seed); + set_mp_seed(seed); + + // multi-party key gen round 1 + let pk_shares = client_keys + .iter() + .map(|k| gen_mp_keys_phase1(k)) + .collect_vec(); + + // create public key + let public_key = aggregate_public_key_shares(&pk_shares); + + // multi-party key gen round 2 + let server_key_shares = client_keys + .iter() + .map(|k| gen_mp_keys_phase2(k, &public_key)) + .collect_vec(); + + // server aggregates server key shares and sets it + let server_key = aggregate_server_key_shares(&server_key_shares); + server_key.set_server_key(); + + // private inputs + let a = 4u8; + let b = 6u8; + let c = 128u8; + let fhe_a = public_key.encrypt(&a); + let fhe_b = public_key.encrypt(&b); + let fhe_c = public_key.encrypt(&c); + + // fhe evaluation + let now = std::time::Instant::now(); + let fhe_out = fhe_circuit(&fhe_a, &fhe_b, &fhe_c); + println!("Circuit time: {:?}", now.elapsed()); + + // plain evaluation + let out = plain_circuit(a, b, c); + + // generate decryption shares to decrypt ciphertext fhe_out + let decryption_shares = client_keys + .iter() + .map(|k| k.gen_decryption_share(&fhe_out)) + .collect_vec(); + + // decrypt fhe_out using decryption shares + let got_out = client_keys[0].aggregate_decryption_shares(&fhe_out, &decryption_shares); + + assert_eq!(got_out, out); +}
M
src/bool/mod.rs
→
src/bool/mod.rs
@@ -26,8 +26,16 @@ static BOOL_SERVER_KEY: OnceLock<ShoupServerKeyEvaluationDomain<Vec<Vec<u64>>>> = OnceLock::new();
static MULTI_PARTY_CRS: OnceLock<MultiPartyCrs<[u8; 32]>> = OnceLock::new(); -pub fn set_parameter_set(parameter: &BoolParameters<u64>) { - BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(parameter.clone()))); +pub enum ParameterSelector { + MultiPartyLessThan16, +} + +pub fn set_parameter_set(select: ParameterSelector) { + match select { + ParameterSelector::MultiPartyLessThan16 => { + BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(SMALL_MP_BOOL_PARAMS))); + } + } } pub fn set_mp_seed(seed: [u8; 32]) {
M
src/bool/parameters.rs
→
src/bool/parameters.rs
@@ -3,7 +3,7 @@
use crate::{backend::Modulus, decomposer::Decomposer}; #[derive(Clone, PartialEq)] -pub(crate) struct BoolParameters<El> { +pub struct BoolParameters<El> { rlwe_q: CiphertextModulus<El>, lwe_q: CiphertextModulus<El>, br_q: usize,@@ -181,7 +181,7 @@ #[derive(Clone, Copy, PartialEq, Debug)]
/// T equals modulus when modulus is non-native. Otherwise T equals 0. bool is /// true when modulus is native, false otherwise. -pub(crate) struct CiphertextModulus<T>(T, bool); +pub struct CiphertextModulus<T>(T, bool); impl<T: ConstZero> CiphertextModulus<T> { const fn new_native() -> Self {
M
src/lib.rs
→
src/lib.rs
@@ -23,8 +23,13 @@
pub use backend::{ ArithmeticLazyOps, ArithmeticOps, ModInit, ModularOpsU64, ShoupMatrixFMA, VectorOps, }; +pub use bool::{ + aggregate_public_key_shares, aggregate_server_key_shares, gen_client_key, gen_mp_keys_phase1, + gen_mp_keys_phase2, set_mp_seed, set_parameter_set, ParameterSelector, +}; pub use decomposer::{Decomposer, DecomposerIter, DefaultDecomposer}; pub use ntt::{Ntt, NttBackendU64, NttInit}; +pub use shortint::FheUint8; pub trait Matrix: AsRef<[Self::R]> { type MatElement;@@ -165,15 +170,15 @@ vec![T::zero(); col]
} } -trait Encryptor<M: ?Sized, C> { +pub trait Encryptor<M: ?Sized, C> { fn encrypt(&self, m: &M) -> C; } -trait Decryptor<M, C> { +pub trait Decryptor<M, C> { fn decrypt(&self, c: &C) -> M; } -trait MultiPartyDecryptor<M, C> { +pub trait MultiPartyDecryptor<M, C> { type DecryptionShare; fn gen_decryption_share(&self, c: &C) -> Self::DecryptionShare;
M
src/random.rs
→
src/random.rs
@@ -12,7 +12,7 @@ thread_local! {
pub(crate) static DEFAULT_RNG: RefCell<DefaultSecureRng> = RefCell::new(DefaultSecureRng::new_seeded([0u8;32])); } -pub(crate) trait NewWithSeed { +pub trait NewWithSeed { type Seed; fn new_with_seed(seed: Self::Seed) -> Self; }@@ -59,7 +59,7 @@ /// represented in the modulus.
fn random_fill(&mut self, modulus: &P, container: &mut M); } -pub(crate) struct DefaultSecureRng { +pub struct DefaultSecureRng { rng: ChaCha8Rng, }
M
src/shortint/mod.rs
→
src/shortint/mod.rs
@@ -8,7 +8,7 @@
mod ops; mod types; -type FheUint8 = types::FheUint8<Vec<u64>>; +pub type FheUint8 = types::FheUint8<Vec<u64>>; impl Encryptor<u8, FheUint8> for ClientKey { fn encrypt(&self, m: &u8) -> FheUint8 {@@ -308,9 +308,7 @@
use crate::{ bool::{ aggregate_public_key_shares, aggregate_server_key_shares, gen_client_key, gen_keys, - gen_mp_keys_phase1, gen_mp_keys_phase2, - parameters::{MP_BOOL_PARAMS, SMALL_MP_BOOL_PARAMS, SP_BOOL_PARAMS}, - set_mp_seed, set_parameter_set, + gen_mp_keys_phase1, gen_mp_keys_phase2, set_mp_seed, set_parameter_set, }, shortint::types::FheUint8, Decryptor, Encryptor, MultiPartyDecryptor,@@ -318,7 +316,7 @@ };
#[test] fn all_uint8_apis() { - set_parameter_set(&SP_BOOL_PARAMS); + set_parameter_set(crate::ParameterSelector::MultiPartyLessThan16); let (ck, sk) = gen_keys(); sk.set_server_key();@@ -466,7 +464,7 @@ }
#[test] fn fheuint8_test_multi_party() { - set_parameter_set(&SMALL_MP_BOOL_PARAMS); + set_parameter_set(crate::ParameterSelector::MultiPartyLessThan16); set_mp_seed([0; 32]); let parties = 8;
M
src/shortint/types.rs
→
src/shortint/types.rs
@@ -1,5 +1,5 @@
#[derive(Clone)] -pub(super) struct FheUint8<C> { +pub struct FheUint8<C> { pub(super) data: Vec<C>, }