fix: replacement for concrete-cpu-noise-model/gaussian/security

This commit is contained in:
rudy
2023-01-17 11:49:45 +01:00
committed by rudy-6-4
parent b3898cca8f
commit 05184593ad
8 changed files with 108 additions and 56 deletions

5
Cargo.toml Normal file
View File

@@ -0,0 +1,5 @@
[workspace]
members = [
"concrete-security-curves-rust",
]

View File

@@ -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

View File

@@ -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("];")

View File

@@ -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 }),

View File

@@ -0,0 +1,3 @@
pub mod curves_gen;
pub mod security_weights;
pub mod security;

View 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));
}
}

View File

@@ -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
}
}
}

View File

@@ -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;