mirror of
https://github.com/arnaucube/fhe-study.git
synced 2026-01-24 04:33:52 +01:00
ckks: get rid of constant generics (reason in two commits ago)
This commit is contained in:
@@ -16,6 +16,14 @@ use arith::{Ring, Rq, R};
|
|||||||
// sigma=3.2 from: https://eprint.iacr.org/2022/162.pdf page 5
|
// sigma=3.2 from: https://eprint.iacr.org/2022/162.pdf page 5
|
||||||
const ERR_SIGMA: f64 = 3.2;
|
const ERR_SIGMA: f64 = 3.2;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct Params {
|
||||||
|
q: u64,
|
||||||
|
n: usize,
|
||||||
|
t: u64,
|
||||||
|
p: u64,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SecretKey(Rq);
|
pub struct SecretKey(Rq);
|
||||||
|
|
||||||
@@ -92,12 +100,6 @@ impl ops::Add<&Rq> for &RLWE {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Params {
|
|
||||||
q: u64,
|
|
||||||
n: usize,
|
|
||||||
t: u64,
|
|
||||||
p: u64,
|
|
||||||
}
|
|
||||||
pub struct BFV {}
|
pub struct BFV {}
|
||||||
|
|
||||||
impl BFV {
|
impl BFV {
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ use anyhow::Result;
|
|||||||
use arith::{Matrix, Ring, Rq, C, R};
|
use arith::{Matrix, Ring, Rq, C, R};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SecretKey<const Q: u64, const N: usize>(Rq<Q, N>);
|
pub struct SecretKey(Rq);
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PublicKey<const Q: u64, const N: usize>(Rq<Q, N>, Rq<Q, N>);
|
pub struct PublicKey(Rq, Rq);
|
||||||
|
|
||||||
pub struct Encoder<const Q: u64, const N: usize> {
|
pub struct Encoder {
|
||||||
|
n: usize,
|
||||||
scale_factor: C<f64>, // Δ (delta)
|
scale_factor: C<f64>, // Δ (delta)
|
||||||
primitive: C<f64>,
|
primitive: C<f64>,
|
||||||
basis: Matrix<C<f64>>,
|
basis: Matrix<C<f64>>,
|
||||||
@@ -34,13 +35,14 @@ fn vandermonde(n: usize, w: C<f64>) -> Matrix<C<f64>> {
|
|||||||
}
|
}
|
||||||
Matrix::<C<f64>>(v)
|
Matrix::<C<f64>>(v)
|
||||||
}
|
}
|
||||||
impl<const Q: u64, const N: usize> Encoder<Q, N> {
|
impl Encoder {
|
||||||
pub fn new(scale_factor: C<f64>) -> Self {
|
pub fn new(n: usize, scale_factor: C<f64>) -> Self {
|
||||||
let primitive: C<f64> = primitive_root_of_unity(2 * N);
|
let primitive: C<f64> = primitive_root_of_unity(2 * n);
|
||||||
let basis = vandermonde(N, primitive);
|
let basis = vandermonde(n, primitive);
|
||||||
let basis_t = basis.transpose();
|
let basis_t = basis.transpose();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
n,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
primitive,
|
primitive,
|
||||||
basis,
|
basis,
|
||||||
@@ -52,7 +54,7 @@ impl<const Q: u64, const N: usize> Encoder<Q, N> {
|
|||||||
/// from $\mathbb{C}^{N/2} \longrightarrow \mathbb{Z_q}[X]/(X^N +1) = R$
|
/// from $\mathbb{C}^{N/2} \longrightarrow \mathbb{Z_q}[X]/(X^N +1) = R$
|
||||||
// TODO use alg.1 from 2018-1043,
|
// TODO use alg.1 from 2018-1043,
|
||||||
// or as in 2018-1073: $f(x) = 1N (U^T.conj() m + U^T m.conj())$
|
// or as in 2018-1073: $f(x) = 1N (U^T.conj() m + U^T m.conj())$
|
||||||
pub fn encode(&self, z: &[C<f64>]) -> Result<R<N>> {
|
pub fn encode(&self, z: &[C<f64>]) -> Result<R> {
|
||||||
// $pi^{-1}: \mathbb{C}^{N/2} \longrightarrow \mathbb{H}$
|
// $pi^{-1}: \mathbb{C}^{N/2} \longrightarrow \mathbb{H}$
|
||||||
let expanded = self.pi_inv(z);
|
let expanded = self.pi_inv(z);
|
||||||
|
|
||||||
@@ -93,10 +95,10 @@ impl<const Q: u64, const N: usize> Encoder<Q, N> {
|
|||||||
|
|
||||||
// TMP: naive round, maybe do gaussian
|
// TMP: naive round, maybe do gaussian
|
||||||
let coeffs = r.iter().map(|e| e.re.round() as i64).collect::<Vec<i64>>();
|
let coeffs = r.iter().map(|e| e.re.round() as i64).collect::<Vec<i64>>();
|
||||||
Ok(R::from_vec(coeffs))
|
Ok(R::from_vec(self.n, coeffs))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode(&self, p: &R<N>) -> Result<Vec<C<f64>>> {
|
pub fn decode(&self, p: &R) -> Result<Vec<C<f64>>> {
|
||||||
let p: Vec<C<f64>> = p
|
let p: Vec<C<f64>> = p
|
||||||
.coeffs()
|
.coeffs()
|
||||||
.iter()
|
.iter()
|
||||||
@@ -110,7 +112,7 @@ impl<const Q: u64, const N: usize> Encoder<Q, N> {
|
|||||||
|
|
||||||
/// pi: \mathbb{H} \longrightarrow \mathbb{C}^{N/2}
|
/// pi: \mathbb{H} \longrightarrow \mathbb{C}^{N/2}
|
||||||
fn pi(&self, z: &[C<f64>]) -> Vec<C<f64>> {
|
fn pi(&self, z: &[C<f64>]) -> Vec<C<f64>> {
|
||||||
z[..N / 2].to_vec()
|
z[..self.n / 2].to_vec()
|
||||||
}
|
}
|
||||||
/// pi^{-1}: \mathbb{C}^{N/2} \longrightarrow \mathbb{H}
|
/// pi^{-1}: \mathbb{C}^{N/2} \longrightarrow \mathbb{H}
|
||||||
fn pi_inv(&self, z: &[C<f64>]) -> Vec<C<f64>> {
|
fn pi_inv(&self, z: &[C<f64>]) -> Vec<C<f64>> {
|
||||||
@@ -154,6 +156,7 @@ mod tests {
|
|||||||
fn test_encode_decode() -> Result<()> {
|
fn test_encode_decode() -> Result<()> {
|
||||||
const Q: u64 = 1024;
|
const Q: u64 = 1024;
|
||||||
const N: usize = 32;
|
const N: usize = 32;
|
||||||
|
let n: usize = 32;
|
||||||
|
|
||||||
let T = 128; // WIP
|
let T = 128; // WIP
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
@@ -166,9 +169,9 @@ mod tests {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let delta = C::<f64>::new(64.0, 0.0); // delta = scaling factor
|
let delta = C::<f64>::new(64.0, 0.0); // delta = scaling factor
|
||||||
let encoder = Encoder::<Q, N>::new(delta);
|
let encoder = Encoder::new(n, delta);
|
||||||
|
|
||||||
let m: R<N> = encoder.encode(&z)?; // polynomial (encoded vec) \in R
|
let m: R = encoder.encode(&z)?; // polynomial (encoded vec) \in R
|
||||||
|
|
||||||
let z_decoded = encoder.decode(&m)?;
|
let z_decoded = encoder.decode(&m)?;
|
||||||
|
|
||||||
|
|||||||
170
ckks/src/lib.rs
170
ckks/src/lib.rs
@@ -18,35 +18,48 @@ pub use encoder::Encoder;
|
|||||||
// sigma=3.2 from: https://eprint.iacr.org/2016/421.pdf page 17
|
// sigma=3.2 from: https://eprint.iacr.org/2016/421.pdf page 17
|
||||||
const ERR_SIGMA: f64 = 3.2;
|
const ERR_SIGMA: f64 = 3.2;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct PublicKey<const Q: u64, const N: usize>(Rq<Q, N>, Rq<Q, N>);
|
pub struct Params {
|
||||||
|
q: u64,
|
||||||
pub struct SecretKey<const Q: u64, const N: usize>(Rq<Q, N>);
|
n: usize,
|
||||||
|
t: u64,
|
||||||
pub struct CKKS<const Q: u64, const N: usize> {
|
|
||||||
encoder: Encoder<Q, N>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const Q: u64, const N: usize> CKKS<Q, N> {
|
#[derive(Debug)]
|
||||||
pub fn new(delta: C<f64>) -> Self {
|
pub struct PublicKey(Rq, Rq);
|
||||||
let encoder = Encoder::<Q, N>::new(delta);
|
|
||||||
Self { encoder }
|
pub struct SecretKey(Rq);
|
||||||
|
|
||||||
|
pub struct CKKS {
|
||||||
|
params: Params,
|
||||||
|
encoder: Encoder,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CKKS {
|
||||||
|
pub fn new(params: &Params, delta: C<f64>) -> Self {
|
||||||
|
let encoder = Encoder::new(params.n, delta);
|
||||||
|
Self {
|
||||||
|
params: params.clone(),
|
||||||
|
encoder,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// generate a new key pair (privK, pubK)
|
/// generate a new key pair (privK, pubK)
|
||||||
pub fn new_key(&self, mut rng: impl Rng) -> Result<(SecretKey<Q, N>, PublicKey<Q, N>)> {
|
pub fn new_key(&self, mut rng: impl Rng) -> Result<(SecretKey, PublicKey)> {
|
||||||
|
let params = &self.params;
|
||||||
|
|
||||||
let Xi_key = Uniform::new(-1_f64, 1_f64);
|
let Xi_key = Uniform::new(-1_f64, 1_f64);
|
||||||
let Xi_err = Normal::new(0_f64, ERR_SIGMA)?;
|
let Xi_err = Normal::new(0_f64, ERR_SIGMA)?;
|
||||||
|
|
||||||
let e = Rq::<Q, N>::rand_f64(&mut rng, Xi_err)?;
|
let e = Rq::rand_f64(&mut rng, Xi_err, params.q, params.n)?;
|
||||||
|
|
||||||
let mut s = Rq::<Q, N>::rand_f64(&mut rng, Xi_key)?;
|
let mut s = Rq::rand_f64(&mut rng, Xi_key, params.q, params.n)?;
|
||||||
// since s is going to be multiplied by other Rq elements, already
|
// since s is going to be multiplied by other Rq elements, already
|
||||||
// compute its NTT
|
// compute its NTT
|
||||||
s.compute_evals();
|
s.compute_evals();
|
||||||
|
|
||||||
let a = Rq::<Q, N>::rand_f64(&mut rng, Xi_key)?;
|
let a = Rq::rand_f64(&mut rng, Xi_key, params.q, params.n)?;
|
||||||
|
|
||||||
let pk: PublicKey<Q, N> = PublicKey((&(-a) * &s) + e, a.clone());
|
let pk: PublicKey = PublicKey((&(-a.clone()) * &s) + e, a.clone()); // TODO rm clones
|
||||||
Ok((SecretKey(s), pk))
|
Ok((SecretKey(s), pk))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,64 +67,54 @@ impl<const Q: u64, const N: usize> CKKS<Q, N> {
|
|||||||
fn encrypt(
|
fn encrypt(
|
||||||
&self, // TODO maybe rm?
|
&self, // TODO maybe rm?
|
||||||
mut rng: impl Rng,
|
mut rng: impl Rng,
|
||||||
pk: &PublicKey<Q, N>,
|
pk: &PublicKey,
|
||||||
m: &R<N>,
|
m: &R,
|
||||||
) -> Result<(Rq<Q, N>, Rq<Q, N>)> {
|
) -> Result<(Rq, Rq)> {
|
||||||
|
let params = self.params;
|
||||||
let Xi_key = Uniform::new(-1_f64, 1_f64);
|
let Xi_key = Uniform::new(-1_f64, 1_f64);
|
||||||
let Xi_err = Normal::new(0_f64, ERR_SIGMA)?;
|
let Xi_err = Normal::new(0_f64, ERR_SIGMA)?;
|
||||||
|
|
||||||
let e_0 = Rq::<Q, N>::rand_f64(&mut rng, Xi_err)?;
|
let e_0 = Rq::rand_f64(&mut rng, Xi_err, params.q, params.n)?;
|
||||||
let e_1 = Rq::<Q, N>::rand_f64(&mut rng, Xi_err)?;
|
let e_1 = Rq::rand_f64(&mut rng, Xi_err, params.q, params.n)?;
|
||||||
|
|
||||||
let v = Rq::<Q, N>::rand_f64(&mut rng, Xi_key)?;
|
let v = Rq::rand_f64(&mut rng, Xi_key, params.q, params.n)?;
|
||||||
|
|
||||||
let m: Rq<Q, N> = Rq::<Q, N>::from(*m);
|
// let m: Rq = Rq::from(*m);
|
||||||
|
let m: Rq = m.clone().to_rq(params.q); // TODO rm clone
|
||||||
|
|
||||||
Ok((m + e_0 + v * pk.0.clone(), v * pk.1.clone() + e_1))
|
Ok((m + e_0 + &v * &pk.0.clone(), &v * &pk.1 + e_1))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrypt(
|
fn decrypt(
|
||||||
&self, // TODO maybe rm?
|
&self, // TODO maybe rm?
|
||||||
sk: &SecretKey<Q, N>,
|
sk: &SecretKey,
|
||||||
c: (Rq<Q, N>, Rq<Q, N>),
|
c: (Rq, Rq),
|
||||||
) -> Result<R<N>> {
|
) -> Result<R> {
|
||||||
let m = c.0.clone() + c.1 * sk.0;
|
let m = c.0.clone() + &c.1 * &sk.0;
|
||||||
Ok(m.mod_centered_q())
|
Ok(m.mod_centered_q())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode_and_encrypt(
|
pub fn encode_and_encrypt(
|
||||||
&self,
|
&self,
|
||||||
mut rng: impl Rng,
|
mut rng: impl Rng,
|
||||||
pk: &PublicKey<Q, N>,
|
pk: &PublicKey,
|
||||||
z: &[C<f64>],
|
z: &[C<f64>],
|
||||||
) -> Result<(Rq<Q, N>, Rq<Q, N>)> {
|
) -> Result<(Rq, Rq)> {
|
||||||
let m: R<N> = self.encoder.encode(&z)?; // polynomial (encoded vec) \in R
|
let m: R = self.encoder.encode(&z)?; // polynomial (encoded vec) \in R
|
||||||
|
|
||||||
self.encrypt(&mut rng, pk, &m)
|
self.encrypt(&mut rng, pk, &m)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrypt_and_decode(
|
pub fn decrypt_and_decode(&self, sk: SecretKey, c: (Rq, Rq)) -> Result<Vec<C<f64>>> {
|
||||||
&self,
|
|
||||||
sk: SecretKey<Q, N>,
|
|
||||||
c: (Rq<Q, N>, Rq<Q, N>),
|
|
||||||
) -> Result<Vec<C<f64>>> {
|
|
||||||
let d = self.decrypt(&sk, c)?;
|
let d = self.decrypt(&sk, c)?;
|
||||||
|
|
||||||
self.encoder.decode(&d)
|
self.encoder.decode(&d)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(
|
pub fn add(&self, c0: &(Rq, Rq), c1: &(Rq, Rq)) -> Result<(Rq, Rq)> {
|
||||||
&self,
|
|
||||||
c0: &(Rq<Q, N>, Rq<Q, N>),
|
|
||||||
c1: &(Rq<Q, N>, Rq<Q, N>),
|
|
||||||
) -> Result<(Rq<Q, N>, Rq<Q, N>)> {
|
|
||||||
Ok((&c0.0 + &c1.0, &c0.1 + &c1.1))
|
Ok((&c0.0 + &c1.0, &c0.1 + &c1.1))
|
||||||
}
|
}
|
||||||
pub fn sub(
|
pub fn sub(&self, c0: &(Rq, Rq), c1: &(Rq, Rq)) -> Result<(Rq, Rq)> {
|
||||||
&self,
|
|
||||||
c0: &(Rq<Q, N>, Rq<Q, N>),
|
|
||||||
c1: &(Rq<Q, N>, Rq<Q, N>),
|
|
||||||
) -> Result<(Rq<Q, N>, Rq<Q, N>)> {
|
|
||||||
Ok((&c0.0 - &c1.0, &c0.1 + &c1.1))
|
Ok((&c0.0 - &c1.0, &c0.1 + &c1.1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,21 +125,22 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_encrypt_decrypt() -> Result<()> {
|
fn test_encrypt_decrypt() -> Result<()> {
|
||||||
const Q: u64 = 2u64.pow(16) + 1;
|
let q: u64 = 2u64.pow(16) + 1;
|
||||||
const N: usize = 32;
|
let n: usize = 32;
|
||||||
const T: u64 = 50;
|
let t: u64 = 50;
|
||||||
|
let params = Params { q, n, t };
|
||||||
let scale_factor_u64 = 512_u64; // delta
|
let scale_factor_u64 = 512_u64; // delta
|
||||||
let scale_factor = C::<f64>::new(scale_factor_u64 as f64, 0.0); // delta
|
let scale_factor = C::<f64>::new(scale_factor_u64 as f64, 0.0); // delta
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
let ckks = CKKS::<Q, N>::new(scale_factor);
|
let ckks = CKKS::new(¶ms, scale_factor);
|
||||||
|
|
||||||
let (sk, pk) = ckks.new_key(&mut rng)?;
|
let (sk, pk) = ckks.new_key(&mut rng)?;
|
||||||
|
|
||||||
let m_raw: R<N> = Rq::<Q, N>::rand_f64(&mut rng, Uniform::new(0_f64, T as f64))?.to_r();
|
let m_raw: R = Rq::rand_f64(&mut rng, Uniform::new(0_f64, t as f64), q, n)?.to_r();
|
||||||
let m = m_raw * scale_factor_u64;
|
let m = &m_raw * &scale_factor_u64;
|
||||||
|
|
||||||
let ct = ckks.encrypt(&mut rng, &pk, &m)?;
|
let ct = ckks.encrypt(&mut rng, &pk, &m)?;
|
||||||
let m_decrypted = ckks.decrypt(&sk, ct)?;
|
let m_decrypted = ckks.decrypt(&sk, ct)?;
|
||||||
@@ -146,8 +150,9 @@ mod tests {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|e| (*e as f64 / (scale_factor_u64 as f64)).round() as u64)
|
.map(|e| (*e as f64 / (scale_factor_u64 as f64)).round() as u64)
|
||||||
.collect();
|
.collect();
|
||||||
let m_decrypted = Rq::<Q, N>::from_vec_u64(m_decrypted);
|
let m_decrypted = Rq::from_vec_u64(q, n, m_decrypted);
|
||||||
assert_eq!(m_decrypted, Rq::<Q, N>::from(m_raw));
|
// assert_eq!(m_decrypted, Rq::from(m_raw));
|
||||||
|
assert_eq!(m_decrypted, m_raw.to_rq(q));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -155,21 +160,22 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_encode_encrypt_decrypt_decode() -> Result<()> {
|
fn test_encode_encrypt_decrypt_decode() -> Result<()> {
|
||||||
const Q: u64 = 2u64.pow(16) + 1;
|
let q: u64 = 2u64.pow(16) + 1;
|
||||||
const N: usize = 16;
|
let n: usize = 16;
|
||||||
const T: u64 = 8;
|
let t: u64 = 8;
|
||||||
|
let params = Params { q, n, t };
|
||||||
let scale_factor = C::<f64>::new(512.0, 0.0); // delta
|
let scale_factor = C::<f64>::new(512.0, 0.0); // delta
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
let ckks = CKKS::<Q, N>::new(scale_factor);
|
let ckks = CKKS::new(¶ms, scale_factor);
|
||||||
let (sk, pk) = ckks.new_key(&mut rng)?;
|
let (sk, pk) = ckks.new_key(&mut rng)?;
|
||||||
|
|
||||||
let z: Vec<C<f64>> = std::iter::repeat_with(|| C::<f64>::rand(&mut rng, T))
|
let z: Vec<C<f64>> = std::iter::repeat_with(|| C::<f64>::rand(&mut rng, t))
|
||||||
.take(N / 2)
|
.take(n / 2)
|
||||||
.collect();
|
.collect();
|
||||||
let m: R<N> = ckks.encoder.encode(&z)?;
|
let m: R = ckks.encoder.encode(&z)?;
|
||||||
println!("{}", m);
|
println!("{}", m);
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
@@ -200,26 +206,27 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add() -> Result<()> {
|
fn test_add() -> Result<()> {
|
||||||
const Q: u64 = 2u64.pow(16) + 1;
|
let q: u64 = 2u64.pow(16) + 1;
|
||||||
const N: usize = 16;
|
let n: usize = 16;
|
||||||
const T: u64 = 8;
|
let t: u64 = 8;
|
||||||
|
let params = Params { q, n, t };
|
||||||
let scale_factor = C::<f64>::new(1024.0, 0.0); // delta
|
let scale_factor = C::<f64>::new(1024.0, 0.0); // delta
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
let ckks = CKKS::<Q, N>::new(scale_factor);
|
let ckks = CKKS::new(¶ms, scale_factor);
|
||||||
|
|
||||||
let (sk, pk) = ckks.new_key(&mut rng)?;
|
let (sk, pk) = ckks.new_key(&mut rng)?;
|
||||||
|
|
||||||
let z0: Vec<C<f64>> = std::iter::repeat_with(|| C::<f64>::rand(&mut rng, T))
|
let z0: Vec<C<f64>> = std::iter::repeat_with(|| C::<f64>::rand(&mut rng, t))
|
||||||
.take(N / 2)
|
.take(n / 2)
|
||||||
.collect();
|
.collect();
|
||||||
let z1: Vec<C<f64>> = std::iter::repeat_with(|| C::<f64>::rand(&mut rng, T))
|
let z1: Vec<C<f64>> = std::iter::repeat_with(|| C::<f64>::rand(&mut rng, t))
|
||||||
.take(N / 2)
|
.take(n / 2)
|
||||||
.collect();
|
.collect();
|
||||||
let m0: R<N> = ckks.encoder.encode(&z0)?;
|
let m0: R = ckks.encoder.encode(&z0)?;
|
||||||
let m1: R<N> = ckks.encoder.encode(&z1)?;
|
let m1: R = ckks.encoder.encode(&z1)?;
|
||||||
|
|
||||||
let ct0 = ckks.encrypt(&mut rng, &pk, &m0)?;
|
let ct0 = ckks.encrypt(&mut rng, &pk, &m0)?;
|
||||||
let ct1 = ckks.encrypt(&mut rng, &pk, &m1)?;
|
let ct1 = ckks.encrypt(&mut rng, &pk, &m1)?;
|
||||||
@@ -243,26 +250,27 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sub() -> Result<()> {
|
fn test_sub() -> Result<()> {
|
||||||
const Q: u64 = 2u64.pow(16) + 1;
|
let q: u64 = 2u64.pow(16) + 1;
|
||||||
const N: usize = 16;
|
let n: usize = 16;
|
||||||
const T: u64 = 8;
|
let t: u64 = 8;
|
||||||
|
let params = Params { q, n, t };
|
||||||
let scale_factor = C::<f64>::new(1024.0, 0.0); // delta
|
let scale_factor = C::<f64>::new(1024.0, 0.0); // delta
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
let ckks = CKKS::<Q, N>::new(scale_factor);
|
let ckks = CKKS::new(¶ms, scale_factor);
|
||||||
|
|
||||||
let (sk, pk) = ckks.new_key(&mut rng)?;
|
let (sk, pk) = ckks.new_key(&mut rng)?;
|
||||||
|
|
||||||
let z0: Vec<C<f64>> = std::iter::repeat_with(|| C::<f64>::rand(&mut rng, T))
|
let z0: Vec<C<f64>> = std::iter::repeat_with(|| C::<f64>::rand(&mut rng, t))
|
||||||
.take(N / 2)
|
.take(n / 2)
|
||||||
.collect();
|
.collect();
|
||||||
let z1: Vec<C<f64>> = std::iter::repeat_with(|| C::<f64>::rand(&mut rng, T))
|
let z1: Vec<C<f64>> = std::iter::repeat_with(|| C::<f64>::rand(&mut rng, t))
|
||||||
.take(N / 2)
|
.take(n / 2)
|
||||||
.collect();
|
.collect();
|
||||||
let m0: R<N> = ckks.encoder.encode(&z0)?;
|
let m0: R = ckks.encoder.encode(&z0)?;
|
||||||
let m1: R<N> = ckks.encoder.encode(&z1)?;
|
let m1: R = ckks.encoder.encode(&z1)?;
|
||||||
|
|
||||||
let ct0 = ckks.encrypt(&mut rng, &pk, &m0)?;
|
let ct0 = ckks.encrypt(&mut rng, &pk, &m0)?;
|
||||||
let ct1 = ckks.encrypt(&mut rng, &pk, &m1)?;
|
let ct1 = ckks.encrypt(&mut rng, &pk, &m1)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user