docs(tfhe): add GlweCiphertext documentation

This commit is contained in:
Arthur Meyre
2022-12-07 17:18:58 +01:00
committed by jborfila
parent d274891948
commit e353af5a72
3 changed files with 152 additions and 19 deletions

View File

@@ -2,7 +2,7 @@ use crate::core_crypto::commons::parameters::*;
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
/// A GGSW Ciphertext.
/// A [`GGSW Ciphertext`](`GgswCiphertext`).
///
/// # Formal Definition
///

View File

@@ -2,12 +2,29 @@ use crate::core_crypto::commons::parameters::*;
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
/// A convenience structure to easily manipulate the body of a [`GlweCiphertext`].
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct GlweBody<C: Container> {
data: C,
}
impl<C: Container> GlweBody<C> {
/// Create a [`GlweBody`] from an existing container.
///
/// # Note
///
/// This docstring exhibits [`GlweBody`] primitives usage.
///
/// ```
/// use tfhe::core_crypto::prelude::*;
///
/// // Define parameters for GlweBody creation
/// let polynomial_size = PolynomialSize(1024);
///
/// let glwe_body = GlweBody::from_container(vec![0u64; polynomial_size.0]);
///
/// assert_eq!(glwe_body.polynomial_size(), polynomial_size);
/// ```
pub fn from_container(container: C) -> GlweBody<C> {
assert!(
container.container_len() > 0,
@@ -16,21 +33,27 @@ impl<C: Container> GlweBody<C> {
GlweBody { data: container }
}
/// Returns the [`PolynomialSize`] of the [`GlweBody`].
///
/// See [`GlweBody::from_container`] for usage.
pub fn polynomial_size(&self) -> PolynomialSize {
PolynomialSize(self.data.container_len())
}
/// Interprets the [`GlweBody`] as a [`Polynomial`].
pub fn as_polynomial(&self) -> PolynomialView<'_, C::Element> {
PolynomialView::from_container(self.as_ref())
}
}
impl<C: ContainerMut> GlweBody<C> {
/// Mutable variant of [`GlweBody::as_polynomial`].
pub fn as_mut_polynomial(&mut self) -> PolynomialMutView<'_, C::Element> {
PolynomialMutView::from_container(self.as_mut())
}
}
/// A convenience structure to easily manipulate the mask of a [`GlweCiphertext`].
#[derive(Clone, Debug)]
pub struct GlweMask<C: Container> {
data: C,
@@ -38,6 +61,24 @@ pub struct GlweMask<C: Container> {
}
impl<C: Container> GlweMask<C> {
/// Create a [`GlweMask`] from an existing container.
///
/// # Note
///
/// This docstring exhibits [`GlweMask`] primitives usage.
///
/// ```
/// use tfhe::core_crypto::prelude::*;
///
/// // Define parameters for GlweMask creation
/// let glwe_dimension = GlweDimension(1);
/// let polynomial_size = PolynomialSize(1024);
///
/// let glwe_mask = GlweMask::from_container(vec![0u64; glwe_dimension.0 * polynomial_size.0]);
///
/// assert_eq!(glwe_mask.glwe_dimension(), glwe_dimension);
/// assert_eq!(glwe_mask.polynomial_size(), polynomial_size);
/// ```
pub fn from_container(container: C, polynomial_size: PolynomialSize) -> Self {
assert!(
container.container_len() % polynomial_size.0 == 0,
@@ -52,20 +93,28 @@ impl<C: Container> GlweMask<C> {
}
}
pub fn polynomial_size(&self) -> PolynomialSize {
self.polynomial_size
}
/// Returns the [`GlweDimension`] of the [`GlweMask`].
///
/// See [`GlweMask::from_container`] for usage.
pub fn glwe_dimension(&self) -> GlweDimension {
GlweDimension(self.data.container_len() / self.polynomial_size.0)
}
/// Returns the [`PolynomialSize`] of the [`GlweMask`].
///
/// See [`GlweMask::from_container`] for usage.
pub fn polynomial_size(&self) -> PolynomialSize {
self.polynomial_size
}
/// Interprets the [`GlweMask`] as a [`PolynomialList`].
pub fn as_polynomial_list(&self) -> PolynomialListView<'_, C::Element> {
PolynomialListView::from_container(self.as_ref(), self.polynomial_size)
}
}
impl<C: ContainerMut> GlweMask<C> {
/// Mutable variant of [`GlweMask::as_polynomial_list`].
pub fn as_mut_polynomial_list(&mut self) -> PolynomialListMutView<'_, C::Element> {
let polynomial_size = self.polynomial_size;
PolynomialListMutView::from_container(self.as_mut(), polynomial_size)
@@ -96,17 +145,48 @@ impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GlweBody<C> {
}
}
/// Returns the number of elements in a [`GlweCiphertext`] given a [`GlweSize`] and
/// [`PolynomialSize`].
pub fn glwe_ciphertext_size(glwe_size: GlweSize, polynomial_size: PolynomialSize) -> usize {
glwe_size.0 * polynomial_size.0
}
/// Returns the number of elements in a [`GlweMask`] given a [`GlweDimension`] and
/// [`PolynomialSize`].
pub fn glwe_ciphertext_mask_size(
polynomial_size: PolynomialSize,
glwe_dimension: GlweDimension,
polynomial_size: PolynomialSize,
) -> usize {
polynomial_size.0 * glwe_dimension.0
glwe_dimension.0 * polynomial_size.0
}
/// A [`GLWE ciphertext`](`GlweCiphertext`).
///
/// **Remark:** GLWE ciphertexts generalize LWE ciphertexts by definition, however in this library,
/// GLWE ciphertext entities do not generalize LWE ciphertexts, i.e., polynomial size cannot be 1.
///
/// # Formal Definition
///
/// ## GLWE Ciphertext
///
/// A GLWE ciphertext is an encryption of a polynomial plaintext.
/// It is secure under the hardness assumption called General Learning With Errors (GLWE). It is a
/// generalization of both [`LWE ciphertexts`](`crate::core_crypto::entities::LweCiphertext`) and
/// RLWE ciphertexts. GLWE requires a cyclotomic ring. We use the notation $\mathcal{R}\_q$ for the
/// following cyclotomic ring: $\mathbb{Z}\_q\[X\]/\left\langle X^N + 1\right\rangle$ where
/// $N\in\mathbb{N}$ is a power of two.
///
/// We call $q$ the ciphertext modulus and $N$ the ring dimension.
///
/// We indicate a GLWE ciphertext of a plaintext $\mathsf{PT} \in\mathcal{R}\_q^{k+1}$ as the
/// following couple: $$\mathsf{CT} = \left( \vec{A}, B\right) = \left( A\_0, \ldots, A\_{k-1},
/// B\right) \in \mathsf{GLWE}\_{\vec{S}} \left( \mathsf{PT} \right) \subseteq
/// \mathcal{R}\_q^{k+1}$$
///
/// ## Generalisation of LWE and RLWE
///
/// When we set $k=1$ a GLWE ciphertext becomes an RLWE ciphertext.
/// When we set $N=1$ a GLWE ciphertext becomes an LWE ciphertext with $n=k$.
#[derive(Clone, Debug, PartialEq)]
pub struct GlweCiphertext<C: Container> {
data: C,
@@ -126,6 +206,34 @@ impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GlweCiphertext<C> {
}
impl<Scalar, C: Container<Element = Scalar>> GlweCiphertext<C> {
/// Create a [`GlweCiphertext`] from an existing container.
///
/// # Note
///
/// This docstring exhibits [`GlweCiphertext`] primitives usage.
///
/// ```
/// use tfhe::core_crypto::prelude::*;
///
/// // Define parameters for GlweCiphertext creation
/// let glwe_size = GlweSize(2);
/// let polynomial_size = PolynomialSize(1024);
///
/// // Create a new GlweCiphertext
/// let glwe = GlweCiphertext::new(0u64, glwe_size, polynomial_size);
///
/// assert_eq!(glwe.glwe_size(), glwe_size);
/// assert_eq!(glwe.polynomial_size(), polynomial_size);
///
/// // Demonstrate how to recover the allocated container
/// let underlying_container: Vec<u64> = glwe.into_container();
///
/// // Recreate a ciphertext using from_container
/// let glwe = GlweCiphertext::from_container(underlying_container, polynomial_size);
///
/// assert_eq!(glwe.glwe_size(), glwe_size);
/// assert_eq!(glwe.polynomial_size(), polynomial_size);
/// ```
pub fn from_container(container: C, polynomial_size: PolynomialSize) -> GlweCiphertext<C> {
assert!(
container.container_len() > 0,
@@ -144,18 +252,25 @@ impl<Scalar, C: Container<Element = Scalar>> GlweCiphertext<C> {
}
}
pub fn polynomial_size(&self) -> PolynomialSize {
self.polynomial_size
}
/// Returns the [`GlweSize`] of the [`GlweCiphertext`].
///
/// See [`GlweCiphertext::from_container`] for usage.
pub fn glwe_size(&self) -> GlweSize {
GlweSize(self.as_ref().container_len() / self.polynomial_size.0)
}
/// Returns the [`PolynomialSize`] of the [`GlweCiphertext`].
///
/// See [`GlweCiphertext::from_container`] for usage.
pub fn polynomial_size(&self) -> PolynomialSize {
self.polynomial_size
}
/// Returns immutable views to the [`GlweMask`] and [`GlweBody`] of a [`GlweCiphertext`].
pub fn get_mask_and_body(&self) -> (GlweMask<&[Scalar]>, GlweBody<&[Scalar]>) {
let (mask, body) = self.data.as_ref().split_at(glwe_ciphertext_mask_size(
self.polynomial_size,
self.glwe_size().to_glwe_dimension(),
self.polynomial_size,
));
(
@@ -164,29 +279,34 @@ impl<Scalar, C: Container<Element = Scalar>> GlweCiphertext<C> {
)
}
/// Returns an immutable view to the [`GlweBody`] of a [`GlweCiphertext`].
pub fn get_body(&self) -> GlweBody<&[Scalar]> {
let body = &self.data.as_ref()[glwe_ciphertext_mask_size(
self.polynomial_size,
self.glwe_size().to_glwe_dimension(),
self.polynomial_size,
)..];
GlweBody::from_container(body)
}
/// Returns an immutable view to the [`GlweMask`] of a [`GlweCiphertext`].
pub fn get_mask(&self) -> GlweMask<&[Scalar]> {
GlweMask::from_container(
&self.as_ref()[0..glwe_ciphertext_mask_size(
self.polynomial_size,
self.glwe_size().to_glwe_dimension(),
self.polynomial_size,
)],
self.polynomial_size,
)
}
/// Interprets the [`GlweCiphertext`] as a [`PolynomialList`].
pub fn as_polynomial_list(&self) -> PolynomialList<&'_ [Scalar]> {
PolynomialList::from_container(self.as_ref(), self.polynomial_size)
}
/// Returns a view of the [`GlweCiphertext`]. This is useful if an algorithm takes a view by
/// value.
pub fn as_view(&self) -> GlweCiphertext<&'_ [Scalar]> {
GlweCiphertext {
data: self.data.as_ref(),
@@ -201,14 +321,15 @@ impl<Scalar, C: Container<Element = Scalar>> GlweCiphertext<C> {
}
impl<Scalar, C: ContainerMut<Element = Scalar>> GlweCiphertext<C> {
/// Mutable variant of [`GlweCiphertext::get_mask_and_body`].
pub fn get_mut_mask_and_body(&mut self) -> (GlweMask<&mut [Scalar]>, GlweBody<&mut [Scalar]>) {
let polynomial_size = self.polynomial_size();
let glwe_dimension = self.glwe_size().to_glwe_dimension();
let polynomial_size = self.polynomial_size();
let (mask, body) = self
.data
.as_mut()
.split_at_mut(glwe_ciphertext_mask_size(polynomial_size, glwe_dimension));
.split_at_mut(glwe_ciphertext_mask_size(glwe_dimension, polynomial_size));
(
GlweMask::from_container(mask, polynomial_size),
@@ -216,31 +337,35 @@ impl<Scalar, C: ContainerMut<Element = Scalar>> GlweCiphertext<C> {
)
}
/// Mutable variant of [`GlweCiphertext::get_body`].
pub fn get_mut_body(&mut self) -> GlweBody<&mut [Scalar]> {
let polynomial_size = self.polynomial_size();
let glwe_dimension = self.glwe_size().to_glwe_dimension();
let polynomial_size = self.polynomial_size();
let body =
&mut self.data.as_mut()[glwe_ciphertext_mask_size(polynomial_size, glwe_dimension)..];
&mut self.data.as_mut()[glwe_ciphertext_mask_size(glwe_dimension, polynomial_size)..];
GlweBody::from_container(body)
}
/// Mutable variant of [`GlweCiphertext::get_mask`].
pub fn get_mut_mask(&mut self) -> GlweMask<&mut [Scalar]> {
let polynomial_size = self.polynomial_size();
let glwe_dimension = self.glwe_size().to_glwe_dimension();
GlweMask::from_container(
&mut self.as_mut()[0..glwe_ciphertext_mask_size(polynomial_size, glwe_dimension)],
&mut self.as_mut()[0..glwe_ciphertext_mask_size(glwe_dimension, polynomial_size)],
polynomial_size,
)
}
/// Mutable variant of [`GlweCiphertext::as_polynomial_list`].
pub fn as_mut_polynomial_list(&mut self) -> PolynomialList<&'_ mut [Scalar]> {
let polynomial_size = self.polynomial_size;
PolynomialList::from_container(self.as_mut(), polynomial_size)
}
/// Mutable variant of [`GlweCiphertext::as_view`].
pub fn as_mut_view(&mut self) -> GlweCiphertext<&'_ mut [Scalar]> {
GlweCiphertext {
data: self.data.as_mut(),
@@ -249,11 +374,17 @@ impl<Scalar, C: ContainerMut<Element = Scalar>> GlweCiphertext<C> {
}
}
/// A [`GlweCiphertext`] owning the memory for its own storage.
pub type GlweCiphertextOwned<Scalar> = GlweCiphertext<Vec<Scalar>>;
/// A [`GlweCiphertext`] immutably borrowing memory for its own storage.
pub type GlweCiphertextView<'data, Scalar> = GlweCiphertext<&'data [Scalar]>;
/// A [`GlweCiphertext`] mutably borrowing memory for its own storage.
pub type GlweCiphertextMutView<'data, Scalar> = GlweCiphertext<&'data mut [Scalar]>;
impl<Scalar: Copy> GlweCiphertextOwned<Scalar> {
/// Allocate memory and create a new owned [`GlweCiphertext`].
///
/// See [`GlweCiphertext::from_container`] for usage.
pub fn new(
fill_with: Scalar,
glwe_size: GlweSize,
@@ -266,6 +397,7 @@ impl<Scalar: Copy> GlweCiphertextOwned<Scalar> {
}
}
/// Metadata used in the [`CreateFrom`] implementation to create [`GlweCiphertext`] entities.
#[derive(Clone, Copy)]
pub struct GlweCiphertextCreationMetadata(pub PolynomialSize);

View File

@@ -131,6 +131,7 @@ impl<Scalar: Copy> GlweCiphertextListOwned<Scalar> {
}
}
/// Metadata used in the [`CreateFrom`] implementation to create [`GlweCiphertextList`] entities.
#[derive(Clone, Copy)]
pub struct GlweCiphertextListCreationMetadata(pub GlweSize, pub PolynomialSize);