Added binary key distributions

This commit is contained in:
Jean-Philippe Bossuat
2025-06-12 10:13:47 +02:00
parent c77a819653
commit d826fcd5c8
4 changed files with 57 additions and 2 deletions

View File

@@ -3,7 +3,7 @@ use crate::ffi::vmp;
use crate::znx_base::{ZnxInfos, ZnxView, ZnxViewMut}; use crate::znx_base::{ZnxInfos, ZnxView, ZnxViewMut};
use crate::{ use crate::{
Backend, FFT64, MatZnxDft, MatZnxDftOwned, MatZnxToMut, MatZnxToRef, Module, ScalarZnxAlloc, ScalarZnxDftAlloc, Backend, FFT64, MatZnxDft, MatZnxDftOwned, MatZnxToMut, MatZnxToRef, Module, ScalarZnxAlloc, ScalarZnxDftAlloc,
ScalarZnxDftOps, Scratch, VecZnxDft, VecZnxDftAlloc, VecZnxDftOps, VecZnxDftToMut, VecZnxDftToRef, VecZnxOps, ZnxZero, ScalarZnxDftOps, Scratch, VecZnxDft, VecZnxDftAlloc, VecZnxDftOps, VecZnxDftToMut, VecZnxDftToRef, VecZnxOps,
}; };
pub trait MatZnxDftAlloc<B: Backend> { pub trait MatZnxDftAlloc<B: Backend> {

View File

@@ -72,6 +72,31 @@ impl<D: AsMut<[u8]> + AsRef<[u8]>> ScalarZnx<D> {
.for_each(|x: &mut i64| *x = (((source.next_u32() & 1) as i64) << 1) - 1); .for_each(|x: &mut i64| *x = (((source.next_u32() & 1) as i64) << 1) - 1);
self.at_mut(col, 0).shuffle(source); self.at_mut(col, 0).shuffle(source);
} }
pub fn fill_binary_prob(&mut self, col: usize, prob: f64, source: &mut Source) {
let choices: [i64; 2] = [0, 1];
let weights: [f64; 2] = [1.0 - prob, prob];
let dist: WeightedIndex<f64> = WeightedIndex::new(&weights).unwrap();
self.at_mut(col, 0)
.iter_mut()
.for_each(|x: &mut i64| *x = choices[dist.sample(source)]);
}
pub fn fill_binary_hw(&mut self, col: usize, hw: usize, source: &mut Source) {
assert!(hw <= self.n());
self.at_mut(col, 0)[..hw]
.iter_mut()
.for_each(|x: &mut i64| *x = (source.next_u32() & 1) as i64);
self.at_mut(col, 0).shuffle(source);
}
pub fn fill_binary_block(&mut self, col: usize, block_size: usize, source: &mut Source) {
assert!(self.n() % block_size == 0);
for chunk in self.at_mut(col, 0).chunks_mut(block_size) {
chunk[0] = 1;
chunk.shuffle(source);
}
}
} }
impl<D: From<Vec<u8>>> ScalarZnx<D> { impl<D: From<Vec<u8>>> ScalarZnx<D> {

View File

@@ -763,6 +763,9 @@ impl<DataSelf: AsRef<[u8]> + AsMut<[u8]>> GLWECiphertext<DataSelf> {
), ),
SecretDistribution::TernaryFixed(hw) => u.fill_ternary_hw(0, hw, source_xu), SecretDistribution::TernaryFixed(hw) => u.fill_ternary_hw(0, hw, source_xu),
SecretDistribution::TernaryProb(prob) => u.fill_ternary_prob(0, prob, source_xu), SecretDistribution::TernaryProb(prob) => u.fill_ternary_prob(0, prob, source_xu),
SecretDistribution::BinaryFixed(hw) => u.fill_binary_hw(0, hw, source_xu),
SecretDistribution::BinaryProb(prob) => u.fill_binary_prob(0, prob, source_xu),
SecretDistribution::BinaryBlock(block_size) => u.fill_binary_block(0, block_size, source_xu),
SecretDistribution::ZERO => {} SecretDistribution::ZERO => {}
} }

View File

@@ -10,8 +10,11 @@ use crate::{GLWECiphertextFourier, Infos};
pub(crate) enum SecretDistribution { pub(crate) enum SecretDistribution {
TernaryFixed(usize), // Ternary with fixed Hamming weight TernaryFixed(usize), // Ternary with fixed Hamming weight
TernaryProb(f64), // Ternary with probabilistic Hamming weight TernaryProb(f64), // Ternary with probabilistic Hamming weight
BinaryFixed(usize), // Binary with fixed Hamming weight
BinaryProb(f64), // Binary with probabilistic Hamming weight
BinaryBlock(usize), // Binary split in block of size 2^k
ZERO, // Debug mod ZERO, // Debug mod
NONE, NONE, // Unitialized
} }
pub struct GLWESecret<T, B: Backend> { pub struct GLWESecret<T, B: Backend> {
@@ -65,6 +68,30 @@ impl<S: AsMut<[u8]> + AsRef<[u8]>> GLWESecret<S, FFT64> {
self.dist = SecretDistribution::TernaryFixed(hw); self.dist = SecretDistribution::TernaryFixed(hw);
} }
pub fn fill_binary_prob(&mut self, module: &Module<FFT64>, prob: f64, source: &mut Source) {
(0..self.rank()).for_each(|i| {
self.data.fill_binary_prob(i, prob, source);
});
self.prep_fourier(module);
self.dist = SecretDistribution::BinaryProb(prob);
}
pub fn fill_binary_hw(&mut self, module: &Module<FFT64>, hw: usize, source: &mut Source) {
(0..self.rank()).for_each(|i| {
self.data.fill_binary_hw(i, hw, source);
});
self.prep_fourier(module);
self.dist = SecretDistribution::BinaryFixed(hw);
}
pub fn fill_binary_block(&mut self, module: &Module<FFT64>, block_size: usize, source: &mut Source) {
(0..self.rank()).for_each(|i| {
self.data.fill_binary_block(i, block_size, source);
});
self.prep_fourier(module);
self.dist = SecretDistribution::BinaryBlock(block_size);
}
pub fn fill_zero(&mut self) { pub fn fill_zero(&mut self) {
self.data.zero(); self.data.zero();
self.dist = SecretDistribution::ZERO; self.dist = SecretDistribution::ZERO;