Skip to content

Commit

Permalink
Add a new key switch method and support q>2N (#135)
Browse files Browse the repository at this point in the history
* init

* first try `ms_ks_ms`

* fix `ntt`

* rename `SecretKeyType` to `LWESecretKeyType`

* try `msks` once again

* minor

* update

* simplify some codes

* simplify

* update

* update

* fix

* minor fix

* fix key switch

* simplify codes

* clippy

* typo

* fix

* improve `rlwe` `bootstrap`

* doc: modulus switch

* improve `ntru` `bootstrap`
  • Loading branch information
serendipity-crypto authored Aug 19, 2024
1 parent 2c583b0 commit eb8e633
Show file tree
Hide file tree
Showing 45 changed files with 1,958 additions and 1,461 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"algebra_derive",
"fhe_core",
"lattice",
"fhe",
"pcs",
"zkfhe",
"zkp",
Expand Down
2 changes: 1 addition & 1 deletion algebra/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
algebra_derive = { path = "../algebra_derive" }
algebra_derive = { path = "../algebra_derive", default-features = false }

thiserror = { workspace = true }
num-traits = { workspace = true }
Expand Down
3 changes: 1 addition & 2 deletions algebra/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ pub use polynomial::multivariate::{
SparsePolynomial,
};
pub use polynomial::univariate::{
ntt_add_mul_assign, ntt_add_mul_assign_fast, ntt_add_mul_inplace, ntt_mul_assign,
ntt_mul_inplace, NTTPolynomial, Polynomial,
ntt_add_mul_assign, ntt_add_mul_assign_fast, ntt_add_mul_inplace, NTTPolynomial, Polynomial,
};
pub use primitive::{div_ceil, AsFrom, AsInto, Bits, Widening, WrappingOps};
pub use random::{
Expand Down
3 changes: 1 addition & 2 deletions algebra/src/polynomial/univariate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@ mod ntt_polynomial;

pub use native_polynomial::Polynomial;
pub use ntt_polynomial::{
ntt_add_mul_assign, ntt_add_mul_assign_fast, ntt_add_mul_inplace, ntt_mul_assign,
ntt_mul_inplace, NTTPolynomial,
ntt_add_mul_assign, ntt_add_mul_assign_fast, ntt_add_mul_inplace, NTTPolynomial,
};
60 changes: 42 additions & 18 deletions algebra/src/polynomial/univariate/native_polynomial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ impl<F: Field> Polynomial<F> {
&mut self.data
}

/// Get the coefficient counts of polynomial.
#[inline]
pub fn coeff_count(&self) -> usize {
self.data.len()
}

/// Creates a [`Polynomial<F>`] with all coefficients equal to zero.
#[inline]
pub fn zero(coeff_count: usize) -> Self {
Expand Down Expand Up @@ -119,24 +125,6 @@ impl<F: Field> Polynomial<F> {
self.data.as_mut_slice()
}

/// Multiply `self` with the a scalar.
#[inline]
pub fn mul_scalar(&self, scalar: F) -> Self {
Self::new(self.iter().map(|&v| v * scalar).collect())
}

/// Multiply `self` with the a scalar inplace.
#[inline]
pub fn mul_scalar_assign(&mut self, scalar: F) {
self.iter_mut().for_each(|v| *v *= scalar)
}

/// Get the coefficient counts of polynomial.
#[inline]
pub fn coeff_count(&self) -> usize {
self.data.len()
}

/// Returns an iterator that allows reading each value or coefficient of the polynomial.
#[inline]
pub fn iter(&self) -> Iter<F> {
Expand Down Expand Up @@ -170,6 +158,42 @@ impl<F: Field> Polynomial<F> {
self.data.resize_with(new_degree, f);
}

/// Multiply `self` with the a scalar.
#[inline]
pub fn mul_scalar(&self, scalar: F) -> Self {
Self::new(self.iter().map(|&v| v * scalar).collect())
}

/// Multiply `self` with the a scalar inplace.
#[inline]
pub fn mul_scalar_assign(&mut self, scalar: F) {
self.iter_mut().for_each(|v| *v *= scalar)
}

/// Performs addition operation:`self + rhs`,
/// and puts the result to the `destination`.
#[inline]
pub fn add_inplace(&self, rhs: &Self, destination: &mut Self) {
self.iter()
.zip(rhs)
.zip(destination)
.for_each(|((&x, &y), z)| {
*z = x + y;
})
}

/// Performs subtraction operation:`self - rhs`,
/// and puts the result to the `destination`.
#[inline]
pub fn sub_inplace(&self, rhs: &Self, destination: &mut Self) {
self.iter()
.zip(rhs)
.zip(destination)
.for_each(|((&x, &y), z)| {
*z = x - y;
})
}

/// Performs the unary `-` operation.
#[inline]
pub fn neg_assign(&mut self) {
Expand Down
122 changes: 64 additions & 58 deletions algebra/src/polynomial/univariate/ntt_polynomial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ impl<F: Field> NTTPolynomial<F> {
&mut self.data
}

/// Get the coefficient counts of polynomial.
#[inline]
pub fn coeff_count(&self) -> usize {
self.data.len()
}

/// Creates a [`NTTPolynomial<F>`] with all coefficients equal to zero.
#[inline]
pub fn zero(coeff_count: usize) -> Self {
Expand Down Expand Up @@ -113,24 +119,6 @@ impl<F: Field> NTTPolynomial<F> {
self.data.as_mut_slice()
}

/// Get the coefficient counts of polynomial.
#[inline]
pub fn coeff_count(&self) -> usize {
self.data.len()
}

/// Multiply `self` with the a scalar.
#[inline]
pub fn mul_scalar(&self, scalar: F) -> Self {
Self::new(self.iter().map(|&v| v * scalar).collect())
}

/// Multiply `self` with the a scalar inplace.
#[inline]
pub fn mul_scalar_assign(&mut self, scalar: F) {
self.iter_mut().for_each(|v| *v *= scalar)
}

/// Returns an iterator that allows reading each value or coefficient of the polynomial.
#[inline]
pub fn iter(&self) -> Iter<F> {
Expand Down Expand Up @@ -164,6 +152,54 @@ impl<F: Field> NTTPolynomial<F> {
self.data.resize_with(new_degree, f);
}

/// Multiply `self` with the a scalar.
#[inline]
pub fn mul_scalar(&self, scalar: F) -> Self {
Self::new(self.iter().map(|&v| v * scalar).collect())
}

/// Multiply `self` with the a scalar inplace.
#[inline]
pub fn mul_scalar_assign(&mut self, scalar: F) {
self.iter_mut().for_each(|v| *v *= scalar)
}

/// Performs addition operation:`self + rhs`,
/// and puts the result to the `destination`.
#[inline]
pub fn add_inplace(&self, rhs: &Self, destination: &mut Self) {
self.iter()
.zip(rhs)
.zip(destination)
.for_each(|((&x, &y), z)| {
*z = x + y;
})
}

/// Performs subtraction operation:`self - rhs`,
/// and puts the result to the `destination`.
#[inline]
pub fn sub_inplace(&self, rhs: &Self, destination: &mut Self) {
self.iter()
.zip(rhs)
.zip(destination)
.for_each(|((&x, &y), z)| {
*z = x - y;
})
}

/// Performs subtraction operation:`self * rhs`,
/// and puts the result to the `destination`.
#[inline]
pub fn mul_inplace(&self, rhs: &Self, destination: &mut Self) {
self.iter()
.zip(rhs)
.zip(destination)
.for_each(|((&x, &y), z)| {
*z = x * y;
})
}

/// Performs the unary `-` operation.
#[inline]
pub fn neg_assign(&mut self) {
Expand Down Expand Up @@ -447,11 +483,8 @@ impl<F: Field> Mul<&NTTPolynomial<F>> for &NTTPolynomial<F> {
impl<F: NTTField> MulAssign<Polynomial<F>> for NTTPolynomial<F> {
#[inline]
fn mul_assign(&mut self, rhs: Polynomial<F>) {
let coeff_count = self.coeff_count();
debug_assert_eq!(coeff_count, rhs.coeff_count());

let rhs = rhs.into_ntt_polynomial();
ntt_mul_assign(self, &rhs);
debug_assert_eq!(self.coeff_count(), rhs.coeff_count());
*self *= rhs.into_ntt_polynomial();
}
}

Expand Down Expand Up @@ -486,13 +519,8 @@ impl<F: NTTField> Mul<Polynomial<F>> for &NTTPolynomial<F> {

#[inline]
fn mul(self, rhs: Polynomial<F>) -> Self::Output {
let coeff_count = self.coeff_count();
debug_assert_eq!(coeff_count, rhs.coeff_count());
debug_assert!(coeff_count.is_power_of_two());

let log_n = coeff_count.trailing_zeros();
let ntt_table = F::get_ntt_table(log_n).unwrap();
ntt_table.transform_inplace(rhs) * self
debug_assert_eq!(self.coeff_count(), rhs.coeff_count());
NTTPolynomial::from(rhs) * self
}
}

Expand Down Expand Up @@ -547,30 +575,10 @@ impl<F: Field> Inv for &NTTPolynomial<F> {
}
}

/// Performs enrty-wise mul operation.
#[inline]
pub fn ntt_mul_assign<F: NTTField>(x: &mut NTTPolynomial<F>, y: &NTTPolynomial<F>) {
x.iter_mut().zip(y).for_each(|(a, b)| *a *= b);
}

/// Performs enrty-wise mul operation.
#[inline]
pub fn ntt_mul_inplace<F: NTTField>(
x: &NTTPolynomial<F>,
y: &NTTPolynomial<F>,
des: &mut NTTPolynomial<F>,
) {
des.iter_mut()
.zip(x)
.zip(y)
.for_each(|((d, &a), &b)| *d = a * b);
}

/// Performs enrty-wise add_mul operation.
///
/// Treats three iterators as [`NTTPolynomial<F>`]'s iterators,
/// then multiply enrty-wise over last two iterators, and add back to the first
/// iterator.
/// Multiply enrty-wise over last two [NTTPolynomial<F>], and add back to the first
/// [NTTPolynomial<F>].
#[inline]
pub fn ntt_add_mul_assign<F: NTTField>(
x: &mut NTTPolynomial<F>,
Expand All @@ -585,9 +593,8 @@ pub fn ntt_add_mul_assign<F: NTTField>(

/// Performs enrty-wise add_mul operation.
///
/// Treats four iterators as [`NTTPolynomial<F>`]'s iterators,
/// then multiply enrty-wise over last two iterators, and add the second
/// iterator, store the result to first iterator.
/// Multiply enrty-wise over middle two [NTTPolynomial<F>], and add the first
/// [NTTPolynomial<F>], store the result to last [NTTPolynomial<F>].
#[inline]
pub fn ntt_add_mul_inplace<F: NTTField>(
x: &NTTPolynomial<F>,
Expand All @@ -604,9 +611,8 @@ pub fn ntt_add_mul_inplace<F: NTTField>(

/// Performs enrty-wise add_mul fast operation.
///
/// Treats three iterators as [`NTTPolynomial<F>`]'s iterators,
/// then multiply enrty-wise over last two iterators, and add back to the first
/// iterator.
/// Multiply enrty-wise over last two [NTTPolynomial<F>], and add back to the first
/// [NTTPolynomial<F>].
///
/// The result coefficients may be in [0, 2*modulus) for some case,
/// and fall back to [0, modulus) for normal case.
Expand Down
5 changes: 5 additions & 0 deletions algebra_derive/src/fhe_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ fn impl_fhe_field(input: Input) -> TokenStream {

quote! {
impl ::algebra::FheField for #name{
#[inline]
fn lazy_new(value: Self::Value) -> Self {
Self(value)
}

#[inline]
fn add_mul(self, a: Self, b: Self) -> Self {
use ::algebra::Widening;
Expand Down
32 changes: 32 additions & 0 deletions fhe/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[package]
name = "fhe"
version = "0.1.0"
edition = "2021"

[dependencies]
algebra = { path = "../algebra", default-features = false }
lattice = { path = "../lattice", default-features = false }
fhe_core = { path = "../fhe_core", default-features = false }

rand = { workspace = true }
rayon = { workspace = true }
once_cell = { workspace = true }

[features]
default = ["concrete-ntt"]
concrete-ntt = [
"algebra/concrete-ntt",
"lattice/concrete-ntt",
"fhe_core/concrete-ntt",
]
nightly = ["algebra/nightly", "lattice/nightly", "fhe_core/nightly"]
count_ntt = ["algebra/count_ntt"]

[dev-dependencies]
criterion = { workspace = true }

[package.metadata.docs.rs]
all-features = true
# enable unstable features in the documentation
rustdoc-args = ["--cfg", "docsrs"]
# RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features --no-deps
1 change: 1 addition & 0 deletions fhe/src/bfhe/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions fhe/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod bfhe;
4 changes: 2 additions & 2 deletions fhe_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ version = "0.1.0"
edition = "2021"

[dependencies]
algebra = { path = "../algebra" }
lattice = { path = "../lattice" }
algebra = { path = "../algebra", default-features = false }
lattice = { path = "../lattice", default-features = false }

thiserror = { workspace = true }
num-traits = { workspace = true }
Expand Down
Loading

0 comments on commit eb8e633

Please sign in to comment.