mirror of
https://github.com/zama-ai/concrete.git
synced 2026-02-15 07:05:09 -05:00
fix: replacement for concrete-cpu-noise-model/gaussian/security
This commit is contained in:
5
Cargo.toml
Normal file
5
Cargo.toml
Normal file
@@ -0,0 +1,5 @@
|
||||
[workspace]
|
||||
|
||||
members = [
|
||||
"concrete-security-curves-rust",
|
||||
]
|
||||
2
Makefile
2
Makefile
@@ -4,7 +4,7 @@ SAGE_SECURITY_CURVES=$(SECURITY_LEVELS:%=$(SAGE_OBJECT_DIR)/%.sobj)
|
||||
SAGE_VERIFIED_CURVES=$(SAGE_OBJECT_DIR)/verified_curves.sobj
|
||||
CURVES_JSON_PATH=json/curves.json
|
||||
CURVES_CPP_GEN_H=concrete-security-curves-cpp/include/concrete/curves.gen.h
|
||||
CURVES_RUST_GEN_TXT=concrete-security-curves-rust/src/curves.gen.rs
|
||||
CURVES_RUST_GEN_TXT=concrete-security-curves-rust/src/gaussian/curves_gen.rs
|
||||
|
||||
generate-code: generate-cpp generate-rust
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@ def print_curve(data):
|
||||
|
||||
|
||||
def print_rust_curves_declaration(datas):
|
||||
print(f"const SECURITY_WEIGHTS_ARRAY: [(u64, SecurityWeights); {len(datas)}] = [")
|
||||
print("use super::security_weights::SecurityWeights;")
|
||||
print(f"pub const SECURITY_WEIGHTS_ARRAY: [(u64, SecurityWeights); {len(datas)}] = [")
|
||||
for data in datas:
|
||||
print_curve(data)
|
||||
print("];")
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const SECURITY_WEIGHTS_ARRAY: [(u64, SecurityWeights); 4] = [
|
||||
use super::security_weights::SecurityWeights;
|
||||
pub const SECURITY_WEIGHTS_ARRAY: [(u64, SecurityWeights); 4] = [
|
||||
(80, SecurityWeights { slope: -0.04045822621883835, bias: 1.7183812000404686, minimal_lwe_dimension: 450 }),
|
||||
(112, SecurityWeights { slope: -0.029881371645803536, bias: 2.6539316216894946, minimal_lwe_dimension: 450 }),
|
||||
(128, SecurityWeights { slope: -0.026599462343105267, bias: 2.981543184145991, minimal_lwe_dimension: 450 }),
|
||||
3
concrete-security-curves-rust/src/gaussian/mod.rs
Normal file
3
concrete-security-curves-rust/src/gaussian/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod curves_gen;
|
||||
pub mod security_weights;
|
||||
pub mod security;
|
||||
71
concrete-security-curves-rust/src/gaussian/security.rs
Normal file
71
concrete-security-curves-rust/src/gaussian/security.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
use super::curves_gen::SECURITY_WEIGHTS_ARRAY;
|
||||
use super::security_weights::SecurityWeights;
|
||||
|
||||
pub fn supported_security_levels() -> impl std::iter::Iterator<Item = u64> {
|
||||
SECURITY_WEIGHTS_ARRAY
|
||||
.iter()
|
||||
.map(|(security_level, _)| *security_level)
|
||||
}
|
||||
|
||||
pub fn security_weight(security_level: u64) -> Option<SecurityWeights> {
|
||||
let index = SECURITY_WEIGHTS_ARRAY
|
||||
.binary_search_by_key(&security_level, |(security_level, _weights)| {
|
||||
*security_level
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
Some(SECURITY_WEIGHTS_ARRAY[index].1)
|
||||
}
|
||||
|
||||
/// Noise ensuring security
|
||||
pub fn minimal_variance_lwe(
|
||||
lwe_dimension: u64,
|
||||
ciphertext_modulus_log: u32,
|
||||
security_level: u64,
|
||||
) -> f64 {
|
||||
minimal_variance_glwe(lwe_dimension, 1, ciphertext_modulus_log, security_level)
|
||||
}
|
||||
|
||||
/// Noise ensuring security
|
||||
pub fn minimal_variance_glwe(
|
||||
glwe_dimension: u64,
|
||||
polynomial_size: u64,
|
||||
ciphertext_modulus_log: u32,
|
||||
security_level: u64,
|
||||
) -> f64 {
|
||||
let equiv_lwe_dimension = glwe_dimension * polynomial_size;
|
||||
let security_weights = security_weight(security_level)
|
||||
.unwrap_or_else(|| panic!("{security_level} bits of security is not supported"));
|
||||
|
||||
let secure_log2_std =
|
||||
security_weights.secure_log2_std(equiv_lwe_dimension, ciphertext_modulus_log as f64);
|
||||
let log2_var = 2.0 * secure_log2_std;
|
||||
f64::exp2(log2_var)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let weight = security_weight(128).unwrap();
|
||||
|
||||
let secure_log_2_std = weight.secure_log2_std(512, 64.);
|
||||
|
||||
assert!((-12.0..-10.0).contains(&secure_log_2_std));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn security_security_glwe_variance_low() {
|
||||
let integer_size = 64;
|
||||
let golden_std_dev = 2.168_404_344_971_009e-19;
|
||||
let security_level = 128;
|
||||
|
||||
let actual_var = minimal_variance_glwe(10, 1 << 14, integer_size, security_level);
|
||||
let actual_std_dev = actual_var.sqrt();
|
||||
let expected_std_dev = (0.99 * golden_std_dev)..(1.01 * golden_std_dev);
|
||||
assert!(expected_std_dev.contains(&actual_std_dev));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct SecurityWeights {
|
||||
pub(crate) slope: f64,
|
||||
pub(crate) bias: f64,
|
||||
pub minimal_lwe_dimension: u64,
|
||||
}
|
||||
|
||||
impl SecurityWeights {
|
||||
pub fn secure_log2_std(&self, lwe_dimension: u64, ciphertext_modulus_log: f64) -> f64 {
|
||||
// ensure to have a minimal on std deviation covering the 2 lowest bits on modular scale
|
||||
let epsilon_log2_std_modular = 2.0;
|
||||
let epsilon_log2_std = epsilon_log2_std_modular - (ciphertext_modulus_log);
|
||||
// ensure the requested lwe_dimension is bigger than the minimal lwe dimension
|
||||
if self.minimal_lwe_dimension <= lwe_dimension {
|
||||
f64::max(
|
||||
self.slope * lwe_dimension as f64 + self.bias,
|
||||
epsilon_log2_std,
|
||||
)
|
||||
} else {
|
||||
ciphertext_modulus_log
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +1 @@
|
||||
include!("./curves.gen.rs");
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct SecurityWeights {
|
||||
slope: f64,
|
||||
bias: f64,
|
||||
minimal_lwe_dimension: u64,
|
||||
}
|
||||
|
||||
impl SecurityWeights {
|
||||
pub fn secure_log2_std(&self, lwe_dimension: u64, ciphertext_modulus_log: f64) -> f64 {
|
||||
// ensure to have a minimal on std deviation covering the 2 lowest bits on modular scale
|
||||
let epsilon_log2_std_modular = 2.0;
|
||||
let epsilon_log2_std = epsilon_log2_std_modular - (ciphertext_modulus_log);
|
||||
// ensure the requested lwe_dimension is bigger than the minimal lwe dimension
|
||||
if self.minimal_lwe_dimension <= lwe_dimension {
|
||||
f64::max(
|
||||
self.slope * lwe_dimension as f64 + self.bias,
|
||||
epsilon_log2_std,
|
||||
)
|
||||
} else {
|
||||
ciphertext_modulus_log
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn supported_security_levels() -> impl std::iter::Iterator<Item = u64> {
|
||||
SECURITY_WEIGHTS_ARRAY
|
||||
.iter()
|
||||
.map(|(security_level, _)| *security_level)
|
||||
}
|
||||
|
||||
pub fn security_weight(security_level: u64) -> Option<SecurityWeights> {
|
||||
let index = SECURITY_WEIGHTS_ARRAY
|
||||
.binary_search_by_key(&security_level, |(security_level, _)| *security_level)
|
||||
.ok()?;
|
||||
|
||||
Some(SECURITY_WEIGHTS_ARRAY[index].1)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let weight = security_weight(128).unwrap();
|
||||
|
||||
let secure_log_2_std = weight.secure_log2_std(512, 64.);
|
||||
|
||||
assert!((-12.0..-10.0).contains(&secure_log_2_std));
|
||||
}
|
||||
}
|
||||
pub mod gaussian;
|
||||
|
||||
Reference in New Issue
Block a user