diff --git a/README.md b/README.md index a58d409..7cea5d4 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Implementations from scratch done while studying some FHE papers; do not use in This example shows usage of TFHE, but the idea is that the same interface would work for using CKKS & BFV, the only thing to be changed would be the parameters -and the line `type S = TWLE` to use `CKKS` or `BFV`. +and the usage of `TLWE` by `CKKS` or `BFV`. ```rust let param = Param { @@ -31,7 +31,7 @@ let msg_dist = Uniform::new(0_u64, param.t); let (sk, pk) = TLWE::new_key(&mut rng, ¶m)?; -// get two random msgs in Z_t +// get three random msgs in Rt let m1 = Rq::rand_u64(&mut rng, msg_dist, ¶m.pt())?; let m2 = Rq::rand_u64(&mut rng, msg_dist, ¶m.pt())?; let m3 = Rq::rand_u64(&mut rng, msg_dist, ¶m.pt())?; @@ -39,8 +39,9 @@ let m3 = Rq::rand_u64(&mut rng, msg_dist, ¶m.pt())?; // encode the msgs into the plaintext space let p1 = TLWE::encode(¶m, &m1); // plaintext let p2 = TLWE::encode(¶m, &m2); // plaintext -let c3_const: T64 = T64(m3.coeffs()[0].v); // encode it as constant +let c3_const = TLWE::new_const(¶m, &m3); // as constant/public value +// encrypt p1 and m2 let c1 = TLWE::encrypt(&mut rng, ¶m, &pk, &p1)?; let c2 = TLWE::encrypt(&mut rng, ¶m, &pk, &p2)?; diff --git a/tfhe/src/tglwe.rs b/tfhe/src/tglwe.rs index 6328a2c..ae4c97b 100644 --- a/tfhe/src/tglwe.rs +++ b/tfhe/src/tglwe.rs @@ -61,6 +61,16 @@ impl TGLWE { let pt = pt.mul_div_round(p, u64::MAX); Rq::from_vec_u64(¶m.pt(), pt.coeffs().iter().map(|c| c.0).collect()) } + /// encodes the given message as a TGLWE constant/public value, for using it + /// in ct-pt-multiplication. + pub fn new_const(param: &Param, m: &Rq) -> Tn { + debug_assert_eq!(param.t, m.param.q); + // don't scale up m, set the Tn element directly from m's coefficients + Tn { + param: param.ring, + coeffs: m.coeffs().iter().map(|c_i| T64(c_i.v)).collect(), + } + } /// encrypts with the given SecretKey (instead of PublicKey) pub fn encrypt_s(rng: impl Rng, param: &Param, sk: &SecretKey, p: &Tn) -> Result { @@ -310,11 +320,7 @@ mod tests { let m1 = Rq::rand_u64(&mut rng, msg_dist, ¶m.pt())?; let m2 = Rq::rand_u64(&mut rng, msg_dist, ¶m.pt())?; let p1: Tn = TGLWE::encode(¶m, &m1); - // don't scale up p2, set it directly from m2 - let p2: Tn = Tn { - param: param.ring, - coeffs: m2.coeffs().iter().map(|c_i| T64(c_i.v)).collect(), - }; + let p2: Tn = TGLWE::new_const(¶m, &m2); // as constant/public value let c1 = TGLWE::encrypt(&mut rng, ¶m, &pk, &p1)?; diff --git a/tfhe/src/tlwe.rs b/tfhe/src/tlwe.rs index 6a4f92f..dac81ac 100644 --- a/tfhe/src/tlwe.rs +++ b/tfhe/src/tlwe.rs @@ -61,6 +61,12 @@ impl TLWE { let p = p.mul_div_round(param.t, u64::MAX); Rq::from_vec_u64(¶m.pt(), p.coeffs().iter().map(|c| c.0).collect()) } + /// encodes the given message as a TLWE constant/public value, for using it + /// in ct-pt-multiplication. + pub fn new_const(param: &Param, m: &Rq) -> T64 { + debug_assert_eq!(param.t, m.param.q); + T64(m.coeffs()[0].v) + } // encrypts with the given SecretKey (instead of PublicKey) pub fn encrypt_s(rng: impl Rng, param: &Param, sk: &SecretKey, p: &T64) -> Result { @@ -400,8 +406,7 @@ mod tests { let m1 = Rq::rand_u64(&mut rng, msg_dist, ¶m.pt())?; let m2 = Rq::rand_u64(&mut rng, msg_dist, ¶m.pt())?; let p1: T64 = TLWE::encode(¶m, &m1); - // don't scale up p2, set it directly from m2 - let p2: T64 = T64(m2.coeffs()[0].v); + let p2: T64 = TLWE::new_const(¶m, &m2); // as constant/public value let c1 = TLWE::encrypt(&mut rng, ¶m, &pk, &p1)?;