1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
use super::{read_from_file, write_to_file};
use concrete_core::crypto::GlweDimension;
use concrete_core::math::polynomial::PolynomialSize;
use concrete_core::math::random::RandomGenerator;
use concrete_core::{
    crypto::secret::{GlweSecretKey, LweSecretKey},
    math::tensor::IntoTensor,
};
use serde::{Deserialize, Serialize};
use std::error::Error;
use std::fmt;

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct RLWESecretKey {
    pub val: GlweSecretKey<Vec<bool>>,
    pub polynomial_size: usize,
    pub dimension: usize,
    pub std_dev: f64,
}

impl RLWESecretKey {
    /// Generate a new secret key from an RLWEParams
    /// # Argument
    /// * `params` - an RLWEParams instance
    /// # Output
    /// * a new RLWESecretKey
    pub fn new(params: &crate::RLWEParams) -> RLWESecretKey {
        let val = GlweSecretKey::generate(
            GlweDimension(params.dimension),
            PolynomialSize(params.polynomial_size),
            &mut RandomGenerator::new(None),
        );
        RLWESecretKey {
            val,
            polynomial_size: params.polynomial_size,
            dimension: params.dimension,
            std_dev: params.get_std_dev(),
        }
    }

    /// Generate a new secret key from a raw dimension (i.e. without a RLWEParams input)
    /// # Argument
    /// * `polynomial_size` - the size of the polynomial
    /// * `dimension` - the length the LWE mask
    /// # Output
    /// * a new RLWESecretKey
    pub fn new_raw(polynomial_size: usize, dimension: usize, std_dev: f64) -> RLWESecretKey {
        let val = GlweSecretKey::generate(
            GlweDimension(dimension),
            PolynomialSize(polynomial_size),
            &mut RandomGenerator::new(None),
        );
        RLWESecretKey {
            val,
            polynomial_size,
            dimension,
            std_dev,
        }
    }

    /// Convert an RLWE secret key into an LWE secret key
    /// # Output
    /// * an LWE secret key
    pub fn to_lwe_secret_key(&self) -> crate::LWESecretKey {
        crate::LWESecretKey {
            val: LweSecretKey::from_container(self.val.clone().into_tensor().into_container()),
            dimension: self.dimension * self.polynomial_size,
            std_dev: self.std_dev,
        }
    }

    /// Return the variance of the error distribution associated with the secret key
    /// # Output
    /// * the variance
    pub fn get_variance(&self) -> f64 {
        f64::powi(self.std_dev, 2i32)
    }

    pub fn save(&self, path: &str) -> Result<(), Box<dyn Error>> {
        write_to_file(path, self)
    }

    pub fn load(path: &str) -> Result<RLWESecretKey, Box<dyn Error>> {
        read_from_file(path)
    }
}

impl fmt::Display for RLWESecretKey {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut to_be_print: String = "".to_string();
        to_be_print = to_be_print
            + &format!(
                " RLWESecretKey {{\n         -> dimension = {}\n         -> polynomial_size = {}\n         -> std_dev = {}\n",
                self.dimension, self.polynomial_size, self.std_dev
            );
        to_be_print += "       }";

        writeln!(f, "{}", to_be_print)
    }
}