Skip to content

Commit

Permalink
Merge pull request #548 from openfheorg/dev
Browse files Browse the repository at this point in the history
Updates to v1.1.1
  • Loading branch information
yspolyakov authored Aug 23, 2023
2 parents 802b226 + cd0b586 commit f6f1b9c
Show file tree
Hide file tree
Showing 13 changed files with 126 additions and 46 deletions.
1 change: 1 addition & 0 deletions CMakeLists.User.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ include_directories( ${OpenFHE_INCLUDE} )
include_directories( ${OpenFHE_INCLUDE}/third-party/include )
include_directories( ${OpenFHE_INCLUDE}/core )
include_directories( ${OpenFHE_INCLUDE}/pke )
include_directories( ${OpenFHE_INCLUDE}/binfhe )
### add directories for other OpenFHE modules as needed for your project

link_directories( ${OpenFHE_LIBDIR} )
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ project (OpenFHE C CXX)

set(OPENFHE_VERSION_MAJOR 1)
set(OPENFHE_VERSION_MINOR 1)
set(OPENFHE_VERSION_PATCH 0)
set(OPENFHE_VERSION_PATCH 1)
set(OPENFHE_VERSION ${OPENFHE_VERSION_MAJOR}.${OPENFHE_VERSION_MINOR}.${OPENFHE_VERSION_PATCH})

set(CMAKE_CXX_STANDARD 17)
Expand Down
15 changes: 4 additions & 11 deletions OpenFHEConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ set(BASE_OPENFHE_VERSION @OPENFHE_VERSION@)
set(OPENMP_INCLUDES "@OPENMP_INCLUDES@" )
set(OPENMP_LIBRARIES "@OPENMP_LIBRARIES@" )

set(OpenFHE_CXX_FLAGS "@CMAKE_CXX_FLAGS@ @OpenMP_CXX_FLAGS@")
set(OpenFHE_C_FLAGS "@CMAKE_C_FLAGS@ @OpenMP_C_FLAGS@")
set(OpenFHE_CXX_FLAGS "@CMAKE_CXX_FLAGS@")
set(OpenFHE_C_FLAGS "@CMAKE_C_FLAGS@")

if( "@WITH_NTL@" STREQUAL "Y" )
set(OpenFHE_CXX_FLAGS "${OpenFHE_CXX_FLAGS} -DWITH_NTL" )
set(OpenFHE_C_FLAGS "${OpenFHE_C_FLAGS} -DWITH_NTL")
endif()

set (OpenFHE_EXE_LINKER_FLAGS "@CMAKE_EXE_LINKER_FLAGS@ @OpenMP_EXE_LINKER_FLAGS@")
set (OpenFHE_EXE_LINKER_FLAGS "@CMAKE_EXE_LINKER_FLAGS@")

# CXX info
set(OpenFHE_CXX_STANDARD "@CMAKE_CXX_STANDARD@")
Expand All @@ -40,20 +40,13 @@ set(OpenFHE_CXX_COMPILER_VERSION "@CMAKE_CXX_COMPILER_VERSION@")
set(OpenFHE_STATIC "@BUILD_STATIC@")
set(OpenFHE_SHARED "@BUILD_SHARED@")
set(OpenFHE_TCM "@WITH_TCM@")
set(OpenFHE_WITH_INTEL_HEXL "@WITH_INTEL_HEXL@")
set(OpenFHE_OPENMP "@WITH_OPENMP@")
set(OpenFHE_NATIVE_SIZE "@NATIVE_SIZE@")
set(OpenFHE_CKKS_M_FACTOR "@CKKS_M_FACTOR@")
set(OpenFHE_NATIVEOPT "@WITH_NATIVEOPT@")

# Math Backend
if("@WITH_BE2@")
set(OpenFHE_BACKEND "BE2")
elseif("@WITH_BE4@")
set(OpenFHE_BACKEND "BE4")
elseif("@WITH_NTL@")
set(OpenFHE_BACKEND "NTL")
endif()
set(OpenFHE_BACKEND "@MATHBACKEND@")

# Build Details
set(OpenFHE_EMSCRIPTEN "@EMSCRIPTEN@")
Expand Down
6 changes: 3 additions & 3 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
alabaster==0.7.12
Babel==2.9.1
breathe==4.33.1
certifi==2021.10.8
certifi>=2023.7.22
charset-normalizer==2.0.12
docutils==0.17.1
exhale>=0.3.0
Expand All @@ -11,10 +11,10 @@ importlib-metadata>=4.0.0
Jinja2==3.0.3
MarkupSafe>=2.0.0
packaging==21.3
Pygments==2.11.2
Pygments>=2.15.0
pyparsing==3.0.7
pytz==2021.3
requests==2.27.1
requests>=2.31.0
snowballstemmer==2.2.0
Sphinx==4.4.0
sphinx-rtd-theme==1.0.0
Expand Down
2 changes: 2 additions & 0 deletions docs/sphinx_rsts/intro/tutorials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ Tutorials on Cryptographic Capabilities
- `Smooth Arbitrary Function Evaluation in CKKS <https://github.com/openfheorg/openfhe-development/blob/main/src/pke/examples/FUNCTION_EVALUATION.md>`_

- `Scheme Switching between CKKS and FHEW/TFHE <https://github.com/openfheorg/openfhe-development/blob/main/src/pke/examples/SCHEME_SWITCHING_CAPABILITY.md>`_

- `Threshold FHE for BGV, BFV, and CKKS <https://github.com/openfheorg/openfhe-development/tree/main/docs/static_docs/Threshold_FHE.md>`_
11 changes: 10 additions & 1 deletion docs/static_docs/Release_Notes.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
07/28/2024: OpenFHE 1.1.0 (development) is released
08/23/2023: OpenFHE 1.1.1 (development) is released

* Fixes the CMake files (binfhe module is now a dependency for the pke module) [#525, #538]
* Fixes a bug in EvalChebyshevFunction (#530)
* Adds documentation for threshold FHE (#457)
* Includes several other bug fixes

The detailed list of changes is available at https://github.com/openfheorg/openfhe-development/pulls?q=is%3Apr+milestone%3A%22Release+1.1.1%22

07/28/2023: OpenFHE 1.1.0 (development) is released

* Adds scheme switching between CKKS and FHEW/TFHE
* Adds comparison and (arg)min evaluation in CKKS via scheme switching to FHEW/FHEW
Expand Down
54 changes: 54 additions & 0 deletions docs/static_docs/Threshold_FHE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
Threshold FHE is currently supported for BGV, BFV, and CKKS. To use the threshold functionality in OpenFHE, the MULTIPARTY feature needs to be enabled for the cryptocontext with the line `cc->Enable(MULTIPARTY)`, where `cc` is the cryptocontext object.

The MULTIPARTY feature has been implemented in two modes for BGV/BFV. The modes are implemented as an enum -
**MultipartyMode multipartyMode**

```
- FIXED_NOISE_MULTIPARTY which is the default mode if not set, adds a fixed 20 bits noise
- The NOISE_FLOODING_MULTIPARTY mode adds extra noise and gives enhanced security compared to the FIXED_NOISE_MULTIPARTY mode. This is the most secure mode of threshold FHE for BFV and BGV.
```
The mode can be configured using the `SetMultipartyMode` method to the parameters passed to cryptocontext. For example, the following code creates a parameters object for a BGVRNS cryptocontext and sets the multiparty mode to `NOISE_FLOODING_MULTIPARTY`.

```
CCParams<CryptoContextBGVRNS> parameters;
parameters.SetMultipartyMode(NOISE_FLOODING_MULTIPARTY);
```

The modes are implemented to provide security against the type of attacks in [Li and Micciancio](https://link.springer.com/chapter/10.1007/978-3-030-77870-5_23) and [Kluczniak and Santato](https://eprint.iacr.org/2023/301).
More on the attack and the solution with noise flooding for CKKS decryption in provided in [CKKS_NOISE_FLOODING.MD](https://github.com/openfheorg/openfhe-development/blob/main/src/pke/examples/CKKS_NOISE_FLOODING.md).
The same kind of attacks also apply in the threshold scenario for all three schemes since the approximate decryption shares from each party are shared before they can be aggregated to decrypt the final result.
The decryption share of a ciphertext $c = (c_0, c_1)$ for party $i$ is $\mathsf{d_i} = c_0 + c_1s_i$.
Similar to the CKKS decryption attack, the noise in the decryption share $d_i$ leaks information about the secret $s_i$.

The FIXED_NOISE_MODE for all schemes is implemented to add a fixed $20$-bit noise to the decryption share to increase the attack complexity.

The NOISE_FLOODING_MODE provides provable security against such attacks as in the IND-CPA^D model. The technique to choose the modulus to accomodate the extra noise from noise flooding is implemented in BGV and BFV differently as follows:

1. BFV:
In this case, additional two towers of moduli are added to the CRT moduli to accomodate the error, which increases the size of the modulus by about $128$ bits. This is automatically done by OpenFHE during parameter generation if the NOISE_FLOODING_MULTIPARTY mode is set in the parameters as above.

The protocol for BFV threshold noise flooding is as follows:
Let our current RNS basis for decryption be $Q=q_0 * q_1 * ... * q_k$. Add two more 60-bit primes $p_0$ and $p_1$. The extended basis is $QP = q_0 * p_1 * p_2 * q_1 * ... * q_k$.

For an input ciphertext $c mod QP$, the decryption shares by each party $i$ are created as follows:

- We first generate a random uniform ring element $b$ w.r.t. to mod $Qprime = QP/q_0$. Then we do exact RNS basis extension from $Qprime$ to $QP$.

- Then we do flooding with $b$ as $c_1 * s_i + b mod QP$.

2. BGV: For BGV threshold noise flooding, the protocol is exactly the same as BFV, except we use $b' = tb$ for flooding instead of $b$ for plaintext modulus $t$.


3. CKKS:

IND-CPA^D mode can be used to instantiate threshold FHE for the mode similar to NOISE_FLOODING_MULTIPARTY. Please look at [the CKKS noise flooding example](https://github.com/openfheorg/openfhe-development/blob/main/src/pke/examples/ckks-noise-flooding.cpp) for more details.

# Threshold decryption with Aborts:

In addition to the multiparty modes that can be set in the parameters for Threshold FHE, there is an aborts option to get a $t$-out-of-N threshold decryption where $t > N/2 + 1$. This can be achieved with an additional secret sharing step after keygen by each party. We use the aborts approach described [here](https://eprint.iacr.org/2011/613.pdf) to use a secret sharing scheme to allow $t$ out of $N$ decryption. The secret sharing and recovery (of an aborted party) are done using the `ShareKeys` and `RecoverSharedKey` functions respectively. Using this approach, we are able to decrypt a ciphertext computed using the joint evaluation keys of $N$ parties even if upto $N-t$ parties drop out from the network. We consider two secret sharing options with the aborts approach:

1. Additive sharing: With this option, we let each party secret share its secret key additively to all other parties, resulting in $N - 1$ additive shares. When one party drops out, the other parties can collaborate and generate the dropped parties' secret key using these shares. Note that this directly allows to decrypt with $N - 1$ parties with one party dropping out. To allow decryption with multiple parties dropping out using this option, we would need each party to generate shares of their secret for all possible combinations of the participating parties. This could lead to very expensive communication.

2. Shamir sharing: We use this option to allow for multiple parties (minority) to drop out from the decryption and still be able to decrypt with $t$-out-of-N where $t > N/2$.

The unittest [UnitTestMultiparty](https://github.com/openfheorg/openfhe-development/blob/main/src/pke/unittest/UnitTestMultiparty.cpp) has a small example that uses these functions for threshold computation with 3 parties.
15 changes: 14 additions & 1 deletion src/binfhe/include/lwe-cryptoparameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,21 @@ class LWECryptoParams : public Serializable {
const NativeInteger& q_KS, double std, uint32_t baseKS,
SecretKeyDist keyDist = UNIFORM_TERNARY)
: m_q(q), m_Q(Q), m_qKS(q_KS), m_n(n), m_N(N), m_baseKS(baseKS), m_keyDist(keyDist) {
if(!m_n)
OPENFHE_THROW(config_error, "m_n (lattice parameter) can not be zero");
if(!m_N)
OPENFHE_THROW(config_error, "m_N (ring dimension) can not be zero");
if(!m_q)
OPENFHE_THROW(config_error, "m_q (modulus for additive LWE) can not be zero");
if(!m_Q)
OPENFHE_THROW(config_error, "m_Q (modulus for RingGSW/RLWE) can not be zero");
if(!q_KS)
OPENFHE_THROW(config_error, "q_KS (modulus for key switching) can not be zero");
if(!m_baseKS)
OPENFHE_THROW(config_error, "m_baseKS (the base used for key switching) can not be zero");

if (m_Q.GetMSB() > MAX_MODULUS_SIZE)
OPENFHE_THROW(config_error, "ERROR: Q.GetMSB() > MAX_MODULUS_SIZE");
OPENFHE_THROW(config_error, "Q.GetMSB() > MAX_MODULUS_SIZE");
m_dgg.SetStd(std);
m_ks_dgg.SetStd(std);
}
Expand Down
1 change: 1 addition & 0 deletions src/core/include/lattice/constants-lattice.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

#include <iosfwd>
#include <string>
#include <cstdint>

namespace lbcrypto {

Expand Down
27 changes: 14 additions & 13 deletions src/core/include/lattice/hal/dcrtpoly-interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -1098,19 +1098,20 @@ class DCRTPolyInterface : public ILElement<DerivedType, BigVecType> {
const std::vector<double>& qInv, Format resultFormat) = 0;

struct CRTBasisExtensionPrecomputations {
const std::shared_ptr<Params>& paramsQlPl;
const std::shared_ptr<Params>& paramsPl;
const std::shared_ptr<Params>& paramsQl;
const std::vector<NativeInteger>& mPlQHatInvModq;
const std::vector<NativeInteger>& mPlQHatInvModqPrecon;
const std::vector<std::vector<NativeInteger>>& qInvModp;
const std::vector<DoubleNativeInt> modpBarrettMu;
const std::vector<NativeInteger>& PlHatInvModp;
const std::vector<NativeInteger>& PlHatInvModpPrecon;
const std::vector<std::vector<NativeInteger>>& PlHatModq;
const std::vector<std::vector<NativeInteger>>& alphaPlModq;
const std::vector<DoubleNativeInt>& modqBarrettMu;
const std::vector<double>& pInv;
// TODO (dsuponit) and (pascoec): make the data members private to enforce their constantness and add getters.
std::shared_ptr<Params> paramsQlPl;
std::shared_ptr<Params> paramsPl;
std::shared_ptr<Params> paramsQl;
std::vector<NativeInteger> mPlQHatInvModq;
std::vector<NativeInteger> mPlQHatInvModqPrecon;
std::vector<std::vector<NativeInteger>> qInvModp;
std::vector<DoubleNativeInt> modpBarrettMu;
std::vector<NativeInteger> PlHatInvModp;
std::vector<NativeInteger> PlHatInvModpPrecon;
std::vector<std::vector<NativeInteger>> PlHatModq;
std::vector<std::vector<NativeInteger>> alphaPlModq;
std::vector<DoubleNativeInt> modqBarrettMu;
std::vector<double> pInv;

// clang-format off
CRTBasisExtensionPrecomputations(
Expand Down
16 changes: 9 additions & 7 deletions src/core/lib/math/chebyshev.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,19 @@
namespace lbcrypto {

std::vector<double> EvalChebyshevCoefficients(std::function<double(double)> func, double a, double b, uint32_t degree) {
// the number of coefficients to be generated should be degree+1 as zero is also included
size_t coeffTotal{degree+1};
double bMinusA = 0.5 * (b - a);
double bPlusA = 0.5 * (b + a);
double PiByDeg = M_PI / static_cast<double>(degree);
std::vector<double> functionPoints(degree);
for (uint32_t i = 0; i < degree; ++i)
double PiByDeg = M_PI / static_cast<double>(coeffTotal);
std::vector<double> functionPoints(coeffTotal);
for (size_t i = 0; i < coeffTotal; ++i)
functionPoints[i] = func(std::cos(PiByDeg * (i + 0.5)) * bMinusA + bPlusA);

double multFactor = 2.0 / static_cast<double>(degree);
std::vector<double> coefficients(degree);
for (uint32_t i = 0; i < degree; ++i) {
for (uint32_t j = 0; j < degree; ++j)
double multFactor = 2.0 / static_cast<double>(coeffTotal);
std::vector<double> coefficients(coeffTotal);
for (size_t i = 0; i < coeffTotal; ++i) {
for (size_t j = 0; j < coeffTotal; ++j)
coefficients[i] += functionPoints[j] * std::cos(PiByDeg * i * (j + 0.5));
coefficients[i] *= multFactor;
}
Expand Down
4 changes: 2 additions & 2 deletions src/pke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ add_library (pkeobj OBJECT ${PKE_SRC_FILES})
set_property(TARGET pkeobj PROPERTY POSITION_INDEPENDENT_CODE 1)

if( BUILD_SHARED )
add_dependencies(pkeobj OPENFHEcore)
add_dependencies(pkeobj OPENFHEcore OPENFHEbinfhe)
add_library (OPENFHEpke SHARED $<TARGET_OBJECTS:pkeobj>)
set_property(TARGET OPENFHEpke PROPERTY VERSION ${PKE_VERSION})
set_property(TARGET OPENFHEpke PROPERTY SOVERSION ${PKE_VERSION_MAJOR})
Expand All @@ -30,7 +30,7 @@ if( BUILD_SHARED )
endif()

if( BUILD_STATIC )
add_dependencies(pkeobj OPENFHEcore_static)
add_dependencies(pkeobj OPENFHEcore_static OPENFHEbinfhe_static)
add_library (OPENFHEpke_static STATIC $<TARGET_OBJECTS:pkeobj>)
set_property(TARGET OPENFHEpke_static PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
install(TARGETS OPENFHEpke_static
Expand Down
18 changes: 11 additions & 7 deletions src/pke/lib/scheme/ckksrns/ckksrns-schemeswitching.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,17 +226,21 @@ Plaintext SWITCHCKKSRNS::MakeAuxPlaintext(const CryptoContextImpl<DCRTPoly>& cc,
double powP = scFact;

// Compute approxFactor, a value to scale down by, in case the value exceeds a 64-bit integer.
int32_t MAX_BITS_IN_WORD = 62;
constexpr int32_t MAX_BITS_IN_WORD = 61;

int32_t logc = 0;
for (size_t i = 0; i < slots; ++i) {
inverse[i] *= powP;
int32_t logci = static_cast<int32_t>(ceil(log2(std::abs(inverse[i].real()))));
if (logc < logci)
logc = logci;
logci = static_cast<int32_t>(ceil(log2(std::abs(inverse[i].imag()))));
if (logc < logci)
logc = logci;
if (inverse[i].real() != 0) {
int32_t logci = static_cast<int32_t>(ceil(log2(std::abs(inverse[i].real()))));
if (logc < logci)
logc = logci;
}
if (inverse[i].imag() != 0) {
int32_t logci = static_cast<int32_t>(ceil(log2(std::abs(inverse[i].imag()))));
if (logc < logci)
logc = logci;
}
}
if (logc < 0) {
OPENFHE_THROW(math_error, "Too small scaling factor");
Expand Down

0 comments on commit f6f1b9c

Please sign in to comment.