From a096be8f63e6eda295fdf207fb363d7217d7d4a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tancr=C3=A8de=20Lepoint?= Date: Sun, 1 Feb 2026 18:27:36 -0500 Subject: [PATCH] Update MSRV to 1.91.1 --- Cargo.toml | 2 +- README.md | 2 +- crates/fhe/src/bfv/keys/secret_key.rs | 29 +++++++++++++++++++++++---- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 19083dae..99ef3453 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ authors = ["Tancrède Lepoint"] edition = "2024" repository = "https://github.com/tlepoint/fhe.rs" license = "MIT" -rust-version = "1.88" +rust-version = "1.91.1" [workspace.lints.rust] missing_docs = "warn" diff --git a/README.md b/README.md index b6fa0131..d4ca369e 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ fhe-traits = "0.1.1" ## Minimum supported version / toolchain -Rust **1.85** or newer (Rust 2024 edition). +Rust **1.91.1** or newer (Rust 2024 edition). ## ⚠️ Security / Stability diff --git a/crates/fhe/src/bfv/keys/secret_key.rs b/crates/fhe/src/bfv/keys/secret_key.rs index 3c7ff088..03017da9 100644 --- a/crates/fhe/src/bfv/keys/secret_key.rs +++ b/crates/fhe/src/bfv/keys/secret_key.rs @@ -85,11 +85,11 @@ impl SecretKey { *c.as_mut() -= &m; let ctx = c.ctx().clone(); let c_inner = std::mem::replace(c.as_mut(), Poly::::zero(&ctx)); - let c = c_inner.into_power_basis(); + let c = Zeroizing::new(c_inner.into_power_basis()); let ciphertext_modulus = ct[0].ctx().modulus(); let mut noise = 0usize; - for coeff in Vec::::from(&c) { + for coeff in Vec::::from(c.as_ref()) { noise = std::cmp::max( noise, std::cmp::min(coeff.bits(), (ciphertext_modulus - &coeff).bits()) as usize, @@ -227,8 +227,8 @@ impl FheDecrypter for SecretKey { let ctx_lvl = self.par.context_level_at(ct.level).unwrap(); let ctx = c.ctx().clone(); let c_inner = std::mem::replace(c.as_mut(), Poly::::zero(&ctx)); - let c_pb = c_inner.into_power_basis(); - let d = Zeroizing::new(c_pb.scale(&ctx_lvl.cipher_plain_context.scaler)?); + let c_pb = Zeroizing::new(c_inner.into_power_basis()); + let d = Zeroizing::new(c_pb.as_ref().scale(&ctx_lvl.cipher_plain_context.scaler)?); let value = match self.par.plaintext { PlaintextModulus::Small { .. } => { @@ -334,6 +334,27 @@ mod tests { Ok(()) } + #[test] + fn measure_noise_within_modulus_bits() -> Result<(), Box> { + let mut rng = rng(); + let params = BfvParameters::default_arc(1, 16); + let sk = SecretKey::random(¶ms, &mut rng); + let q = fhe_math::zq::Modulus::new(params.plaintext()).unwrap(); + + let pt = Plaintext::try_encode( + &q.random_vec(params.degree(), &mut rng), + Encoding::poly_at_level(0), + ¶ms, + )?; + let ct = sk.try_encrypt(&pt, &mut rng)?; + let noise = unsafe { sk.measure_noise(&ct)? }; + + let modulus_bits = ct[0].ctx().modulus().bits() as usize; + assert!(noise <= modulus_bits); + + Ok(()) + } + #[test] fn serialize_roundtrip() -> Result<(), Box> { let mut rng = rng();