use rand::Rng;
use crate::modular::mod_q;
use crate::params::Params;
#[derive(Clone, Debug)]
pub struct SecretKey {
pub s: Vec<u64>,
params: Params,
}
impl SecretKey {
pub fn params(&self) -> &Params {
&self.params
}
}
#[derive(Clone, Debug)]
pub struct PublicKey {
pub a: Vec<Vec<u64>>,
params: Params,
}
impl PublicKey {
pub fn params(&self) -> &Params {
&self.params
}
}
fn rand_zq<R: Rng>(rng: &mut R, q: u64) -> u64 {
rng.gen_range(0..q)
}
fn sample_error<R: Rng>(rng: &mut R, bound: i64) -> i64 {
if bound <= 0 {
return 0;
}
rng.gen_range(-bound..=bound)
}
pub fn keygen<R: Rng>(rng: &mut R, params: &Params) -> (SecretKey, PublicKey) {
let n = params.n;
let m = params.m;
let q = params.q;
let bound = params.error_bound;
let t: Vec<u64> = (0..n).map(|_| rand_zq(rng, q)).collect();
let mut s = vec![1u64];
for &ti in &t {
s.push(mod_q(-(ti as i64), q));
}
let b_mat: Vec<Vec<u64>> = (0..m)
.map(|_| (0..n).map(|_| rand_zq(rng, q)).collect())
.collect();
let e: Vec<i64> = (0..m).map(|_| sample_error(rng, bound)).collect();
let mut b = vec![0u64; m];
for i in 0..m {
let mut dot: i64 = 0;
for j in 0..n {
dot += b_mat[i][j] as i64 * t[j] as i64;
}
b[i] = mod_q(dot + e[i], q);
}
let mut a = vec![vec![0u64; n + 1]; m];
for i in 0..m {
a[i][0] = b[i];
for j in 0..n {
a[i][j + 1] = b_mat[i][j];
}
}
(
SecretKey {
s: s.clone(),
params: params.clone(),
},
PublicKey {
a,
params: params.clone(),
},
)
}