broken bootstrapping implementation
This commit is contained in:
@ -76,18 +76,60 @@ pub fn generate_bootstrap_key(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// /// Evaluates the decryption circuit to refresh a ciphertext (lower the noise level)
|
pub fn encrypt_and_evaluate(
|
||||||
// pub fn bootstrap(
|
c: &Integer,
|
||||||
// ciphertext: &Integer,
|
bootstrap_key: &BootstrapKey,
|
||||||
// bk: &BootstrapKey,
|
precision_bits: u32,
|
||||||
// pk: &PublicKey,
|
) -> Vec<Rational> {
|
||||||
// rho: u32,
|
let mut result = Vec::with_capacity(bootstrap_key.y.len());
|
||||||
// sk: &PrivateKey,
|
|
||||||
// ) -> Integer {
|
let scale = Integer::from(1) << precision_bits;
|
||||||
// // TODO: actual implementation
|
let scale_rat = Rational::from(&scale);
|
||||||
// let m = decrypt_bit(ciphertext, &sk.p);
|
|
||||||
// encrypt_bit_asym(m, pk, rho)
|
for y_i in &bootstrap_key.y {
|
||||||
// }
|
let prod = Rational::from(c) * y_i;
|
||||||
|
let scaled = prod.clone() * &scale_rat;
|
||||||
|
|
||||||
|
let floored = scaled.clone().floor();
|
||||||
|
let frac = &scaled - floored;
|
||||||
|
|
||||||
|
result.push(frac);
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bootstrap(
|
||||||
|
c: &Integer,
|
||||||
|
z: &[Rational],
|
||||||
|
encrypted_sk_bits: &[Integer],
|
||||||
|
pk: &PublicKey,
|
||||||
|
precision_bits: u32,
|
||||||
|
) -> Integer {
|
||||||
|
let int_scale = Integer::from(1) << precision_bits;
|
||||||
|
let scale_rat = Rational::from(&int_scale);
|
||||||
|
let half_rat = Rational::from((1, 2));
|
||||||
|
let x0 = &pk.xs[0];
|
||||||
|
|
||||||
|
let mut acc = Integer::from(0);
|
||||||
|
for (z_i, enc_s_i) in z.iter().zip(encrypted_sk_bits.iter()) {
|
||||||
|
let rounded: Integer = (z_i.clone() * &scale_rat + &half_rat).floor_ref().into();
|
||||||
|
|
||||||
|
acc += &rounded * enc_s_i;
|
||||||
|
}
|
||||||
|
|
||||||
|
acc %= x0;
|
||||||
|
|
||||||
|
let inv_scale = int_scale
|
||||||
|
.invert(x0)
|
||||||
|
.expect("2^precision_bits and x0 must be coprime");
|
||||||
|
let adjusted_sum = (acc * inv_scale) % x0;
|
||||||
|
|
||||||
|
let mut diff = c.clone();
|
||||||
|
diff -= &adjusted_sum;
|
||||||
|
diff.modulo(x0)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
@ -165,4 +207,65 @@ mod tests {
|
|||||||
bound
|
bound
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bootstrapping_preserve_m() {
|
||||||
|
let eta = 1000; // secret key bit size
|
||||||
|
let rho = 30; // initial noise
|
||||||
|
let theta = 1000; // Hamming weight of hint support
|
||||||
|
let n_theta = 1000; // total hint size
|
||||||
|
let kappa = 1000; // precision for y_i
|
||||||
|
|
||||||
|
let (sk, pk) = generate_keys(rho, eta, rho, theta);
|
||||||
|
let bk = generate_bootstrap_key(&pk, &sk.p, kappa, theta, n_theta, rho);
|
||||||
|
|
||||||
|
for m in 0..=1 {
|
||||||
|
let mut c = encrypt_bit_asym(m, &pk, rho);
|
||||||
|
for _ in 0..=100 {
|
||||||
|
|
||||||
|
let encrypted_z = encrypt_and_evaluate(&c, &bk, kappa);
|
||||||
|
c = bootstrap(&c, &encrypted_z, &bk.enc_s, &pk, kappa);
|
||||||
|
|
||||||
|
let m_boot = decrypt_bit(&c, &sk.p);
|
||||||
|
assert_eq!(
|
||||||
|
m, m_boot,
|
||||||
|
"Bootstrap failed: expected {}, got {}",
|
||||||
|
m, m_boot
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bootstrapping() {
|
||||||
|
let eta = 1000; // secret key bit size
|
||||||
|
let rho = 30; // initial noise
|
||||||
|
let theta = 1000; // Hamming weight of hint support
|
||||||
|
let n_theta = 1000; // total hint size
|
||||||
|
let kappa = 1000; // precision for y_i
|
||||||
|
|
||||||
|
let (sk, pk) = generate_keys(rho, eta, rho, theta);
|
||||||
|
let bk = generate_bootstrap_key(&pk, &sk.p, kappa, theta, n_theta, rho);
|
||||||
|
|
||||||
|
// let c0 = encrypt_bit_asym(0u8, &pk, rho);
|
||||||
|
let c1 = encrypt_bit_asym(1u8, &pk, rho);
|
||||||
|
|
||||||
|
for m in 0..=1 {
|
||||||
|
let mut c = encrypt_bit_asym(m, &pk, rho);
|
||||||
|
for _ in 0..=100 {
|
||||||
|
// c += c0.clone();
|
||||||
|
c *= c1.clone();
|
||||||
|
|
||||||
|
let encrypted_z = encrypt_and_evaluate(&c, &bk, kappa*2);
|
||||||
|
c = bootstrap(&c, &encrypted_z, &bk.enc_s, &pk, kappa*2);
|
||||||
|
|
||||||
|
let m_boot = decrypt_bit(&c, &sk.p);
|
||||||
|
assert_eq!(
|
||||||
|
m, m_boot,
|
||||||
|
"Bootstrap failed: expected {}, got {}",
|
||||||
|
m, m_boot
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user