Improve GGSW-based blind rotation API

This commit is contained in:
Pro7ech
2025-10-28 11:04:47 +01:00
parent 8ba01a6420
commit 787504c230
6 changed files with 28 additions and 10 deletions

View File

@@ -2,13 +2,18 @@
## [0.3.2] - 2025-10-27 ## [0.3.2] - 2025-10-27
### `poulpy-schemes`
- Added `sign` argument to GGSW-based blind rotation, which enables to choose the rotation direction of the test vector.
## [0.3.2] - 2025-10-27
### `poulpy-hal` ### `poulpy-hal`
- Improved convolution functionality - Improved convolution functionality
### `poulpy-core` ### `poulpy-core`
- Rename `GLWEToLWESwitchingKey` to `GLWEToLWEKey`. - Rename `GLWEToLWESwitchingKey` to `GLWEToLWEKey`.
- Rename `LWEToGLWESwitchingKey` to `LWEToGLWEKey`. - Rename `LWEToGLWESwitchingKey` to `LWEToGLWEKey`.
- Add `GLWESecretTensor` which stores the flattened upper triangular matrix of the pairs `sk[i] * sk[j]`. - Add `GLWESecretTensor` which stores the flattened upper right of the tensor matrix of the pairs `sk[i] * sk[j]`.
- Add `GGLWEToGGSWKey`, `GGLWEToGGSWKeyPrepared`, `GGLWEToGGSWKeyCompressed`, which encrypts the full tensor matrix of all pairs `sk[i] * sk[j]`, with one `GGLWE` per row. - Add `GGLWEToGGSWKey`, `GGLWEToGGSWKeyPrepared`, `GGLWEToGGSWKeyCompressed`, which encrypts the full tensor matrix of all pairs `sk[i] * sk[j]`, with one `GGLWE` per row.
- Update `GGLWEToGGSW` API to take `GGLWEToGGSWKey` instead of the `GLWETensorKey` - Update `GGLWEToGGSW` API to take `GGLWEToGGSWKey` instead of the `GLWETensorKey`
- Add `GLWETensor`, the result of tensoring two `GLWE` of identical rank. - Add `GLWETensor`, the result of tensoring two `GLWE` of identical rank.

2
Cargo.lock generated
View File

@@ -401,7 +401,7 @@ dependencies = [
[[package]] [[package]]
name = "poulpy-schemes" name = "poulpy-schemes"
version = "0.3.2" version = "0.3.3"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"criterion", "criterion",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "poulpy-schemes" name = "poulpy-schemes"
version = "0.3.2" version = "0.3.3"
edition = "2024" edition = "2024"
license = "Apache-2.0" license = "Apache-2.0"
readme = "README.md" readme = "README.md"

View File

@@ -36,7 +36,8 @@ where
res: &mut R, res: &mut R,
a: &A, a: &A,
k: &K, k: &K,
bit_start: usize, sign: bool,
bit_rsh: usize,
bit_mask: usize, bit_mask: usize,
bit_lsh: usize, bit_lsh: usize,
scratch: &mut Scratch<BE>, scratch: &mut Scratch<BE>,
@@ -58,7 +59,8 @@ where
&mut res.at_mut(row, col), &mut res.at_mut(row, col),
&a.at(row, col), &a.at(row, col),
k, k,
bit_start, sign,
bit_rsh,
bit_mask, bit_mask,
bit_lsh, bit_lsh,
scratch, scratch,
@@ -81,7 +83,8 @@ where
res: &mut R, res: &mut R,
test_vector: &S, test_vector: &S,
k: &K, k: &K,
bit_start: usize, sign: bool,
bit_rsh: usize,
bit_mask: usize, bit_mask: usize,
bit_lsh: usize, bit_lsh: usize,
scratch: &mut Scratch<BE>, scratch: &mut Scratch<BE>,
@@ -115,7 +118,8 @@ where
&mut res.at_mut(row, col), &mut res.at_mut(row, col),
&tmp_glwe, &tmp_glwe,
k, k,
bit_start, sign,
bit_rsh,
bit_mask, bit_mask,
bit_lsh, bit_lsh,
scratch_1, scratch_1,
@@ -146,12 +150,13 @@ where
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
/// res <- a * X^{((k>>bit_rsh) % 2^bit_mask) << bit_lsh}. /// res <- a * X^{sign * ((k>>bit_rsh) % 2^bit_mask) << bit_lsh}.
fn glwe_to_glwe_blind_rotation<R, A, K>( fn glwe_to_glwe_blind_rotation<R, A, K>(
&self, &self,
res: &mut R, res: &mut R,
a: &A, a: &A,
k: &K, k: &K,
sign: bool,
bit_rsh: usize, bit_rsh: usize,
bit_mask: usize, bit_mask: usize,
bit_lsh: usize, bit_lsh: usize,
@@ -170,7 +175,10 @@ where
let (mut tmp_res, scratch_1) = scratch.take_glwe(&res); let (mut tmp_res, scratch_1) = scratch.take_glwe(&res);
// a <- a ; b <- a * X^{-2^{i + bit_lsh}} // a <- a ; b <- a * X^{-2^{i + bit_lsh}}
self.glwe_rotate(-1 << bit_lsh, &mut res, a); match sign {
true => self.glwe_rotate(1 << bit_lsh, &mut res, a),
false => self.glwe_rotate(-1 << bit_lsh, &mut res, a),
}
// b <- (b - a) * GGSW(b[i]) + a // b <- (b - a) * GGSW(b[i]) + a
self.cmux_inplace(&mut res, a, &k.get_bit(bit_rsh), scratch_1); self.cmux_inplace(&mut res, a, &k.get_bit(bit_rsh), scratch_1);
@@ -187,7 +195,10 @@ where
}; };
// a <- a ; b <- a * X^{-2^{i + bit_lsh}} // a <- a ; b <- a * X^{-2^{i + bit_lsh}}
self.glwe_rotate(-1 << (i + bit_lsh), b, a); match sign {
true => self.glwe_rotate(1 << (i + bit_lsh), b, a),
false => self.glwe_rotate(-1 << (i + bit_lsh), b, a),
}
// b <- (b - a) * GGSW(b[i]) + a // b <- (b - a) * GGSW(b[i]) + a
self.cmux_inplace(b, a, &k.get_bit(i + bit_rsh), scratch_1); self.cmux_inplace(b, a, &k.get_bit(i + bit_rsh), scratch_1);

View File

@@ -121,6 +121,7 @@ where
&mut res, &mut res,
&scalar, &scalar,
&k_enc_prep, &k_enc_prep,
false,
bit_start, bit_start,
bit_size, bit_size,
bit_step, bit_step,

View File

@@ -106,6 +106,7 @@ where
&mut res, &mut res,
&test_glwe, &test_glwe,
&k_enc_prep, &k_enc_prep,
false,
bit_start, bit_start,
bit_size, bit_size,
bit_step, bit_step,