broken bootstrapping implementation

This commit is contained in:
2025-05-21 21:56:49 +02:00
parent 25841d0493
commit 9346355406

View File

@ -76,18 +76,60 @@ pub fn generate_bootstrap_key(
}
// /// Evaluates the decryption circuit to refresh a ciphertext (lower the noise level)
// pub fn bootstrap(
// ciphertext: &Integer,
// bk: &BootstrapKey,
// pk: &PublicKey,
// rho: u32,
// sk: &PrivateKey,
// ) -> Integer {
// // TODO: actual implementation
// let m = decrypt_bit(ciphertext, &sk.p);
// encrypt_bit_asym(m, pk, rho)
// }
pub fn encrypt_and_evaluate(
c: &Integer,
bootstrap_key: &BootstrapKey,
precision_bits: u32,
) -> Vec<Rational> {
let mut result = Vec::with_capacity(bootstrap_key.y.len());
let scale = Integer::from(1) << precision_bits;
let scale_rat = Rational::from(&scale);
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)]
mod tests {
@ -165,4 +207,65 @@ mod tests {
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
);
}
}
}
}