mirror of
https://github.com/Sunscreen-tech/Sunscreen.git
synced 2026-01-10 22:28:14 -05:00
Rweber/overlay size (#394)
Add methods to check if entities are correct size. Update aligned-vec version to incorporate upstreamed security fix.
This commit is contained in:
71
Cargo.lock
generated
71
Cargo.lock
generated
@@ -40,10 +40,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aligned-vec"
|
||||
version = "0.5.0"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1"
|
||||
checksum = "af15ccceeacb9304119d97925de463bc97ae3555ee8dc8056f67b119f66e5934"
|
||||
dependencies = [
|
||||
"equator",
|
||||
"serde",
|
||||
]
|
||||
|
||||
@@ -293,7 +294,7 @@ dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.11.0",
|
||||
"log",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
@@ -301,7 +302,7 @@ dependencies = [
|
||||
"regex",
|
||||
"rustc-hash 2.1.0",
|
||||
"shlex",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -845,7 +846,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e16e44ab292b1dddfdaf7be62cfd8877df52f2f3fde5858d95bab606be259f20"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"libloading 0.7.4",
|
||||
"libloading 0.8.1",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
@@ -870,7 +871,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -881,7 +882,7 @@ checksum = "c5a91391accf613803c2a9bf9abccdbaa07c54b4244a5b64883f9c3c137c86be"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -966,6 +967,26 @@ dependencies = [
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equator"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc"
|
||||
dependencies = [
|
||||
"equator-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equator-macro"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
@@ -1045,7 +1066,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1143,7 +1164,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2048,7 +2069,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2206,7 +2227,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2269,9 +2290,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -2688,7 +2709,7 @@ checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2960,7 +2981,7 @@ dependencies = [
|
||||
"semver",
|
||||
"serde",
|
||||
"static_assertions",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
@@ -2972,7 +2993,7 @@ dependencies = [
|
||||
"quote",
|
||||
"serde_json",
|
||||
"sunscreen_compiler_common",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
@@ -3044,7 +3065,7 @@ dependencies = [
|
||||
"num",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3129,9 +3150,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.49"
|
||||
version = "2.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496"
|
||||
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3218,7 +3239,7 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3462,7 +3483,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -3496,7 +3517,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@@ -3586,7 +3607,7 @@ dependencies = [
|
||||
"js-sys",
|
||||
"khronos-egl",
|
||||
"libc",
|
||||
"libloading 0.7.4",
|
||||
"libloading 0.8.1",
|
||||
"log",
|
||||
"metal",
|
||||
"naga",
|
||||
@@ -3897,7 +3918,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3917,5 +3938,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
@@ -38,7 +38,8 @@ lto = false
|
||||
codegen-units = 16
|
||||
|
||||
[workspace.dependencies]
|
||||
aligned-vec = { version = "0.5.0", features = ["serde"] }
|
||||
# We must have our upstreamed security fix that addresses a panic during bincode deserialization when the length is malformed or malicious.
|
||||
aligned-vec = { version = ">=0.6.2", features = ["serde"] }
|
||||
bytemuck = "1.13.0"
|
||||
raw-cpuid = "11.0.1"
|
||||
lazy_static = "1.4.0"
|
||||
@@ -60,8 +61,8 @@ find_cuda_helper = "0.2.0"
|
||||
criterion = { version = "0.5.1", default-features = false }
|
||||
darling = "0.20.3"
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0.32"
|
||||
syn = { version = "2.0.28", features = ["full"] }
|
||||
quote = "1"
|
||||
syn = { version = "2", features = ["full"] }
|
||||
petgraph = { version = "0.6.0", features = ["serde-1"] }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
static_assertions = "1.1.0"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::error::*;
|
||||
use crate::scratch::Pod;
|
||||
|
||||
macro_rules! avec {
|
||||
@@ -42,36 +43,52 @@ macro_rules! dst {
|
||||
*l = r.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> crate::dst::AsSlice<$wrapper<T>> for $ref_t<T> where T: Clone $(+ $t_bounds)* {
|
||||
#[allow(unused)]
|
||||
/// Returns a slice view of the data representing a $t.
|
||||
pub fn as_slice(&self) -> &[$wrapper<T>] {
|
||||
fn as_slice(&self) -> &[$wrapper<T>] {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
impl<T> crate::dst::AsMutSlice<$wrapper<T>> for $ref_t<T> where T: Clone $(+ $t_bounds)* {
|
||||
#[inline(always)]
|
||||
/// Returns a mutable slice view of the data representing a $t.
|
||||
pub fn as_mut_slice(&mut self) -> &mut [$wrapper<T>] {
|
||||
fn as_mut_slice(&mut self) -> &mut [$wrapper<T>] {
|
||||
&mut self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> crate::dst::FromSlice<$wrapper<T>> for $ref_t<T> where T: Clone $(+ $t_bounds)* {
|
||||
fn from_slice(s: &[$wrapper<T>]) -> &$ref_t<T> {
|
||||
// Casting the slice to the ref type is sound because it is #[repr(transparent)]
|
||||
unsafe { &*(s as *const [$wrapper<T>] as *const $ref_t<T>) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> crate::dst::FromMutSlice<$wrapper<T>> for $ref_t<T> where T: Clone $(+ $t_bounds)* {
|
||||
fn from_mut_slice(s: &mut [$wrapper<T>]) -> &mut $ref_t<T> {
|
||||
// Casting the mut slice to the mut ref type is sound because it is #[repr(transparent)]
|
||||
unsafe { &mut *(s as *mut [$wrapper<T>] as *mut $ref_t<T>) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> crate::dst::Len for $ref_t<T> where T: Clone $(+ $t_bounds)* {
|
||||
#[inline(always)]
|
||||
fn len(&self) -> usize {
|
||||
use crate::dst::AsSlice;
|
||||
|
||||
self.as_slice().len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> $ref_t<T> where T: Clone $(+ $t_bounds)*, $wrapper<T>: num::Zero {
|
||||
#[allow(unused)]
|
||||
/// Clears the contents of self to contain zero
|
||||
pub fn clear(&mut self) {
|
||||
use crate::dst::AsMutSlice;
|
||||
|
||||
for x in self.as_mut_slice() {
|
||||
*x = <$wrapper<T> as num::Zero>::zero();
|
||||
@@ -462,13 +479,50 @@ macro_rules! dst_iter {
|
||||
|
||||
pub type NoWrapper<T> = T;
|
||||
|
||||
pub(crate) trait AsSlice<T> {
|
||||
fn as_slice(&self) -> &[T];
|
||||
}
|
||||
|
||||
pub(crate) trait AsMutSlice<T> {
|
||||
fn as_mut_slice(&mut self) -> &mut [T];
|
||||
}
|
||||
|
||||
/// The length of an entity in fundamental elements (i.e. the type of polynomial coefficients in the underlying scheme).
|
||||
pub trait Len {
|
||||
/// Gets the length of this entity in fundamental elements.
|
||||
fn len(&self) -> usize;
|
||||
}
|
||||
|
||||
/// Describes how large an entity will be for the given parameters.
|
||||
pub trait OverlaySize {
|
||||
pub trait OverlaySize: Len {
|
||||
/// The inputs that determine this entity's size
|
||||
type Inputs: Copy + Clone;
|
||||
|
||||
/// Get the size of the entity.
|
||||
fn size(t: Self::Inputs) -> usize;
|
||||
|
||||
#[inline(always)]
|
||||
/// Returns if this entity is the correct length for the given input parameters
|
||||
fn check_is_valid(&self, t: Self::Inputs) -> Result<()> {
|
||||
if self.len() == Self::size(t) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::InvalidSize)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Panics if this entity is not of the correct length.
|
||||
fn assert_is_valid(&self, t: Self::Inputs) {
|
||||
self.check_is_valid(t)
|
||||
.expect("Entity was not the correct length.");
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Pod> Len for [S] {
|
||||
fn len(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Pod> OverlaySize for [S] {
|
||||
|
||||
@@ -2,7 +2,7 @@ use num::{Complex, Zero};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
dst::{NoWrapper, OverlaySize},
|
||||
dst::{AsMutSlice, AsSlice, NoWrapper, OverlaySize},
|
||||
entities::{
|
||||
GgswCiphertextFftIterator, GgswCiphertextFftIteratorMut, GgswCiphertextFftRef,
|
||||
GgswCiphertextIterator, GgswCiphertextIteratorMut, GgswCiphertextRef,
|
||||
|
||||
@@ -2,7 +2,7 @@ use num::{Complex, Zero};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
dst::{NoWrapper, OverlaySize},
|
||||
dst::{AsMutSlice, AsSlice, NoWrapper, OverlaySize},
|
||||
entities::{
|
||||
GgswCiphertextFftIterator, GgswCiphertextFftIteratorMut, GgswCiphertextFftRef,
|
||||
GgswCiphertextIterator, GgswCiphertextIteratorMut, GgswCiphertextRef,
|
||||
@@ -96,22 +96,13 @@ impl<S: TorusOps> BootstrapKeyRef<S> {
|
||||
glwe: &GlweDef,
|
||||
radix: &RadixDecomposition,
|
||||
) {
|
||||
self.assert_valid(lwe, glwe, radix);
|
||||
result.assert_valid(lwe, glwe, radix);
|
||||
self.assert_is_valid((lwe.dim, glwe.dim, radix.count));
|
||||
result.assert_is_valid((lwe.dim, glwe.dim, radix.count));
|
||||
|
||||
for (s, r) in self.rows(glwe, radix).zip(result.rows_mut(glwe, radix)) {
|
||||
s.fft(r, glwe, radix);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Asserts that this entity is valid under the passed parameters.
|
||||
pub fn assert_valid(&self, lwe: &LweDef, glwe: &GlweDef, radix: &RadixDecomposition) {
|
||||
assert_eq!(
|
||||
Self::size((lwe.dim, glwe.dim, radix.count)),
|
||||
self.data.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
dst! {
|
||||
@@ -184,13 +175,4 @@ impl BootstrapKeyFftRef<Complex<f64>> {
|
||||
s.ifft(r, params, radix);
|
||||
}
|
||||
}
|
||||
|
||||
/// Asserts that the [BootstrapKeyFft] is valid for the given parameters.
|
||||
#[inline(always)]
|
||||
pub fn assert_valid(&self, lwe: &LweDef, glwe: &GlweDef, radix: &RadixDecomposition) {
|
||||
assert_eq!(
|
||||
self.as_slice().len(),
|
||||
BootstrapKeyFftRef::size((lwe.dim, glwe.dim, radix.count))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@ use serde::{Deserialize, Serialize};
|
||||
use sunscreen_math::Zero;
|
||||
|
||||
use crate::{
|
||||
dst::OverlaySize, GlweDef, GlweDimension, LweDef, LweDimension,
|
||||
PrivateFunctionalKeyswitchLweCount, RadixCount, RadixDecomposition, Torus, TorusOps,
|
||||
dst::{AsMutSlice, AsSlice, OverlaySize},
|
||||
GlweDef, GlweDimension, LweDef, LweDimension, PrivateFunctionalKeyswitchLweCount, RadixCount,
|
||||
RadixDecomposition, Torus, TorusOps,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -117,17 +118,4 @@ impl<S: TorusOps> CircuitBootstrappingKeyswitchKeysRef<S> {
|
||||
|
||||
ParallelPrivateFunctionalKeyswitchKeyIterMut::new(self.as_mut_slice(), stride)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Assert these keys are valid under the given parameters.
|
||||
pub fn assert_valid(&self, from_lwe: &LweDef, to_glwe: &GlweDef, radix: &RadixDecomposition) {
|
||||
assert_eq!(
|
||||
self.as_slice().len(),
|
||||
CircuitBootstrappingKeyswitchKeysRef::<S>::size((
|
||||
from_lwe.dim,
|
||||
to_glwe.dim,
|
||||
radix.count,
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,17 +101,11 @@ where
|
||||
params: &GlweDef,
|
||||
radix: &RadixDecomposition,
|
||||
) {
|
||||
self.assert_valid(params, radix);
|
||||
result.assert_valid(params, radix);
|
||||
self.assert_is_valid((params.dim, radix.count));
|
||||
result.assert_is_valid((params.dim, radix.count));
|
||||
|
||||
for (s, r) in self.rows(params, radix).zip(result.rows_mut(params, radix)) {
|
||||
s.fft(r, params);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Assert that the GGSW ciphertext is valid for the given parameters.
|
||||
pub fn assert_valid(&self, glwe: &GlweDef, radix: &RadixDecomposition) {
|
||||
assert_eq!(self.as_slice().len(), Self::size((glwe.dim, radix.count)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use num::{Complex, Zero};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
dst::{NoWrapper, OverlaySize},
|
||||
dst::{AsMutSlice, AsSlice, NoWrapper, OverlaySize},
|
||||
entities::GgswCiphertextRef,
|
||||
GlweDef, GlweDimension, RadixCount, RadixDecomposition, TorusOps,
|
||||
};
|
||||
@@ -76,10 +76,4 @@ impl GgswCiphertextFftRef<Complex<f64>> {
|
||||
s.ifft(r, params);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Asserts that this entity is valid under the passed parameters.
|
||||
pub fn assert_valid(&self, glwe: &GlweDef, radix: &RadixDecomposition) {
|
||||
assert_eq!(Self::size((glwe.dim, radix.count)), self.data.len());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,12 +71,4 @@ where
|
||||
i.fft(fft, params);
|
||||
}
|
||||
}
|
||||
|
||||
/// Assert that this entityt is valid.
|
||||
pub fn assert_valid(&self, params: &GlweDef, radix: &RadixDecomposition) {
|
||||
assert_eq!(
|
||||
self.data.len(),
|
||||
GlevCiphertextRef::<S>::size((params.dim, radix.count))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,8 +139,8 @@ where
|
||||
|
||||
/// Create an FFT transformed version of `self` stored to result.
|
||||
pub fn fft(&self, result: &mut GlweCiphertextFftRef<Complex<f64>>, params: &GlweDef) {
|
||||
self.assert_valid(params);
|
||||
result.assert_valid(params);
|
||||
self.assert_is_valid(params.dim);
|
||||
result.assert_is_valid(params.dim);
|
||||
|
||||
for (a, fft) in self.a(params).zip(result.a_mut(params)) {
|
||||
a.fft(fft);
|
||||
@@ -149,15 +149,6 @@ where
|
||||
self.b(params).fft(result.b_mut(params));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Asserts that this entity is valid for the given `params`
|
||||
pub fn assert_valid(&self, params: &GlweDef) {
|
||||
assert_eq!(
|
||||
self.as_slice().len(),
|
||||
GlweCiphertextRef::<S>::size(params.dim)
|
||||
)
|
||||
}
|
||||
|
||||
/// Sets all coefficients of the polynomial at the specified index in the
|
||||
/// GLWE ciphertext's mask (a) to zero.
|
||||
///
|
||||
|
||||
@@ -2,7 +2,7 @@ use num::{complex::Complex64, Complex, Zero};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
dst::{FromMutSlice, FromSlice, NoWrapper, OverlaySize},
|
||||
dst::{AsMutSlice, AsSlice, FromMutSlice, FromSlice, NoWrapper, OverlaySize},
|
||||
GlweDef, GlweDimension, TorusOps,
|
||||
};
|
||||
|
||||
@@ -109,12 +109,6 @@ impl GlweCiphertextFftRef<Complex<f64>> {
|
||||
|
||||
self.b(params).ifft(result.b_mut(params));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Asserts this entity is valid for the given `params`.
|
||||
pub fn assert_valid(&self, params: &GlweDef) {
|
||||
assert_eq!(Self::size(params.dim), self.data.len());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -100,7 +100,7 @@ where
|
||||
{
|
||||
params.assert_valid();
|
||||
assert!(plaintext_bits.0 < S::BITS);
|
||||
ct.assert_valid(params);
|
||||
ct.assert_is_valid(params.dim);
|
||||
|
||||
let mut result = Polynomial::zero(ct.a_b(params).1.len());
|
||||
|
||||
@@ -156,15 +156,6 @@ where
|
||||
pub fn to_lwe_secret_key(&self) -> &LweSecretKeyRef<S> {
|
||||
LweSecretKeyRef::from_slice(&self.data)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Asserts that this entity is valid for the given `params`
|
||||
pub fn assert_valid(&self, params: &GlweDef) {
|
||||
assert_eq!(
|
||||
self.as_slice().len(),
|
||||
GlweSecretKeyRef::<S>::size(params.dim)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> GlweSecretKeyRef<S>
|
||||
|
||||
@@ -92,15 +92,6 @@ impl<S: TorusOps> LweCiphertextRef<S> {
|
||||
|
||||
b
|
||||
}
|
||||
|
||||
/// Asserts that the LWE ciphertext is valid for a given LWE dimension.
|
||||
#[inline(always)]
|
||||
pub fn assert_valid(&self, params: &LweDef) {
|
||||
assert_eq!(
|
||||
self.as_slice().len(),
|
||||
LweCiphertextRef::<S>::size(params.dim)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sunscreen_math::Zero;
|
||||
|
||||
use crate::{dst::OverlaySize, LweDef, LweDimension, Torus, TorusOps};
|
||||
use crate::{
|
||||
dst::{AsMutSlice, AsSlice, OverlaySize},
|
||||
LweDef, LweDimension, Torus, TorusOps,
|
||||
};
|
||||
|
||||
use super::{LweCiphertextIterator, LweCiphertextIteratorMut, LweCiphertextRef};
|
||||
|
||||
|
||||
@@ -80,20 +80,6 @@ where
|
||||
|
||||
LevCiphertextIteratorMut::new(&mut self.data, stride)
|
||||
}
|
||||
|
||||
/// Asserts that the keyswitch key is valid for the given parameters.
|
||||
#[inline(always)]
|
||||
pub fn assert_valid(
|
||||
&self,
|
||||
original_params: &LweDef,
|
||||
new_params: &LweDef,
|
||||
radix: &RadixDecomposition,
|
||||
) {
|
||||
assert_eq!(
|
||||
self.as_slice().len(),
|
||||
LweKeyswitchKeyRef::<S>::size((original_params.dim, new_params.dim, radix.count))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -52,7 +52,7 @@ where
|
||||
/// then using the resulting ciphertext as the public key.
|
||||
pub fn generate(sk: &LweSecretKeyRef<S>, params: &LweDef) -> Self {
|
||||
params.assert_valid();
|
||||
sk.assert_valid(params);
|
||||
sk.assert_is_valid(params.dim);
|
||||
|
||||
let mut pk = LwePublicKey {
|
||||
data: avec![Torus::zero(); LwePublicKeyRef::<S>::size(params.dim)],
|
||||
@@ -90,7 +90,7 @@ where
|
||||
plaintext_bits: PlaintextBits,
|
||||
) -> (LweCiphertext<S>, TlwePublicEncRandomness<S>) {
|
||||
params.assert_valid();
|
||||
self.assert_valid(params);
|
||||
self.assert_is_valid(params.dim);
|
||||
assert!(plaintext_bits.0 < S::BITS);
|
||||
|
||||
let msg = Torus::<S>::encode(msg, plaintext_bits);
|
||||
@@ -129,12 +129,6 @@ where
|
||||
|
||||
(acc, noise)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Assert this entity is valid under the given `lwe`.
|
||||
pub fn assert_valid(&self, lwe: &LweDef) {
|
||||
assert_eq!(Self::size(lwe.dim), self.data.len());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -91,7 +91,7 @@ where
|
||||
/// [Self::decrypt] for a function that performs the decoding automatically.
|
||||
pub fn decrypt_without_decode(&self, ct: &LweCiphertextRef<S>, params: &LweDef) -> Torus<S> {
|
||||
params.assert_valid();
|
||||
ct.assert_valid(params);
|
||||
ct.assert_is_valid(params.dim);
|
||||
|
||||
let (a, b) = ct.a_b(params);
|
||||
|
||||
@@ -116,20 +116,12 @@ where
|
||||
) -> S {
|
||||
params.assert_valid();
|
||||
assert!(plaintext_bits.0 < S::BITS);
|
||||
ct.assert_valid(params);
|
||||
ct.assert_is_valid(params.dim);
|
||||
|
||||
let msg = self.decrypt_without_decode(ct, params);
|
||||
|
||||
msg.decode(plaintext_bits)
|
||||
}
|
||||
|
||||
/// Asserts that a given secret key is valid for a given LWE dimension.
|
||||
pub fn assert_valid(&self, params: &LweDef) {
|
||||
assert_eq!(
|
||||
self.as_slice().len(),
|
||||
LweSecretKeyRef::<S>::size(params.dim)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> LweSecretKeyRef<S>
|
||||
|
||||
@@ -7,7 +7,7 @@ use num::{Complex, Zero};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
dst::{FromMutSlice, FromSlice, NoWrapper, OverlaySize},
|
||||
dst::{AsMutSlice, FromMutSlice, FromSlice, NoWrapper, OverlaySize},
|
||||
fft::negacyclic::get_fft,
|
||||
polynomial::{polynomial_add_assign, polynomial_external_mad, polynomial_sub_assign},
|
||||
scratch::allocate_scratch,
|
||||
@@ -133,12 +133,6 @@ where
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.data.is_empty()
|
||||
}
|
||||
|
||||
/// Asserts that this polynomial is valid for the given degree.
|
||||
#[inline]
|
||||
pub fn assert_valid(&self, degree: PolynomialDegree) {
|
||||
assert_eq!(self.degree(), degree);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PolynomialRef<T>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use num::Complex;
|
||||
|
||||
use crate::{
|
||||
dst::{NoWrapper, OverlaySize},
|
||||
dst::{AsMutSlice, AsSlice, NoWrapper, OverlaySize},
|
||||
fft::negacyclic::get_fft,
|
||||
scratch::allocate_scratch,
|
||||
simd, FrequencyTransform, FromF64, NumBits, PolynomialDegree,
|
||||
|
||||
@@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
||||
use sunscreen_math::Zero;
|
||||
|
||||
use crate::{
|
||||
dst::OverlaySize,
|
||||
dst::{AsMutSlice, AsSlice, OverlaySize},
|
||||
entities::{GlevCiphertextIterator, GlevCiphertextIteratorMut, GlevCiphertextRef},
|
||||
GlweDef, GlweDimension, LweDef, LweDimension, PrivateFunctionalKeyswitchLweCount, RadixCount,
|
||||
RadixDecomposition, Torus, TorusOps,
|
||||
@@ -113,24 +113,4 @@ impl<S: TorusOps> PrivateFunctionalKeyswitchKeyRef<S> {
|
||||
GlevCiphertextRef::<S>::size((to_glwe.dim, radix.count)),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Assert this value is correct for the given parameters.
|
||||
pub fn assert_valid(
|
||||
&self,
|
||||
from_lwe: &LweDef,
|
||||
to_glwe: &GlweDef,
|
||||
radix: &RadixDecomposition,
|
||||
lwe_count: &PrivateFunctionalKeyswitchLweCount,
|
||||
) {
|
||||
assert_eq!(
|
||||
self.as_slice().len(),
|
||||
PrivateFunctionalKeyswitchKeyRef::<S>::size((
|
||||
from_lwe.dim,
|
||||
to_glwe.dim,
|
||||
radix.count,
|
||||
*lwe_count
|
||||
))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
||||
use sunscreen_math::Zero;
|
||||
|
||||
use crate::{
|
||||
dst::OverlaySize,
|
||||
dst::{AsMutSlice, AsSlice, OverlaySize},
|
||||
entities::{GlevCiphertextIterator, GlevCiphertextIteratorMut, GlevCiphertextRef},
|
||||
GlweDef, GlweDimension, LweDef, LweDimension, RadixCount, RadixDecomposition, Torus, TorusOps,
|
||||
};
|
||||
@@ -63,12 +63,4 @@ impl<S: TorusOps> PublicFunctionalKeyswitchKeyRef<S> {
|
||||
|
||||
GlevCiphertextIteratorMut::new(self.as_mut_slice(), stride)
|
||||
}
|
||||
|
||||
/// Asserts that the key is valid for the given parameters.
|
||||
pub fn assert_valid(&self, from_lwe: &LweDef, to_glwe: &GlweDef, radix: &RadixDecomposition) {
|
||||
assert_eq!(
|
||||
self.as_slice().len(),
|
||||
PublicFunctionalKeyswitchKeyRef::<S>::size((from_lwe.dim, to_glwe.dim, radix.count))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,12 +63,4 @@ where
|
||||
|
||||
(p0.next().unwrap(), p1)
|
||||
}
|
||||
|
||||
/// Asserts this (`RlwePublicKey`)[RlwePublicKey] matches the given glwe parameters.
|
||||
pub fn assert_valid(&self, glwe: &GlweDef) {
|
||||
assert_eq!(
|
||||
self.as_slice().len(),
|
||||
GlweCiphertextRef::<S>::size(glwe.dim)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,8 +177,8 @@ where
|
||||
params: &GlweDef,
|
||||
radix: &RadixDecomposition,
|
||||
) {
|
||||
self.assert_valid(params, radix);
|
||||
result.assert_valid(params, radix);
|
||||
self.assert_is_valid((params.dim, radix.count));
|
||||
result.assert_is_valid((params.dim, radix.count));
|
||||
|
||||
for (s, r) in self
|
||||
.glev_ciphertexts(params, radix)
|
||||
@@ -187,12 +187,6 @@ where
|
||||
s.fft(r, params);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Asserts that this entity is valid under the passed parameters.
|
||||
pub fn assert_valid(&self, params: &GlweDef, radix: &RadixDecomposition) {
|
||||
assert_eq!(Self::size((params.dim, radix.count)), self.data.len());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -2,7 +2,7 @@ use num::{Complex, Zero};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
dst::{NoWrapper, OverlaySize},
|
||||
dst::{AsMutSlice, AsSlice, NoWrapper, OverlaySize},
|
||||
entities::SchemeSwitchKeyRef,
|
||||
GlweDef, GlweDimension, RadixCount, RadixDecomposition, TorusOps,
|
||||
};
|
||||
@@ -157,10 +157,4 @@ impl SchemeSwitchKeyFftRef<Complex<f64>> {
|
||||
s.ifft(r, params);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Asserts that this entity is valid under the passed parameters.
|
||||
pub fn assert_valid(&self, glwe: &GlweDef, radix: &RadixDecomposition) {
|
||||
assert_eq!(Self::size((glwe.dim, radix.count)), self.data.len());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,10 +109,4 @@ impl<S: TorusOps> UnivariateLookupTableRef<S> {
|
||||
*o = Torus::encode(val, plaintext_bits);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Asserts this LUT is valid under the given [`GlweDef`] parameters.
|
||||
pub fn assert_valid(&self, glwe: &GlweDef) {
|
||||
assert_eq!(Self::size(glwe.dim), self.data.len());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
#[derive(thiserror::Error)]
|
||||
/// Errors that can occur using this crate.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
OutOfRange
|
||||
}
|
||||
/// The size of the given entity is invalid under the given scheme parameters.
|
||||
#[error("The given entity is the incorrect size for the requested parameters.")]
|
||||
InvalidSize,
|
||||
}
|
||||
|
||||
/// A result that can occur in this crate.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
@@ -37,3 +37,7 @@ pub mod high_level;
|
||||
/// Zero Knowledge proofs for TFHE.
|
||||
#[cfg(feature = "logproof")]
|
||||
pub mod zkp;
|
||||
|
||||
/// Container [`Error`] and [`Result`] types for this crate.
|
||||
mod error;
|
||||
pub use error::*;
|
||||
|
||||
@@ -6,7 +6,10 @@ use std::{
|
||||
use num::traits::MulAdd;
|
||||
|
||||
use crate::{
|
||||
dst::FromMutSlice, entities::PolynomialRef, scratch::allocate_scratch, ToF64, Torus, TorusOps,
|
||||
dst::{AsMutSlice, AsSlice, FromMutSlice},
|
||||
entities::PolynomialRef,
|
||||
scratch::allocate_scratch,
|
||||
ToF64, Torus, TorusOps,
|
||||
};
|
||||
|
||||
/// Polynomial subtraction in place. This is equivalent to `a -= b` for each
|
||||
|
||||
@@ -13,8 +13,8 @@ use crate::{
|
||||
keyswitch::private_functional_keyswitch::private_functional_keyswitch,
|
||||
},
|
||||
scratch::allocate_scratch_ref,
|
||||
GlweDef, LweDef, PlaintextBits, PrivateFunctionalKeyswitchLweCount, RadixDecomposition, Torus,
|
||||
TorusOps,
|
||||
GlweDef, LweDef, OverlaySize, PlaintextBits, PrivateFunctionalKeyswitchLweCount,
|
||||
RadixDecomposition, Torus, TorusOps,
|
||||
};
|
||||
|
||||
/// Bootstraps a LWE ciphertext to a GGSW ciphertext.
|
||||
@@ -163,10 +163,10 @@ pub fn circuit_bootstrap<S: TorusOps>(
|
||||
pbs_radix.assert_valid::<S>();
|
||||
cbs_radix.assert_valid::<S>();
|
||||
pfks_radix.assert_valid::<S>();
|
||||
cbsksk.assert_valid(&glwe_2.as_lwe_def(), glwe_1, pfks_radix);
|
||||
bsk.assert_valid(lwe_0, glwe_2, pbs_radix);
|
||||
output.assert_valid(glwe_1, cbs_radix);
|
||||
input.assert_valid(lwe_0);
|
||||
cbsksk.assert_is_valid((glwe_2.as_lwe_def().dim, glwe_1.dim, pfks_radix.count));
|
||||
bsk.assert_is_valid((lwe_0.dim, glwe_2.dim, pbs_radix.count));
|
||||
output.assert_is_valid((glwe_1.dim, cbs_radix.count));
|
||||
input.assert_is_valid(lwe_0.dim);
|
||||
|
||||
// Step 1, for each l in cbs_radix.count, use bootstrapping to base decompose the
|
||||
// plaintext in input. We bootstrap from level 0 -> level 2.
|
||||
|
||||
@@ -18,7 +18,7 @@ use crate::{
|
||||
fft_ops::cmux,
|
||||
},
|
||||
scratch::allocate_scratch_ref,
|
||||
CarryBits, GlweDef, LweDef, PlaintextBits, RadixDecomposition, Torus, TorusOps,
|
||||
CarryBits, GlweDef, LweDef, OverlaySize, PlaintextBits, RadixDecomposition, Torus, TorusOps,
|
||||
};
|
||||
|
||||
use super::rotate_glwe_negative_monomial_negacyclic;
|
||||
@@ -44,9 +44,9 @@ pub fn generate_bootstrap_key<S>(
|
||||
lwe.assert_valid();
|
||||
glwe.assert_valid();
|
||||
radix.assert_valid::<S>();
|
||||
bootstrap_key.assert_valid(lwe, glwe, radix);
|
||||
sk.assert_valid(glwe);
|
||||
sk_to_encrypt.assert_valid(lwe);
|
||||
bootstrap_key.assert_is_valid((lwe.dim, glwe.dim, radix.count));
|
||||
sk.assert_is_valid(glwe.dim);
|
||||
sk_to_encrypt.assert_is_valid(lwe.dim);
|
||||
|
||||
sk_to_encrypt
|
||||
.s()
|
||||
@@ -352,10 +352,10 @@ pub fn generalized_programmable_bootstrap<S>(
|
||||
lwe_params.assert_valid();
|
||||
glwe_params.assert_valid();
|
||||
radix.assert_valid::<S>();
|
||||
bootstrap_key.assert_valid(lwe_params, glwe_params, radix);
|
||||
lut.assert_valid(glwe_params);
|
||||
input.assert_valid(lwe_params);
|
||||
output.assert_valid(glwe_params);
|
||||
bootstrap_key.assert_is_valid((lwe_params.dim, glwe_params.dim, radix.count));
|
||||
lut.assert_is_valid(glwe_params.dim);
|
||||
input.assert_is_valid(lwe_params.dim);
|
||||
output.assert_is_valid(glwe_params.dim);
|
||||
|
||||
// Steps:
|
||||
// 1. Modulus switch the ciphertext to 2N.
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
dst::FromMutSlice,
|
||||
dst::{AsSlice, FromMutSlice},
|
||||
entities::{
|
||||
GgswCiphertextRef, GlevCiphertextRef, GlweCiphertextRef, GlweSecretKeyRef, Polynomial,
|
||||
PolynomialFft, PolynomialRef, SchemeSwitchKeyRef,
|
||||
@@ -13,7 +13,7 @@ use crate::{
|
||||
ops::{ciphertext::decomposed_polynomial_glev_mad, encryption::encrypt_secret_glev_ciphertext},
|
||||
radix::PolynomialRadixIterator,
|
||||
scratch::allocate_scratch_ref,
|
||||
GlweDef, RadixDecomposition, Torus, TorusOps,
|
||||
GlweDef, OverlaySize, RadixDecomposition, Torus, TorusOps,
|
||||
};
|
||||
use num::{Complex, Zero};
|
||||
|
||||
@@ -33,8 +33,8 @@ pub fn generate_scheme_switch_key<S>(
|
||||
params.assert_valid();
|
||||
radix.assert_valid::<S>();
|
||||
|
||||
scheme_switch_key.assert_valid(params, radix);
|
||||
sk.assert_valid(params);
|
||||
scheme_switch_key.assert_is_valid((params.dim, radix.count));
|
||||
sk.assert_is_valid(params.dim);
|
||||
|
||||
let polynomial_size = params.dim.polynomial_degree.0;
|
||||
|
||||
@@ -261,9 +261,9 @@ pub fn scheme_switch<S>(
|
||||
) where
|
||||
S: TorusOps,
|
||||
{
|
||||
ssk.assert_valid(params, radix_ss);
|
||||
output.assert_valid(params, radix_ggsw);
|
||||
glev_ciphertext.assert_valid(params, radix_ggsw);
|
||||
ssk.assert_is_valid((params.dim, radix_ss.count));
|
||||
output.assert_is_valid((params.dim, radix_ggsw.count));
|
||||
glev_ciphertext.assert_is_valid((params.dim, radix_ggsw.count));
|
||||
|
||||
let k = params.dim.size.0;
|
||||
|
||||
@@ -417,7 +417,7 @@ mod tests {
|
||||
generate_scheme_switch_key(&mut ssk, &sk, ¶ms, &radix);
|
||||
|
||||
// Basic validity checks
|
||||
ssk.assert_valid(¶ms, &radix);
|
||||
ssk.assert_is_valid((params.dim, radix.count));
|
||||
|
||||
// Check dimensions
|
||||
let expected_glev_count = (glwe_size * (glwe_size + 1)) / 2;
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
},
|
||||
radix::PolynomialRadixIterator,
|
||||
scratch::allocate_scratch_ref,
|
||||
GlweDef, RadixDecomposition, TorusOps,
|
||||
GlweDef, OverlaySize, RadixDecomposition, TorusOps,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -36,7 +36,7 @@ pub fn sample_extract<S>(
|
||||
) where
|
||||
S: TorusOps,
|
||||
{
|
||||
glwe.assert_valid(params);
|
||||
glwe.assert_is_valid(params.dim);
|
||||
assert!(h < params.dim.polynomial_degree.0);
|
||||
|
||||
// We are copying parts of the GLWE ciphertext out according to the following rule:
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
ops::encryption::encrypt_secret_glev_ciphertext_generic,
|
||||
polynomial::polynomial_external_mad,
|
||||
scratch::allocate_scratch_ref,
|
||||
GlweDef, PlaintextBits, RadixDecomposition, Torus, TorusOps,
|
||||
GlweDef, OverlaySize, PlaintextBits, RadixDecomposition, Torus, TorusOps,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -172,8 +172,8 @@ pub fn decrypt_ggsw_ciphertext<S>(
|
||||
assert_eq!(msg.len(), params.dim.polynomial_degree.0);
|
||||
params.assert_valid();
|
||||
radix.assert_valid::<S>();
|
||||
ggsw_ciphertext.assert_valid(params, radix);
|
||||
glwe_secret_key.assert_valid(params);
|
||||
ggsw_ciphertext.assert_is_valid((params.dim, radix.count));
|
||||
glwe_secret_key.assert_is_valid(params.dim);
|
||||
|
||||
// To decrypt a GGSW ciphertext, it suffices to decrypt the first GLWE
|
||||
// ciphertext in the last row. We can decrypt any of the GLWE ciphertexts in
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::{
|
||||
ops::encryption::rlwe_encrypt_public,
|
||||
polynomial::polynomial_scalar_mul,
|
||||
scratch::allocate_scratch_ref,
|
||||
GlweDef, RadixDecomposition, Torus, TorusOps,
|
||||
GlweDef, OverlaySize, RadixDecomposition, Torus, TorusOps,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -36,9 +36,9 @@ pub(crate) fn encrypt_secret_glev_ciphertext_generic<S>(
|
||||
S: TorusOps,
|
||||
{
|
||||
radix.assert_valid::<S>();
|
||||
glev_ciphertext.assert_valid(params, radix);
|
||||
msg.assert_valid(params.dim.polynomial_degree);
|
||||
glwe_secret_key.assert_valid(params);
|
||||
glev_ciphertext.assert_is_valid((params.dim, radix.count));
|
||||
msg.assert_is_valid(params.dim.polynomial_degree);
|
||||
glwe_secret_key.assert_is_valid(params.dim);
|
||||
|
||||
let decomposition_radix_log = radix.radix_log.0;
|
||||
|
||||
@@ -142,9 +142,9 @@ pub fn encrypt_rlev_ciphertext<S>(
|
||||
S: TorusOps,
|
||||
{
|
||||
radix.assert_valid::<S>();
|
||||
msg.assert_valid(params.dim.polynomial_degree);
|
||||
rlev_ciphertext.assert_valid(params, radix);
|
||||
rlwe_public_key.assert_valid(params);
|
||||
msg.assert_is_valid(params.dim.polynomial_degree);
|
||||
rlev_ciphertext.assert_is_valid((params.dim, radix.count));
|
||||
rlwe_public_key.assert_is_valid(params.dim);
|
||||
|
||||
allocate_scratch_ref!(
|
||||
scaled_msg,
|
||||
@@ -172,10 +172,10 @@ pub(crate) fn decrypt_glwe_in_glev<S>(
|
||||
S: TorusOps,
|
||||
{
|
||||
radix.assert_valid::<S>();
|
||||
msg.assert_valid(params.dim.polynomial_degree);
|
||||
msg.assert_is_valid(params.dim.polynomial_degree);
|
||||
params.assert_valid();
|
||||
glev_ciphertext.assert_valid(params, radix);
|
||||
glwe_secret_key.assert_valid(params);
|
||||
glev_ciphertext.assert_is_valid((params.dim, radix.count));
|
||||
glwe_secret_key.assert_is_valid(params.dim);
|
||||
|
||||
let decomposition_radix_log = radix.radix_log.0;
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use sunscreen_math::Zero;
|
||||
|
||||
use crate::{
|
||||
dst::AsSlice,
|
||||
entities::{LweCiphertextRef, LweSecretKeyRef},
|
||||
math::{Torus, TorusOps},
|
||||
rand::{normal_torus, uniform_torus},
|
||||
LweDef, PlaintextBits,
|
||||
LweDef, OverlaySize, PlaintextBits,
|
||||
};
|
||||
|
||||
/// Generate a trivial GLWE encryption. Note that the caller will need to scale
|
||||
@@ -17,7 +18,7 @@ pub fn trivially_encrypt_lwe_ciphertext<S>(
|
||||
S: TorusOps,
|
||||
{
|
||||
params.assert_valid();
|
||||
c.assert_valid(params);
|
||||
c.assert_is_valid(params.dim);
|
||||
|
||||
let (a, b) = c.a_b_mut(params);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
polynomial::{polynomial_add_assign, polynomial_external_mad},
|
||||
rand::{binary_torus_polynomial, normal_torus_polynomial},
|
||||
scratch::allocate_scratch_ref,
|
||||
GlweDef, PlaintextBits, Torus, TorusOps,
|
||||
GlweDef, OverlaySize, PlaintextBits, Torus, TorusOps,
|
||||
};
|
||||
|
||||
/// The randomness used to generate a public-key RLWE encryption of a message.
|
||||
@@ -133,8 +133,8 @@ where
|
||||
{
|
||||
assert_eq!(glwe.dim.size.0, 1);
|
||||
assert_eq!(encoded_msg.len(), glwe.dim.polynomial_degree.0);
|
||||
ct.assert_valid(glwe);
|
||||
public_key.assert_valid(glwe);
|
||||
ct.assert_is_valid(glwe.dim);
|
||||
public_key.assert_is_valid(glwe.dim);
|
||||
|
||||
ct.clear();
|
||||
|
||||
|
||||
@@ -154,10 +154,10 @@ pub fn cmux<S>(
|
||||
{
|
||||
params.assert_valid();
|
||||
radix.assert_valid::<S>();
|
||||
c.assert_valid(params);
|
||||
d_0.assert_valid(params);
|
||||
d_1.assert_valid(params);
|
||||
b_fft.assert_valid(params, radix);
|
||||
c.assert_is_valid(params.dim);
|
||||
d_0.assert_is_valid(params.dim);
|
||||
d_1.assert_is_valid(params.dim);
|
||||
b_fft.assert_is_valid((params.dim, radix.count));
|
||||
|
||||
allocate_scratch_ref!(diff, GlweCiphertextRef<S>, (params.dim));
|
||||
|
||||
@@ -406,9 +406,9 @@ pub fn scheme_switch_fft<S>(
|
||||
) where
|
||||
S: TorusOps,
|
||||
{
|
||||
ssk_fft.assert_valid(params, radix_ss);
|
||||
output.assert_valid(params, radix_ggsw);
|
||||
glev_ciphertext.assert_valid(params, radix_ggsw);
|
||||
ssk_fft.assert_is_valid((params.dim, radix_ss.count));
|
||||
output.assert_is_valid((params.dim, radix_ggsw.count));
|
||||
glev_ciphertext.assert_is_valid((params.dim, radix_ggsw.count));
|
||||
|
||||
let k = params.dim.size.0;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{entities::LweCiphertextRef, LweDef, Torus, TorusOps};
|
||||
use crate::{entities::LweCiphertextRef, LweDef, OverlaySize, Torus, TorusOps};
|
||||
|
||||
/// Add `amount` to each torus element (mod q) in the ciphertext.
|
||||
/// This shifts where messages lie on the torus and adds no noise.
|
||||
@@ -12,8 +12,8 @@ pub fn rotate<S: TorusOps>(
|
||||
amount: Torus<S>,
|
||||
lwe: &LweDef,
|
||||
) {
|
||||
output.assert_valid(lwe);
|
||||
input.assert_valid(lwe);
|
||||
output.assert_is_valid(lwe.dim);
|
||||
input.assert_is_valid(lwe.dim);
|
||||
|
||||
output.a_mut(lwe).clone_from_slice(input.a(lwe));
|
||||
*output.b_mut(lwe) = input.b(lwe) + amount;
|
||||
|
||||
@@ -94,7 +94,7 @@ pub fn generate_keyswitch_key_glwe<S>(
|
||||
mod tests {
|
||||
|
||||
use crate::{
|
||||
dst::FromSlice,
|
||||
dst::{AsSlice, FromSlice},
|
||||
entities::{GlweKeyswitchKey, GlweKeyswitchKeyRef},
|
||||
high_level::{TEST_GLWE_DEF_1, TEST_RADIX},
|
||||
Torus,
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
},
|
||||
radix::PolynomialRadixIterator,
|
||||
scratch::allocate_scratch_ref,
|
||||
LweDef, PolynomialDegree, RadixDecomposition, TorusOps,
|
||||
LweDef, OverlaySize, PolynomialDegree, RadixDecomposition, TorusOps,
|
||||
};
|
||||
|
||||
/// Switches a ciphertext under the original key to a ciphertext under the new
|
||||
@@ -33,9 +33,9 @@ pub fn keyswitch_lwe_to_lwe<S>(
|
||||
old_params.assert_valid();
|
||||
new_params.assert_valid();
|
||||
radix.assert_valid::<S>();
|
||||
output.assert_valid(new_params);
|
||||
ciphertext_under_original_key.assert_valid(old_params);
|
||||
keyswitch_key.assert_valid(old_params, new_params, radix);
|
||||
output.assert_is_valid(new_params.dim);
|
||||
ciphertext_under_original_key.assert_is_valid(old_params.dim);
|
||||
keyswitch_key.assert_is_valid((old_params.dim, new_params.dim, radix.count));
|
||||
|
||||
let (ciphertext_a, ciphertext_b) = ciphertext_under_original_key.a_b(old_params);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
entities::{LweKeyswitchKeyRef, LweSecretKeyRef},
|
||||
ops::encryption::encrypt_lwe_ciphertext,
|
||||
LweDef, RadixDecomposition, Torus, TorusOps,
|
||||
LweDef, OverlaySize, RadixDecomposition, Torus, TorusOps,
|
||||
};
|
||||
|
||||
/// Generates a keyswitch key from an original LWE key to a new LWE key. The
|
||||
@@ -26,10 +26,10 @@ pub fn generate_keyswitch_key_lwe<S>(
|
||||
old_params.assert_valid();
|
||||
new_params.assert_valid();
|
||||
radix.assert_valid::<S>();
|
||||
new_lwe_secret_key.assert_valid(new_params);
|
||||
original_lwe_secret_key.assert_valid(old_params);
|
||||
new_lwe_secret_key.assert_valid(new_params);
|
||||
keyswitch_key.assert_valid(old_params, new_params, radix);
|
||||
new_lwe_secret_key.assert_is_valid(new_params.dim);
|
||||
original_lwe_secret_key.assert_is_valid(old_params.dim);
|
||||
new_lwe_secret_key.assert_is_valid(new_params.dim);
|
||||
keyswitch_key.assert_is_valid((old_params.dim, new_params.dim, radix.count));
|
||||
|
||||
let decomposition_radix_log = radix.radix_log.0;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use rayon::iter::{IndexedParallelIterator, ParallelIterator};
|
||||
use sunscreen_math::Zero;
|
||||
|
||||
use crate::{
|
||||
dst::FromMutSlice,
|
||||
dst::{AsSlice, FromMutSlice},
|
||||
entities::{
|
||||
CircuitBootstrappingKeyswitchKeysRef, GlweCiphertextRef, GlweSecretKeyRef,
|
||||
LweCiphertextRef, LweSecretKeyRef, PolynomialRef, PrivateFunctionalKeyswitchKeyRef,
|
||||
@@ -13,7 +13,8 @@ use crate::{
|
||||
},
|
||||
radix::{scale_by_decomposition_factor, ScalarRadixIterator},
|
||||
scratch::allocate_scratch_ref,
|
||||
GlweDef, LweDef, PrivateFunctionalKeyswitchLweCount, RadixDecomposition, Torus, TorusOps,
|
||||
GlweDef, LweDef, OverlaySize, PrivateFunctionalKeyswitchLweCount, RadixDecomposition, Torus,
|
||||
TorusOps,
|
||||
};
|
||||
|
||||
/// Initialize `output`, a
|
||||
@@ -51,10 +52,10 @@ pub fn generate_private_functional_keyswitch_key<S, F>(
|
||||
S: TorusOps,
|
||||
F: Fn(&mut PolynomialRef<Torus<S>>, &[Torus<S>]),
|
||||
{
|
||||
output.assert_valid(from_lwe, to_glwe, radix, lwe_count);
|
||||
output.assert_is_valid((from_lwe.dim, to_glwe.dim, radix.count, *lwe_count));
|
||||
radix.assert_valid::<S>();
|
||||
from_key.assert_valid(from_lwe);
|
||||
to_key.assert_valid(to_glwe);
|
||||
from_key.assert_is_valid(from_lwe.dim);
|
||||
to_key.assert_is_valid(to_glwe.dim);
|
||||
to_glwe.assert_valid();
|
||||
from_lwe.assert_valid();
|
||||
lwe_count.assert_valid();
|
||||
@@ -101,8 +102,8 @@ pub fn private_functional_keyswitch<S: TorusOps>(
|
||||
radix: &RadixDecomposition,
|
||||
lwe_count: &PrivateFunctionalKeyswitchLweCount,
|
||||
) {
|
||||
output.assert_valid(to_glwe);
|
||||
pfksk.assert_valid(from_lwe, to_glwe, radix, lwe_count);
|
||||
output.assert_is_valid(to_glwe.dim);
|
||||
pfksk.assert_is_valid((from_lwe.dim, to_glwe.dim, radix.count, *lwe_count));
|
||||
from_lwe.assert_valid();
|
||||
to_glwe.assert_valid();
|
||||
radix.assert_valid::<S>();
|
||||
@@ -138,10 +139,10 @@ pub fn generate_circuit_bootstrapping_pfks_keys<S: TorusOps>(
|
||||
to_glwe: &GlweDef,
|
||||
radix: &RadixDecomposition,
|
||||
) {
|
||||
output.assert_valid(from_lwe, to_glwe, radix);
|
||||
from_key.assert_valid(from_lwe);
|
||||
output.assert_is_valid((from_lwe.dim, to_glwe.dim, radix.count));
|
||||
from_key.assert_is_valid(from_lwe.dim);
|
||||
to_glwe.assert_valid();
|
||||
to_key.assert_valid(to_glwe);
|
||||
to_key.assert_is_valid(to_glwe.dim);
|
||||
radix.assert_valid::<S>();
|
||||
from_lwe.assert_valid();
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@ use crate::ops::fft_ops::decomposed_polynomial_glev_mad;
|
||||
use crate::polynomial::polynomial_add_assign;
|
||||
use crate::radix::PolynomialRadixIterator;
|
||||
use crate::scratch::allocate_scratch;
|
||||
use crate::Torus;
|
||||
use crate::{
|
||||
entities::{GlweCiphertextFftRef, GlweSecretKeyRef, PublicFunctionalKeyswitchKeyRef},
|
||||
radix::scale_by_decomposition_factor,
|
||||
scratch::allocate_scratch_ref,
|
||||
GlweDef, LweDef, RadixDecomposition, TorusOps,
|
||||
};
|
||||
use crate::{OverlaySize, Torus};
|
||||
|
||||
/// Generate a public functional keyswitch key, which is used to transform a
|
||||
/// list of LWE ciphertexts into a GLWE ciphertext while applying a provided
|
||||
@@ -34,9 +34,9 @@ pub fn generate_public_functional_keyswitch_key<S: TorusOps>(
|
||||
to_glwe: &GlweDef,
|
||||
radix: &RadixDecomposition,
|
||||
) {
|
||||
from_sk.assert_valid(from_lwe);
|
||||
to_sk.assert_valid(to_glwe);
|
||||
output.assert_valid(from_lwe, to_glwe, radix);
|
||||
from_sk.assert_is_valid(from_lwe.dim);
|
||||
to_sk.assert_is_valid(to_glwe.dim);
|
||||
output.assert_is_valid((from_lwe.dim, to_glwe.dim, radix.count));
|
||||
|
||||
allocate_scratch_ref!(pt, PolynomialRef<Torus<S>>, (to_glwe.dim.polynomial_degree));
|
||||
pt.clear();
|
||||
@@ -83,11 +83,11 @@ pub fn public_functional_keyswitch<S, F>(
|
||||
S: TorusOps,
|
||||
F: Fn(&mut PolynomialRef<Torus<S>>, &[Torus<S>]),
|
||||
{
|
||||
pufksk.assert_valid(from_lwe, to_glwe, radix);
|
||||
output.assert_valid(to_glwe);
|
||||
pufksk.assert_is_valid((from_lwe.dim, to_glwe.dim, radix.count));
|
||||
output.assert_is_valid(to_glwe.dim);
|
||||
|
||||
for i in inputs {
|
||||
i.assert_valid(from_lwe);
|
||||
i.assert_is_valid(from_lwe.dim);
|
||||
}
|
||||
|
||||
assert!(inputs.len() <= to_glwe.dim.polynomial_degree.0);
|
||||
|
||||
Reference in New Issue
Block a user