Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
29 changes: 25 additions & 4 deletions crates/fhe/src/bfv/keys/secret_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Ntt>::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::<BigUint>::from(&c) {
for coeff in Vec::<BigUint>::from(c.as_ref()) {
noise = std::cmp::max(
noise,
std::cmp::min(coeff.bits(), (ciphertext_modulus - &coeff).bits()) as usize,
Expand Down Expand Up @@ -227,8 +227,8 @@ impl FheDecrypter<Plaintext, Ciphertext> 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::<Ntt>::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 { .. } => {
Expand Down Expand Up @@ -334,6 +334,27 @@ mod tests {
Ok(())
}

#[test]
fn measure_noise_within_modulus_bits() -> Result<(), Box<dyn Error>> {
let mut rng = rng();
let params = BfvParameters::default_arc(1, 16);
let sk = SecretKey::random(&params, &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),
&params,
)?;
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<dyn Error>> {
let mut rng = rng();
Expand Down
Loading