Palisade lattice headers
文章目录
- Palisade lattice headers
\core\include\lattice\elemparams.h
class ElemParams : public Serializable
Wrapper class to hold the parameters for Element types and their inheritors.
参数类,首先看它有什么参数:
protected:
usint cyclotomicOrder;
usint ringDimension; // True iff the Ring Dimension is a power of 2.
bool isPowerOfTwo;
IntegerType ciphertextModulus;
IntegerType rootOfUnity;
IntegerType bigCiphertextModulus; // Used for only some applications.
IntegerType bigRootOfUnity; // Used for only some applications.
构造函数:
/**
* @brief Simple constructor method that takes as input root of unity, big
* root of unity, cyclotomic order and the ciphertext modulus and big
* ciphertext Modulus. This is used for bit-packing operations.
* @param order the cyclotomic order wrapped by the parameter set.
* @param ctModulus the ciphertext modulus wrapped by the parameter set.
* @param rUnity the root of unity.
* @param bigCtModulus the big ciphertext modulus used for bit packing
* operations.
* @param bigRUnity the big root of unity used for bit packing operations.
*/
ElemParams(usint order, const IntegerType& ctModulus,
const IntegerType& rUnity = IntegerType(0),
const IntegerType& bigCtModulus = IntegerType(0),
const IntegerType& bigRUnity = IntegerType(0)) {
cyclotomicOrder = order;
ringDimension = GetTotient(order);
isPowerOfTwo = ringDimension == cyclotomicOrder / 2;
ciphertextModulus = ctModulus;
rootOfUnity = rUnity;
bigCiphertextModulus = bigCtModulus;
bigRootOfUnity = bigRUnity;
}
cyclotomicOrder 是分圆的次数,ringDimension 等于cyclotomicOrder 的欧拉函数值,与之对应的是分圆多项式的次数。环是模分圆多项式的。
/**
* @brief Copy constructor using assignment to copy wrapped elements.
* @param rhs the input ElemParams copied.
* @return the resulting parameter set with parameters copied.
*/
ElemParams(const ElemParams& rhs) {
cyclotomicOrder = rhs.cyclotomicOrder;
ringDimension = rhs.ringDimension;
isPowerOfTwo = rhs.isPowerOfTwo;
ciphertextModulus = rhs.ciphertextModulus;
rootOfUnity = rhs.rootOfUnity;
bigCiphertextModulus = rhs.bigCiphertextModulus;
bigRootOfUnity = rhs.bigRootOfUnity;
}
/**
* @brief Copy constructor using move semnantics to copy wrapped elements.
* @param rhs the input ElemParams copied.
* @return the resulting copy of the parameter set.
*/
ElemParams(const ElemParams&& rhs) {
cyclotomicOrder = rhs.cyclotomicOrder;
ringDimension = rhs.ringDimension;
isPowerOfTwo = rhs.isPowerOfTwo;
ciphertextModulus = std::move(rhs.ciphertextModulus);
rootOfUnity = std::move(rhs.rootOfUnity);
bigCiphertextModulus = std::move(rhs.bigCiphertextModulus);
bigRootOfUnity = std::move(rhs.bigRootOfUnity);
}
赋值运算符重载和析构函数
/**
* @brief Assignment operator using assignment operations of wrapped elements.
* @param rhs the ElemParams instance to copy.
*/
const ElemParams& operator=(const ElemParams& rhs) {
cyclotomicOrder = rhs.cyclotomicOrder;
ringDimension = rhs.ringDimension;
isPowerOfTwo = rhs.isPowerOfTwo;
ciphertextModulus = rhs.ciphertextModulus;
rootOfUnity = rhs.rootOfUnity;
bigCiphertextModulus = rhs.bigCiphertextModulus;
bigRootOfUnity = rhs.bigRootOfUnity;
return *this;
}
/**
* @brief Simple destructor method.
* @return
*/
virtual ~ElemParams() {}
getter函数,没有setter函数,因此只能在构造时确定参数。
/**
* @brief Simple getter method for cyclotomic order.
* @return The cyclotomic order.
*/
usint GetCyclotomicOrder() const { return cyclotomicOrder; }
/**
* @brief Simple ring dimension getter method. The ring dimension is the
* evaluation of the totient function of the cyclotomic order.
* @return the ring dimension.
*/
usint GetRingDimension() const { return ringDimension; }
/**
* @brief Returns True if the cyclotomic order or ring dimension is a power
* of 2.
* @return True if the cyclotomic order or ring dimension is a power of 2.
* False otherwise.
*/
bool OrderIsPowerOfTwo() const { return isPowerOfTwo; }
/**
* @brief Simple getter method for the ciphertext modulus, not the big
* ciphertext modulus.
* @return The ciphertext modulus, not the big ciphertext modulus.
*/
const IntegerType& GetModulus() const { return ciphertextModulus; }
/**
* @brief Simpler getter method for the big ciphertext modulus.
* This is not relevant for all applications.
* @return The big ciphertext modulus.
*/
const IntegerType& GetBigModulus() const { return bigCiphertextModulus; }
/**
* @brief Simple getter method for the root of unity, not the big root of
* unity.
* @return The root of unity, not the big root of unity.
*/
const IntegerType& GetRootOfUnity() const { return rootOfUnity; }
/**
* @brief Simple getter method for the big root of unity.
* @return The the big root of unity.
*/
const IntegerType& GetBigRootOfUnity() const { return bigRootOfUnity; }
输出运算符,判断相等运算符,判断不相等运算符重载
【注】友元不是成员函数
/**
* @brief Output strem operator.
* @param out the preceding output stream.
* @param item what to add to the output stream.
* @return the appended output stream.
*/
friend std::ostream& operator<<(std::ostream& out, const ElemParams& item) {
return item.doprint(out);
}
/**
* @brief Equality operator that tests the equality of all wrapped values.
* @param other the other ElemenParams to compare to.
* @return True if all elements are equal, and False otherwise.
*/
virtual bool operator==(const ElemParams<IntegerType>& other) const {
return cyclotomicOrder == other.cyclotomicOrder &&
ringDimension == other.ringDimension &&
ciphertextModulus == other.ciphertextModulus &&
rootOfUnity == other.rootOfUnity &&
bigCiphertextModulus == other.bigCiphertextModulus &&
bigRootOfUnity == other.bigRootOfUnity;
}
/**
* @brief Inequality operator that tests the equality of all wrapped values.
* @param other the other ElemenParams to compare to.
* @return False if all elements are equal, and True otherwise.
*/
bool operator!=(const ElemParams<IntegerType>& other) const {
return !(*this == other);
}
save和load函数,暂时没搞懂要干啥
template <class Archive>
void save(Archive& ar, std::uint32_t const version) const {
ar(::cereal::make_nvp("co", cyclotomicOrder));
ar(::cereal::make_nvp("rd", ringDimension));
ar(::cereal::make_nvp("2n", isPowerOfTwo));
ar(::cereal::make_nvp("cm", ciphertextModulus));
ar(::cereal::make_nvp("ru", rootOfUnity));
ar(::cereal::make_nvp("bm", bigCiphertextModulus));
ar(::cereal::make_nvp("br", bigRootOfUnity));
}
template <class Archive>
void load(Archive& ar, std::uint32_t const version) {
if (version > SerializedVersion()) {
PALISADE_THROW(deserialize_error,
"serialized object version " + std::to_string(version) +
" is from a later version of the library");
}
ar(::cereal::make_nvp("co", cyclotomicOrder));
ar(::cereal::make_nvp("rd", ringDimension));
ar(::cereal::make_nvp("2n", isPowerOfTwo));
ar(::cereal::make_nvp("cm", ciphertextModulus));
ar(::cereal::make_nvp("ru", rootOfUnity));
ar(::cereal::make_nvp("bm", bigCiphertextModulus));
ar(::cereal::make_nvp("br", bigRootOfUnity));
}
std::string SerializedObjectName() const { return "ElemParams"; }
static uint32_t SerializedVersion() { return 1; }
以上函数都是public的
下面这个是protected属性,是给输出运算符调用的。
/**
* @brief Pretty print operator for the ElemParams type.
* @param out the ElemParams to output
* @return the resulting output stream.
*/
virtual std::ostream& doprint(std::ostream& out) const {
out << "[m=" << cyclotomicOrder << (isPowerOfTwo ? "* " : " ")
<< "n=" << ringDimension << " q=" << ciphertextModulus
<< " ru=" << rootOfUnity << " bigq=" << bigCiphertextModulus
<< " bigru=" << bigRootOfUnity << "]";
return out;
}
};
\core\include\lattice\ilparams.h
Wraps parameters for integer lattice operations. Inherits from ElemParams.
class ILParamsImpl : public ElemParams
继承自ElemParams类,继承了所有成员。
public:
typedef IntType Integer;
构造函数
/**
* @brief Constructor for the case of partially pre-computed parameters.
*
* @param &order the order of the ciphertext.
* @param &modulus the ciphertext modulus.
* @param &rootOfUnity the root of unity used in the ciphertext.
* @param bigModulus the big ciphertext modulus.
* @param bigRootOfUnity the big ciphertext modulus used for bit packing
* operations.
* @return
*/
ILParamsImpl(const usint order, const IntType &modulus,
const IntType &rootOfUnity, const IntType &bigModulus = 0, // 这个要传rootIfUnity
const IntType &bigRootOfUnity = 0)
: ElemParams<IntType>(order, modulus, rootOfUnity, bigModulus,
bigRootOfUnity) {}
/**
* @brief Constructor for the case of partially pre-computed parameters.
*
* @param &order the order of the ciphertext.
* @param &modulus the ciphertext modulus.
*/
ILParamsImpl(const usint order, const IntType &modulus)
: ElemParams<IntType>(order, modulus) {
this->rootOfUnity = RootOfUnity<IntType>(order, modulus); // 跟父类不同之处在于父类不需要计算rootOfUnity,交给子类计算。
}
/**
* @brief Copy constructor.
*
* @param &rhs the input set of parameters which is copied.
*/
ILParamsImpl(const ILParamsImpl &rhs) : ElemParams<IntType>(rhs) {}
/**
* @brief Assignment Operator.
*
* @param &rhs the params to be copied.
* @return this object
*/
const ILParamsImpl &operator=(const ILParamsImpl &rhs) {
ElemParams<IntType>::operator=(rhs);
return *this;
}
/**
* @brief Move constructor.
*
* @param &rhs the input set of parameters which is copied.
*/
ILParamsImpl(const ILParamsImpl &&rhs) : ElemParams<IntType>(rhs) {}
/**
* @brief Standard Destructor method.
*/
~ILParamsImpl() {}
相等运算符重载
/**
* @brief Equality operator compares ElemParams (which will be dynamic casted)
*
* @param &rhs is the specified Poly to be compared with this Poly.
* @return True if this Poly represents the same values as the specified
* DCRTPoly, False otherwise
*/
bool operator==(const ElemParams<IntType> &rhs) const {
if (dynamic_cast<const ILParamsImpl<IntType> *>(&rhs) == nullptr) // 动态类型转换
return false;
return ElemParams<IntType>::operator==(rhs);
}
下面这个函数供输出运算符调用,输出运算符重载在父类实现。
private:
std::ostream &doprint(std::ostream &out) const {
out << "ILParams ";
ElemParams<IntType>::doprint(out);
out << std::endl;
return out;
}
save和load函数
public:
template <class Archive>
void save(Archive &ar, std::uint32_t const version) const {
ar(::cereal::base_class<ElemParams<IntType>>(this));
}
template <class Archive>
void load(Archive &ar, std::uint32_t const version) {
if (version > SerializedVersion()) {
PALISADE_THROW(deserialize_error,
"serialized object version " + std::to_string(version) +
" is from a later version of the library");
}
ar(::cereal::base_class<ElemParams<IntType>>(this));
}
std::string SerializedObjectName() const { return "ILParms"; }
static uint32_t SerializedVersion() { return 1; }
};
\core\include\lattice\ildcrtparams.h
Wraps parameters for integer lattice operations using double-CRT representation. Inherits from ElemParams.
class ILDCRTParams : public ElemParams
/**
* @brief Parameters for array of ideal lattices (used for Double-CRT).
*
* The double-CRT representation of polynomials is a common optimization for
* lattice encryption operations. Basically, it allows large-modulus polynamials
* to be represented as multiple smaller-modulus polynomials. The double-CRT
* representations are discussed theoretically here:
* - Gentry C., Halevi S., Smart N.P. (2012) Homomorphic Evaluation of the AES
* Circuit. In: Safavi-Naini R., Canetti R. (eds) Advances in Cryptology –
* CRYPTO 2012. Lecture Notes in Computer Science, vol 7417. Springer, Berlin,
* Heidelberg
*/
template <typename IntType>
class ILDCRTParams : public ElemParams<IntType> {
public:
static const usint DEFAULT_NBITS = 20;
typedef IntType Integer;
using ILNativeParams = ILParamsImpl<NativeInteger>; // typedef 不能够直接给模板类进行取别名。
首先看私有成员,比父类多出两个成员
m_parms是一个ILNativeParams对象的数组,每个对象包含ILParamsImpl<nativeInteger>中的所有成员,即cyclotomicOrder、ringDimension、isPowerOfTwo、ciphertextModulus、rootOfUnity、bigCiphertextModulus、bigRootOfUnity和函数。
originalModulus并不真正存放密文模数,ciphertextModulus才真正存放密文模数。
private:
std::ostream &doprint(std::ostream &out) const {
out << "ILDCRTParams ";
ElemParams<IntType>::doprint(out);
out << std::endl << " Parms:" << std::endl;
for (size_t i = 0; i < m_parms.size(); i++) {
out << " " << i << ":" << *m_parms[i] << std::endl;
}
out << "OriginalModulus " << originalModulus << std::endl;
return out;
}
// array of smaller ILParams
std::vector<std::shared_ptr<ILNativeParams>> m_parms;
// original modulus when being constructed from a Poly or when
// ctor is passed that parameter
// note orignalModulus will be <= composite modules
// i.e. \Prod_i=0^k-1 m_params[i]->GetModulus() 它们的乘积
// note not using ElemParams::ciphertextModulus due to object stripping
Integer originalModulus;
};
构造函数,一个一个来
第一个:
/**
* @brief Constructor with basic parameter set.
* q is selected as FirstPrime(bits, order)
* @param order the order of the ciphertext.
* @param depth is the size of the tower.
* @param bits is the number of bits of each tower's moduli.
*/
explicit ILDCRTParams(usint order = 0, usint depth = 1, // 声明为explicit的构造函数不能在隐式转换中使用。也就是不能用隐式转换法创建对象。
usint bits = DEFAULT_NBITS);
第二个:
传入cyclotomicOrder,modulus,rootOfUnity参数,其中rootOfUnity参数没有用到,modulus参数限制了密文模数的大小,先声明三个变量:numOfTower保存模数的数目,moduli保存模数数组,rootsOtUnity保存与模数对应的单位根数组,当compositeModulus大于等于modulus时停止,将moduli和rootsOfUnity保存到成员m_params中,然后重新计算密文模数,将其保存到ciphertextModulus中。originalModulus保存modulus。
这个构造函数与bigModulus无关。
/**
* @brief Constructor with basic parameters
*
* @param cyclotomic_order the order of the ciphertext
* @param &modulus is the modulus for the primary ciphertext. 是总的密文模数q
* @param rootsOfUnity is unused
*/
ILDCRTParams(const usint cyclotomic_order, const IntType &modulus,
const IntType &rootOfUnity)
: ElemParams<IntType>(cyclotomic_order, modulus, 0, 0, 0) {
// NOTE parms generation uses this constructor to make an empty parms that
// it will later populate during the gen process. For that special case... populate:增添数据
// we don't populate, and we just return
if (cyclotomic_order == 0) return;
DEBUG_FLAG(false);
DEBUG(
"in ILDCRTParams(const usint cyclotomic_order, const IntType &modulus, "
"const IntType& rootOfUnity");
DEBUGEXP(cyclotomic_order);
DEBUGEXP(modulus);
DEBUGEXP(rootOfUnity);
usint numOfTower = 1;
std::vector<NativeInteger> moduli;
std::vector<NativeInteger> rootsOfUnity;
NativeInteger q =
FirstPrime<NativeInteger>(DEFAULT_NBITS, cyclotomic_order); // q = 1 mod cyclotomic_order
IntType compositeModulus(1);
for (;;) {
moduli.push_back(q);
rootsOfUnity.push_back(RootOfUnity(cyclotomic_order, q));
compositeModulus = compositeModulus * IntType(q.ConvertToInt());
if (compositeModulus >= modulus) break; // 直到compositeModulus大于形参
q = NextPrime(q, cyclotomic_order);
numOfTower++; // numOfTower记录有几个模数
}
originalModulus = modulus; // originalModulus被设置为形参
DEBUGEXP(compositeModulus);
DEBUGEXP(moduli);
DEBUGEXP(rootsOfUnity);
DEBUGEXP(m_parms.size());
for (size_t i = 0; i < moduli.size(); i++) {
m_parms.push_back(std::make_shared<ILNativeParams>(
cyclotomic_order, moduli[i], rootsOfUnity[i]));
}
RecalculateModulus();
DEBUGEXP(m_parms.size());
}
第三个:
这个构造函数直接传入对应的四个数组,用传入的参数进行初始化。
/**
* @brief Constructor with some pre-computed parameters provided as input.
* @param cyclotomic_order the order of the ciphertext
* @param moduli the list of the smaller moduli of the component polynomials.
* @param rootsOfUnity the list of the smaller roots of unity of the component
* polynomials.
* @param moduliBig the list of the big moduli of the component polynomials
* (arbitrary cyclotomics).
* @param rootsOfUnityBig the list of the roots of unity of the component
* polynomials for big moduli (arbitrary cyclotomics).
* @return
*/
ILDCRTParams(const usint cyclotomic_order,
const std::vector<NativeInteger> &moduli,
const std::vector<NativeInteger> &rootsOfUnity,
const std::vector<NativeInteger> &moduliBig = {},
const std::vector<NativeInteger> &rootsOfUnityBig = {},
const IntType &inputOriginalModulus = IntType(0))
: ElemParams<IntType>(cyclotomic_order, 0, 0, 0, 0) {
this->originalModulus = inputOriginalModulus;
if (moduli.size() != rootsOfUnity.size()) {
PALISADE_THROW(math_error,
"sizes of moduli and roots of unity do not match");
}
if (moduliBig.size() == moduli.size()) { // 只有有相同元素个数的时候才设置bigModuli
for (size_t i = 0; i < moduli.size(); i++) {
m_parms.push_back(std::make_shared<ILNativeParams>(
cyclotomic_order, moduli[i], rootsOfUnity[i], moduliBig[i],
rootsOfUnityBig[i]));
}
RecalculateBigModulus();
} else {
for (size_t i = 0; i < moduli.size(); i++) {
m_parms.push_back(std::make_shared<ILNativeParams>(
cyclotomic_order, moduli[i], rootsOfUnity[i]));
}
}
RecalculateModulus();
}
第四个:只传入一个数组,保存模数数组,对应的单位根在ILNativeParams构造函数中计算。
/**
* @brief Constructor with only cylotomic order and chain of moduli.
* Multiplied values of the chain of moduli is automatically calculated. Root
* of unity of the modulus is also calculated.
*
* @param cyclotomic_order the order of the ciphertext
* @param &moduli is the tower of moduli
*/
ILDCRTParams(const usint cyclotomic_order,
const std::vector<NativeInteger> &moduli,
const IntType &inputOriginalModulus = IntType(0))
: ElemParams<IntType>(cyclotomic_order, 0, 0, 0, 0) {
this->originalModulus = inputOriginalModulus;
for (size_t i = 0; i < moduli.size(); i++) {
m_parms.push_back(std::make_shared<ILNativeParams>(cyclotomic_order,
moduli[i], 0, 0, 0));
}
RecalculateModulus();
}
第五个:一步到位
/**
* @brief Constructor that takes in the cyclotomic order and the component
* parameters of the component moduli.
* @param cyclotomic_order the primary cyclotomic order. This is not checked
* against the component moduli.
* @param parms the componet parameters.
* @return
*/
ILDCRTParams(const usint cyclotomic_order,
std::vector<std::shared_ptr<ILNativeParams>> &parms,
const IntType &inputOriginalModulus = IntType(0))
: ElemParams<IntType>(cyclotomic_order, 0, 0, 0, 0), m_parms(parms) {
this->originalModulus = inputOriginalModulus;
RecalculateModulus();
}
赋值操作符重载
/**
* Assignment Operator.
*
* @param &rhs the copied ILDCRTParams.
* @return the resulting ILDCRTParams.
*/
const ILDCRTParams &operator=(const ILDCRTParams &rhs) {
ElemParams<IntType>::operator=(rhs);
originalModulus = rhs.originalModulus;
m_parms = rhs.m_parms;
return *this;
}
getter函数
// ACCESSORS
/**
* @brief Getter method for the component parameters.
* @return A vector of the component polynomial parameters.
*/
const std::vector<std::shared_ptr<ILNativeParams>> &GetParams() const {
return m_parms;
}
返回模数的一部分
/**
* @brief Getter method that returns a subset of the component parameters.
*
* @param start The index of the first tower to include in the result.
* @param end The index of the last tower to include.
* @return A vector of the component polynomial parameters.
*/
std::vector<std::shared_ptr<ILNativeParams>> GetParamPartition(
uint32_t start, uint32_t end) const {
if (end < start || end > this->GetParams().size()) {
PALISADE_THROW(math_error,
"Incorrect parameters for GetParamPartition - (start: " +
std::to_string(start) +
", end:" + std::to_string(end) + ")");
}
std::vector<std::shared_ptr<ILNativeParams>> resParams =
std::vector<std::shared_ptr<ILNativeParams>>(end - start + 1);
IntType q = IntType(1);
for (uint32_t i = 0; i <= (end - start); i++) {
resParams[i] = this->GetParams()[i + start];
q = q.Mul(IntType(this->GetParams()[i + start]->GetModulus()));
}
return resParams;
}
获取和设置originalModulus
/**
* @brief Simple getter method for the original modulus, not the ciphertex
* modulus.
* @return The original modulus, not the big ciphertext modulus.
*/
const IntType &GetOriginalModulus() const { return originalModulus; }
/**
* @brief Simple setter method for the original modulus, not the ciphertex
* modulus.
* @return void
*/
void SetOriginalModulus(const IntType &inputOriginalModulus) {
originalModulus = inputOriginalModulus;
}
操作符重载
/**
* @brief Getter method for the component parameters of a specific index.
* @param i the index of the parameters to return. Note this this call is
* unguarded if the index is out of bounds.
* @return the parameters at index i.
*/
std::shared_ptr<ILNativeParams> &operator[](const usint i) {
return m_parms[i];
}
去掉最后一个模数
/**
* @brief Removes the last parameter set and adjust the multiplied moduli.
*
*/
void PopLastParam() {
this->ciphertextModulus /=
IntType(m_parms.back()->GetModulus().ConvertToInt());
m_parms.pop_back();
}
析构函数
/**
* Destructor.
*/
~ILDCRTParams() {}
重载相等运算符
/**
* @brief Equality operator checks if the ElemParams are the same.
*
* @param &other ElemParams to compare against.
* @return the equality check results.
*/
bool operator==(const ElemParams<IntType> &other) const {
const auto *dcrtParams = dynamic_cast<const ILDCRTParams *>(&other);
if (dcrtParams == nullptr) return false;
if (ElemParams<IntType>::operator==(other) == false) return false; // 先判断父类的元素
if (m_parms.size() != dcrtParams->m_parms.size()) return false;
for (size_t i = 0; i < m_parms.size(); i++) { // 再判断子类自己的元素
if (*m_parms[i] != *dcrtParams->m_parms[i]) return false;
}
// if (originalModulus != dcrtParams->originalModulus) // originalModulus可以不同,注释掉了
// return false;
return true;
}
/**
* @brief Method to recalculate the composite modulus from the component
* moduli.
*/
void RecalculateModulus() {
this->ciphertextModulus = 1;
for (usint i = 0; i < m_parms.size(); i++) {
this->ciphertextModulus =
this->ciphertextModulus *
IntType(m_parms[i]->GetModulus().ConvertToInt());
}
}
/**
* @brief Method to recalculate the big composite modulus from the component
* moduli.
*/
void RecalculateBigModulus() {
this->bigCiphertextModulus = 1;
for (usint i = 0; i < m_parms.size(); i++) {
this->bigCiphertextModulus =
this->bigCiphertextModulus *
IntType(m_parms[i]->GetBigModulus().ConvertToInt());
}
}
save和load函数
template <class Archive>
void save(Archive &ar, std::uint32_t const version) const {
ar(::cereal::base_class<ElemParams<IntType>>(this));
ar(::cereal::make_nvp("p", m_parms));
ar(::cereal::make_nvp("m", originalModulus));
}
template <class Archive>
void load(Archive &ar, std::uint32_t const version) {
if (version > SerializedVersion()) {
PALISADE_THROW(deserialize_error,
"serialized object version " + std::to_string(version) +
" is from a later version of the library");
}
ar(::cereal::base_class<ElemParams<IntType>>(this));
ar(::cereal::make_nvp("p", m_parms));
ar(::cereal::make_nvp("m", originalModulus));
}
std::string SerializedObjectName() const { return "DCRTParams"; }
static uint32_t SerializedVersion() { return 1; }
\core\include\lattice\elemparamfactory.h
这个类是用来生成上面参数类对象的。
#include "lattice/ildcrtparams.h"
#include "lattice/ilparams.h"
#include "math/backend.h"
#include "utils/parmfactory.h"
成员全是static
// predefined values of m are 16, 1024, 2048, 4096, 8192, 16384, 32768 and 65536
// the items in ElementOrder are an index into DefaultSet[]
enum ElementOrder { M16 = 0, M1024, M2048, M4096, M8192, M16384, M32768 };
class ElemParamFactory {
public:
static struct ElemParmSet {
usint m; // cyclotomic order
usint n; // ring dimension
string q; // ciphertext modulus
string ru; // root of unity
} DefaultSet[];
返回大于等于 m m m 的最接近的 index
static size_t GetNearestIndex(usint m) {
size_t sIdx = 0;
if (DefaultSet[0].m < m) {
for (sIdx = 1; DefaultSet[sIdx].m != 0; sIdx++) {
if (m <= DefaultSet[sIdx].m) break;
}
}
if (DefaultSet[sIdx].m == 0) sIdx--;
return sIdx;
}
P应该就是上面三种 params 类型
/**
* GenElemParams for a particular predefined cyclotomic order
*
* @param o - the order (an ElementOrder)
* @return new params
*/
template <typename P>
static shared_ptr<P> GenElemParams(ElementOrder o) {
DEBUG_FLAG(false);
DEBUG("in GenElemParams(ElementOrder o)");
return std::make_shared<P>(
DefaultSet[static_cast<int>(o)].m,
typename P::Integer(DefaultSet[static_cast<int>(o)].q),
typename P::Integer(DefaultSet[static_cast<int>(o)].ru));
}
/**
* GenElemParams for a particular cyclotomic order - finds the predefined
* order that's >= m
*
* @param m - order
* @return new params
*/
template <typename P>
static shared_ptr<P> GenElemParams(usint m) {
DEBUG_FLAG(false);
DEBUG("in GenElemParams(usint m)");
size_t sIdx = GetNearestIndex(m);
return std::make_shared<P>(DefaultSet[sIdx].m,
typename P::Integer(DefaultSet[sIdx].q),
typename P::Integer(DefaultSet[sIdx].ru));
}
/**
* GenElemParams for a particular cyclotomic order and bits in q
* NOTE this is deprecated and will go away once ParamsGen is fully 注意:这已被弃用,一旦ParamsGen完全实现,它就会消失
* implemented
*
* @param m - cyclotomic order
* @param bits # of bits in q
* @return new params
*/
template <typename P>
static shared_ptr<P> GenElemParams(usint m, usint bits, usint towersize = 1) {
DEBUG_FLAG(false);
DEBUG("in GenElemParams(usint m, usint bits, usint towers)");
typename P::Integer q = FirstPrime<typename P::Integer>(bits, m);
typename P::Integer ru = RootOfUnity<typename P::Integer>(m, q);
return std::make_shared<P>(m, q, ru);
}
/**
* GenElemParams given the three components directly
*
* @param m - cyclotomic order
* @param ctModulus - ciphertext modulus
* @param rootUnity - root of unity
* @return
*/
template <typename P>
static shared_ptr<P> GenElemParams(usint m,
const typename P::Integer& ctModulus,
const typename P::Integer& rootUnity) {
DEBUG_FLAG(false);
DEBUG("in GenElemParams(usint m, const typename P::Integer etc)");
return std::make_shared<P>(m, ctModulus, rootUnity);
}
};
下面是实现
GenerateDCRTParams 是 utils/parmfactory.h 中惟一的函数。
template <>
inline shared_ptr<ILDCRTParams<M2Integer>>
ElemParamFactory::GenElemParams<ILDCRTParams<M2Integer>>(usint m, usint bits,
usint towersize) {
DEBUG_FLAG(false);
DEBUG(
"in GenElemParams<ILDCRTParams<M2Integer>>(usint m, usint bits, usint "
"towersize)");
DEBUGEXP(m);
DEBUGEXP(bits);
DEBUGEXP(towersize);
return GenerateDCRTParams<M2Integer>(m, towersize, bits);
}
template <>
inline shared_ptr<ILDCRTParams<M4Integer>>
ElemParamFactory::GenElemParams<ILDCRTParams<M4Integer>>(usint m, usint bits,
usint towersize) {
DEBUG_FLAG(false);
DEBUG(
"in GenElemParams<ILDCRTParams<M4Integer>>(usint m, usint bits, usint "
"towersize)");
DEBUGEXP(m);
DEBUGEXP(bits);
DEBUGEXP(towersize);
return GenerateDCRTParams<M4Integer>(m, towersize, bits);
}
#ifdef WITH_NTL
template <>
inline shared_ptr<ILDCRTParams<M6Integer>>
ElemParamFactory::GenElemParams<ILDCRTParams<M6Integer>>(usint m, usint bits,
usint towersize) {
DEBUG_FLAG(false);
DEBUG(
"in GenElemParams<ILDCRTParams<M6Integer>>(usint m, usint bits, usint "
"towersize)");
DEBUGEXP(m);
DEBUGEXP(bits);
DEBUGEXP(towersize);
return GenerateDCRTParams<M6Integer>(m, towersize, bits);
}
utils\parmfactory.h 中实现的 GererateDCRTParams函数
/**
* Generate an ILDCRTParams with a given number of parms, with cyphertext moduli
* of at least a given size
* @param m - order
* @param numOfTower - # of polynomials
* @param pbits - number of bits in the prime, to start with
* @return
*/
template <typename I>
inline shared_ptr<ILDCRTParams<I>> GenerateDCRTParams(usint m, usint numOfTower,
usint pbits) {
DEBUG_FLAG(false);
DEBUG("in GenerateDCRTParams");
DEBUGEXP(m);
DEBUGEXP(numOfTower);
DEBUGEXP(pbits);
if (numOfTower == 0) {
PALISADE_THROW(math_error, "Can't make parms with numOfTower == 0");
}
std::vector<NativeInteger> moduli(numOfTower);
std::vector<NativeInteger> rootsOfUnity(numOfTower);
NativeInteger q = FirstPrime<NativeInteger>(pbits, m);
I modulus(1);
usint j = 0;
DEBUGEXP(q);
for (;;) {
moduli[j] = q;
rootsOfUnity[j] = RootOfUnity(m, q);
modulus = modulus * I(q.ConvertToInt());
DEBUG("j " << j << " modulus " << q << " rou " << rootsOfUnity[j]);
if (++j == numOfTower) break;
q = NextPrime(q, m);
}
auto params = std::make_shared<ILDCRTParams<I>>(m, moduli, rootsOfUnity);
return params;
}
\core\include\lattice\stdlatticeparms.h
Header for the standard values for Lattice Parms, as determined by homomorphicencryption.org
定义了一些同态加密中用到的参数
// this is the representation of the standard lattice parameters defined in the
// Homomorphic Encryption Standard, as defined by
// http://homomorphicencryption.org
// given a distribution type and a security level, you can get the maxQ for a
// given ring dimension, and you can get the ring dimension given a maxQ
// The code below is very specific to the layout of the DistributionType and
// SecurityLevel enums IF you change them, go look at and change byRing and
// byLogQ
DistributationType
均匀分布,误差分布,三项分布
enum DistributionType {
HEStd_uniform,
HEStd_error,
HEStd_ternary,
};
SecurityLevel
enum SecurityLevel {
HEStd_128_classic,
HEStd_192_classic,
HEStd_256_classic,
HEStd_NotSet,
};
inline std::ostream& operator<<(std::ostream& s, SecurityLevel sl) {
switch (sl) {
case HEStd_128_classic:
s << "HEStd_128_classic";
break;
case HEStd_192_classic:
s << "HEStd_192_classic";
break;
case HEStd_256_classic:
s << "HEStd_256_classic";
break;
case HEStd_NotSet:
s << "HEStd_NotSet";
break;
default:
s << "UKNOWN";
break;
}
return s;
}
StdLatticeParm 类
每个对象有四个成员(private),并且有它们对应的getter函数(public),剩下的都是public static成员,包括两个二位数组保存map,第一种map用ringDim成员索引,第二种map用maxLogQ成员索引,还有个vector保存StdLatticeParm成员,bool类型的initialized指示 这个vector成员是否被map到上面连个二维数组中。静态函数包括初始化、查找maxq和ringDim操作。
std::pair 包括两个成员 first 和 second,可以直接使用。
class {
DistributionType distType;
usint ringDim;
SecurityLevel minSecLev;
usint maxLogQ;
// NOTE!!! the declaration below relies upon there being three possible values
// for the first index (the distribution type), and three possible values for
// the second index (the security level)
// The values in the enums, above, meet this criteria
// it's also important that the different values are numbered from 0-2
// again, the enums above do this
// DO NOT change the values of the enums to be anything other than consecutive
// numbers starting from 0, or this code will break in strange ways, and you
// will suffer MAKE SURE that the number of entries in the DistributionType
// enum is == the first index, and MAKE SURE that the number of entries in the
// SecurityLevel enum is == the second index
static map<usint, StdLatticeParm*> byRing[3][3];
static map<usint, StdLatticeParm*> byLogQ[3][3];
static vector<StdLatticeParm> StandardLatticeParmSets;
static bool initialized;
public:
StdLatticeParm(DistributionType distType, usint ringDim,
SecurityLevel minSecLev, usint maxLogQ)
: distType(distType),
ringDim(ringDim),
minSecLev(minSecLev),
maxLogQ(maxLogQ) {}
static void initializeLookups() {
for (size_t i = 0; i < StandardLatticeParmSets.size(); i++) {
StdLatticeParm& s = StandardLatticeParmSets[i];
byRing[static_cast<int>(s.distType)][static_cast<int>(s.minSecLev)]
[s.ringDim] = &s;
byLogQ[static_cast<int>(s.distType)][static_cast<int>(s.minSecLev)]
[s.maxLogQ] = &s;
}
initialized = true;
}
static usint FindMaxQ(DistributionType distType, SecurityLevel minSecLev,
usint ringDim) {
int distTypeIdx = static_cast<int>(distType);
int minSecLevIdx = static_cast<int>(minSecLev);
if (!initialized) initializeLookups();
auto it = byRing[distTypeIdx][minSecLevIdx].find(ringDim);
if (it == byRing[distTypeIdx][minSecLevIdx].end()) return 0;
return it->second->getMaxLogQ();
}
static usint FindRingDim(DistributionType distType, SecurityLevel minSecLev,
usint curLogQ) {
if (!initialized) initializeLookups();
usint prev = 0;
int distTypeIdx = static_cast<int>(distType);
int minSecLevIdx = static_cast<int>(minSecLev);
for (std::pair<const unsigned int, StdLatticeParm*>& it :
byLogQ[distTypeIdx][minSecLevIdx]) {
if ((curLogQ <= it.second->getMaxLogQ()) && (curLogQ > prev))
return it.second->getRingDim();
prev = it.second->getMaxLogQ();
}
return 65536;
}
DistributionType getDistType() const { return distType; }
usint getRingDim() const { return ringDim; }
SecurityLevel getMinSecLev() const { return minSecLev; }
usint getMaxLogQ() const { return maxLogQ; }
};
\core\include\lattice\ilelement.h
Represents and defines integer lattice element objects ins Palisade.
ILElement 抽象类
element 是所有纯虚函数的返回类型
/**
* @brief Interface for ideal lattices
*
* Every lattice must implement these pure virtuals in order to properly
* interoperate with PALISADE PKE. Element is the return type for all of these
* virtual functions. There is no constructor here in the base class; it
* contains no data to construct.
*/
template <typename Element, typename VecType>
class ILElement : public Serializable {
using IntType = typename VecType::Integer;
public:
克隆函数:
/**
* @brief Clone the object by making a copy of it and returning the copy
* @return new Element
*/
virtual Element Clone() const = 0;
/**
* @brief Clone the object, but have it contain nothing
* @return new Element
*/
virtual Element CloneEmpty() const = 0;
/**
* @brief Clones the element's parameters, leaves vector initialized to 0
* @return new Element
*/
virtual Element CloneParametersOnly() const = 0;
/**
* @brief Clones the element with parameters and with noise for the vector
* @param dgg
* @param format
* @return new Element
*/
virtual Element CloneWithNoise(
const DiscreteGaussianGeneratorImpl<VecType> &dgg,
Format format = Format::EVALUATION) const = 0;
析构函数
/**
* @brief Standard destructor
*/
virtual ~ILElement() {}
一些赋值操作符重载
// Assignment operators
/**
* @brief Assignment operator that copies elements.
* @param rhs
*/
virtual const Element &operator=(const Element &rhs) = 0;
/**
* @brief Assignment operator that copies elements.
* @param rhs
*/
virtual const Element &operator=(Element &&rhs) = 0;
/**
* @brief Assignment operator that copies elements.
* @param rhs
*/
virtual const Element &operator=(std::initializer_list<uint64_t> rhs) = 0;
GETTER函数
// GETTERS
/**
* @brief Get format of the element
*
* @return Format is either COEFFICIENT or EVALUATION
*/
virtual Format GetFormat() const = 0;
/**
* @brief Get the length of the element.
*
* @return length
*/
virtual usint GetLength() const = 0;
/**
* @brief Get modulus of the element
*
* @return the modulus.
*/
virtual const IntType &GetModulus() const = 0;
/**
* @brief Get the values for the element
*
* @return the vector.
*/
virtual const VecType &GetValues() const = 0;
/**
* @brief Get the cyclotomic order
*
* @return order
*/
virtual usint GetCyclotomicOrder() const = 0;
/**
* @brief Gets the Value in the Element that is At Index and returns it.
* This is only implemented for some derived classes, so the default
* implementation throws an exception
*
* @param i is the index.
* @return will throw an error.
*/
virtual IntType &at(usint i) {
PALISADE_THROW(not_implemented_error, "at not implemented");
}
virtual const IntType &at(usint i) const {
PALISADE_THROW(not_implemented_error, "const at not implemented");
}
virtual IntType &operator[](usint i) {
PALISADE_THROW(not_implemented_error, "[] not implemented");
}
virtual const IntType &operator[](usint i) const {
PALISADE_THROW(not_implemented_error, "const [] not implemented");
}
// virtual NativePoly DecryptionCRTInterpolate(PlaintextModulus ptm) const
//= 0;
一些运算操作,返回的都是Element类型
// OPERATORS
/**
* @brief Unary negation on a lattice 取负号操作
* @return -lattice
*/
virtual Element operator-() const = 0;
/**
* @brief Scalar addition - add an element to the first index only. 标量加法,只加到第一个索引上
* This operation is only allowed in COEFFICIENT format. 仅在系数表示下才能用
*
* @param &element is the element to add entry-wise.
* @return is the return of the addition operation.
*/
virtual Element Plus(const IntType &element) const = 0;
/**
* @brief Scalar subtraction - subtract an element frp, all entries.
*
* @param &element is the element to subtract entry-wise.
* @return is the return value of the minus operation.
*/
virtual Element Minus(const IntType &element) const = 0;
/**
* @brief Scalar multiplication - multiply all entries.
*
* @param &element is the element to multiply entry-wise.
* @return is the return value of the times operation.
*/
virtual Element Times(const IntType &element) const = 0;
/**
* @brief Scalar multiplication - mulltiply by a signed integer
*
* @param &element is the element to multiply entry-wise.
* @return is the return value of the times operation.
*/
virtual Element Times(
bigintnat::NativeInteger::SignedNativeInt element) const = 0;
前面都是与一个数的运算,后面是与一个Element类型的运算
/**
* @brief Performs an addition operation and returns the result.
*
* @param &element is the element to add with.
* @return is the result of the addition.
*/
virtual Element Plus(const Element &element) const = 0;
/**
* @brief Performs a subtraction operation and returns the result.
*
* @param &element is the element to subtract with.
* @return is the result of the subtraction.
*/
virtual Element Minus(const Element &element) const = 0;
/**
* @brief Performs a multiplication operation and returns the result.
*
* @param &element is the element to multiply with.
* @return is the result of the multiplication.
*/
virtual Element Times(const Element &element) const = 0;
运算符重载
// overloaded op= operators
/**
* @brief Performs += operation with a BigInteger and returns the result.
*
* @param &element is the element to add
* @return is the result of the addition.
*/
virtual const Element &operator+=(const IntType &element) = 0;
/**
* @brief Performs -= operation with a BigInteger and returns the result.
*
* @param &element is the element to subtract
* @return is the result of the addition.
*/
virtual const Element &operator-=(const IntType &element) = 0;
/**
* @brief Performs *= operation with a BigInteger and returns the result.
*
* @param &element is the element to multiply by
* @return is the result of the multiplication.
*/
virtual const Element &operator*=(const IntType &element) = 0;
/**
* @brief Performs an addition operation and returns the result.
*
* @param &element is the element to add
* @return is the result of the addition.
*/
virtual const Element &operator+=(const Element &element) = 0;
/**
* @brief Performs an subtraction operation and returns the result.
*
* @param &element is the element to subtract
* @return is the result of the addition.
*/
virtual const Element &operator-=(const Element &element) = 0;
/**
* @brief Performs an multiplication operation and returns the result.
*
* @param &element is the element to multiply by
* @return is the result of the multiplication.
*/
virtual const Element &operator*=(const Element &element) = 0;
/**
* @brief Equality operator. Compares values of element to be compared to.
* @param element the element to compare to.
*/
virtual bool operator==(const Element &element) const = 0;
/**
* @brief Inequality operator. Compares values of element to be compared to.
* @param element the element to compare to.
*/
inline bool operator!=(const Element &element) const {
return !(*this == element);
}
/**
* @brief Adds one to every entry of the Element, in place
*/
virtual void AddILElementOne() = 0;
自同构操作
/**
* @brief Performs an automorphism transform operation and returns the result.
*
* @param &i is the element to perform the automorphism transform with.
* @return is the result of the automorphism transform.
*/
virtual Element AutomorphismTransform(const usint &i) const = 0;
/**
* @brief Performs an automorphism transform operation using precomputed bit
* reversal indices.
*
* @param &i is the element to perform the automorphism transform with.
* @param &map a vector with precomputed indices
* @return is the result of the automorphism transform.
*/
virtual Element AutomorphismTransform(
usint i, const std::vector<uint32_t> &map) const = 0;
/**
* @brief Transpose the ring element using the automorphism operation
*
* @return is the result of the transposition.
*/
virtual Element Transpose() const = 0;
基分解,用于 relinearlisation
base为 2 的幂
/**
* @brief Write the element as \f$ \sum\limits{i=0}^{\lfloor {\log q/base}
* \rfloor} {(base^i u_i)} \f$ and return the vector of \f$ \left\{u_0,
* u_1,...,u_{\lfloor {\log q/base} \rfloor} \right\} \in R_{{base}^{\lceil
* {\log q/base} \rceil}} \f$; This is used as a subroutine in the
* relinearization procedure.
*
* @param baseBits is the number of bits in the base, i.e., base = 2^baseBits
* @param evalModeAnswer - if true, convert the resultant polynomials to
* evaluation mode
* @result is the pointer where the base decomposition vector is stored
*/
virtual std::vector<Element> BaseDecompose(
usint baseBits, bool evalModeAnswer = true) const = 0;
除法然后四舍五入
除以大整数
q
q
q
/**
* @brief Scalar division followed by rounding operation - operation on all
* entries.
*
* @param &q is the element to divide entry-wise.
* @return is the return value of the divide, followed by rounding operation.
*/
virtual Element DivideAndRound(const IntType &q) const = 0;
判断是否有逆
/**
* @brief Determines if inverse exists
*
* @return true if there exists a multiplicative inverse.
*/
virtual bool InverseExists() const = 0;
求无穷范数
/**
* @brief Returns the infinity norm, basically the largest value in the ring
* element.
*
* @return the largest value in the ring element.
*/
virtual double Norm() const = 0;
判断向量是否为空
/**
* @brief Returns true if the vector is empty/ m_values==nullptr
*
* @return true if the vector is empty and all values nullptr. false
* otherwise.
*/
virtual bool IsEmpty() const = 0;
稀疏操作
/**
* @brief Make the element Sparse for SHE KeyGen operations.
* Sets every index not equal to zero mod the wFactor to zero.
*
* @param &wFactor ratio between the original element's ring dimension and the
* new ring dimension.
*/
virtual void MakeSparse(const uint32_t &wFactor) = 0;
模 2 2 2 操作
/**
* @brief Calculate Element mod 2
*
* @return result of performing a mod-2 operation on the element.
*/
virtual Element ModByTwo() const = 0;
求乘法逆
/**
* @brief Calculate and return the Multiplicative Inverse of the element
* @return the multiplicative inverse of the element, if it exists.
*/
virtual Element MultiplicativeInverse() const = 0;
乘以 p q \frac{p}{q} qp 然后四舍五入
/**
* @brief Scalar multiplication followed by division and rounding operation -
* operation on all entries.
*
* @param &p is the integer muliplicand.
* @param &q is the integer divisor.
* @return is the return value of the multiply, divide and followed by
* rounding operation.
*/
virtual Element MultiplyAndRound(const IntType &p,
const IntType &q) const = 0;
跟基分解相关联的操作,用于 relinearlisation
/**
* @brief Calculate a vector of elements by raising the base element to
* successive powers
*
* @param baseBits
* @return
*/
virtual std::vector<Element> PowersOfBase(usint baseBits) const = 0;
求模操作
/**
* @brief Mod - perform a modulus operation.
* Does proper mapping of [-modulus/2, modulus/2) to [0, modulus). 将从 [-modulus/2,modulus/2) 正确映射到 [0,modulus)
*
* @param modulus is the modulus to use.
* @return is the return value of the modulus.
*/
virtual Element Mod(const IntType &modulus) const = 0;
模切换
/**
* @brief Switch modulus and adjust the values
*
* @param &modulus is the modulus to be set.
* @param &rootOfUnity is the corresponding root of unity for the modulus
* @param &modulusArb is the modulus used for arbitrary cyclotomics CRT
* @param &rootOfUnityArb is the corresponding root of unity for the modulus
* ASSUMPTION: This method assumes that the caller provides the correct
* rootOfUnity for the modulus.
*/
virtual void SwitchModulus(const IntType &modulus, const IntType &rootOfUnity,
const IntType &modulusArb = IntType::ZERO,
const IntType &rootOfUnityArb = IntType::ZERO) = 0;
转换格式,即在CRT和系数表示之间转换
/**
* @brief convert from Coefficient to CRT or vice versa; calls FFT and inverse
* FFT.
*/
virtual void SwitchFormat() = 0;
/**
* @brief Sets the format/representation of the element.
* @param format the format/representation to set.
*/
void SetFormat(const Format format) {
if (this->GetFormat() != format) {
this->SwitchFormat();
}
}
};
\core\include\lattice\backend.h
This file contains the functionality to switch between lattice backends
#include "lattice/elemparams.h"
#include "lattice/ildcrtparams.h"
#include "lattice/ilelement.h"
#include "lattice/ilparams.h"
#include "lattice/poly.h"
声明
namespace lbcrypto {
template <typename IntType>
class ILParamsImpl;
template <typename VecType>
class PolyImpl;
using M2Poly = PolyImpl<M2Vector>;
using M4Poly = PolyImpl<M4Vector>;
#ifdef WITH_NTL
using M6Poly = PolyImpl<M6Vector>;
#endif
using NativePoly = PolyImpl<NativeVector>;
using NativePoly64 = NativePoly;
using M2Params = ILParamsImpl<M2Integer>;
using M4Params = ILParamsImpl<M4Integer>;
#ifdef WITH_NTL
using M6Params = ILParamsImpl<M6Integer>;
#endif
using ILNativeParams = ILParamsImpl<NativeInteger>;
默认设置
// the default for the backend...
using ILParams = ILParamsImpl<BigInteger>;
using Poly = PolyImpl<BigVector>;
} // namespace lbcrypto
下面定义与double-CRT有关
#include "lattice/dcrtpoly.h"
namespace lbcrypto {
template <typename IntType>
class ILDCRTParams;
template <typename VecType>
class DCRTPolyImpl;
using M2DCRTPoly = DCRTPolyImpl<M2Vector>;
using M4DCRTPoly = DCRTPolyImpl<M4Vector>;
#ifdef WITH_NTL
using M6DCRTPoly = DCRTPolyImpl<M6Vector>;
#endif
using M2DCRTParams = ILDCRTParams<M2Integer>;
using M4DCRTParams = ILDCRTParams<M4Integer>;
#ifdef WITH_NTL
using M6DCRTParams = ILDCRTParams<M6Integer>;
#endif
默认设置
// the default for the backend...
using DCRTPoly = DCRTPolyImpl<BigVector>;
} // namespace lbcrypto
其他的
#ifdef WITH_NTL
#define RUN_BIG_POLYS(FUNCTION, MESSAGE) \
{ \
if (TestB2) { \
using V = M2Poly; \
FUNCTION<V>("BE2Poly " MESSAGE); \
} \
if (TestB4) { \
using V = M4Poly; \
FUNCTION<V>("BE4Poly " MESSAGE); \
} \
if (TestB6) { \
using V = M6Poly; \
FUNCTION<V>("BE6Poly " MESSAGE); \
} \
}
#define RUN_BIG_DCRTPOLYS(FUNCTION, MESSAGE) \
{ \
if (TestB2) { \
using V = M2DCRTPoly; \
FUNCTION<V>("BE2DCRTPoly " MESSAGE); \
} \
if (TestB4) { \
using V = M4DCRTPoly; \
FUNCTION<V>("BE4DCRTPoly " MESSAGE); \
} \
if (TestB6) { \
using V = M6DCRTPoly; \
FUNCTION<V>("BE6DCRTPoly " MESSAGE); \
} \
}
#else
#define RUN_BIG_POLYS(FUNCTION, MESSAGE) \
{ \
if (TestB2) { \
using V = M2Poly; \
FUNCTION<V>("BE2Poly " MESSAGE); \
} \
if (TestB4) { \
using V = M4Poly; \
FUNCTION<V>("BE4Poly " MESSAGE); \
} \
}
#define RUN_BIG_DCRTPOLYS(FUNCTION, MESSAGE) \
{ \
if (TestB2) { \
using V = M2DCRTPoly; \
FUNCTION<V>("BE2DCRTPoly " MESSAGE); \
} \
if (TestB4) { \
using V = M4DCRTPoly; \
FUNCTION<V>("BE4DCRTPoly " MESSAGE); \
} \
}
#endif
#define RUN_ALL_POLYS(FUNCTION, MESSAGE) \
{ \
RUN_BIG_POLYS(FUNCTION, MESSAGE) \
if (TestNative) { \
using V = NativePoly; \
FUNCTION<V>("Native " MESSAGE); \
} \
}
\core\include\lattice\field2n.h
Represents and defines power-of-2 fields.
class Field2n : public std::vector<std::complex>, public Serializable
继承自vector<std::complex<double>>
private成员
private:
// Format of the field element
Format format;
构造函数
public:
/**
* @brief Default Constructor
*/
Field2n() : format(Format::COEFFICIENT) {}
explicit Field2n(Format f) : format(f) {}
/**
* @brief Constructor for field element
* @param size element size
* @param f format/representation of the element. Initially set to
* Format::EVALUATION representation.
* @param initializeElementToZero flag for initializing values to zero. It is
* set to false by default.
*/
Field2n(int size, Format f = Format::EVALUATION,
bool initializeElementToZero = false)
: std::vector<std::complex<double>>(
size,
initializeElementToZero ? 0 : -std::numeric_limits<double>::max()) {
this->format = f;
}
/**
* @brief Constructor from ring element
* @param & element ring element
*/
explicit Field2n(const Poly &element);
/**
* @brief Constructor from ring element
* @param & element ring element
*/
explicit Field2n(const NativePoly &element);
/**
* @brief Constructor from DCRTPoly ring element
* @param & element ring element
*/
explicit Field2n(const DCRTPoly &element);
/**
* @brief Constructor from a ring element matrix
* @param &element ring element matrix
*/
explicit Field2n(const Matrix<int64_t> &element);
一些操作
/**
* @brief Method for getting the format/representation of the element
*
* @return format/representation of the field element
*/
Format GetFormat() const { return format; }
/**
* @brief Inverse operation for the field elements
*
* @return the inverse field element
*/
Field2n Inverse() const;
/**
* @brief Addition operation for field elements
*
* @param &rhs right hand side element for operation
* @return result of the operation
*/
Field2n Plus(const Field2n &rhs) const;
/**
* @brief Scalar addition operation for field elements
*
* @param &rhs right hand side element for operation
* @return result of the operation
*/
Field2n Plus(double rhs) const;
/**
* @brief Substraction operation for field elements
*
* @param &rhs right hand side element for operation
* @return result of the operation
*/
Field2n Minus(const Field2n &rhs) const;
/**
* @brief Multiplication operation for field elements
*
* @param &rhs right hand side element for operation
* @return result of the operation
*/
Field2n Times(const Field2n &rhs) const;
/**
* @brief Right shift operation for the field element
*
* @return the shifted field element
*/
Field2n ShiftRight();
/**
* @brief Performs an automorphism transform operation and returns the result.
*
* @param &i is the element to perform the automorphism transform with.
* @return is the result of the automorphism transform.
*/
Field2n AutomorphismTransform(size_t i) const;
/**
* @brief Transpose operation defined in section VI.B4 of
* https://eprint.iacr.org/2017/844.pdf
*
* @return the transpose of the element
*/
Field2n Transpose() const;
/**
* @brief Function for extracting odd factors of the field element
*
* @return the field element with odd parts of the initial element
*/
Field2n ExtractOdd() const;
/**
* @brief Function for extracting even factors of the field element
*
* @return the field element with even parts of the initial element
*/
Field2n ExtractEven() const;
/**
* @brief Permutation operation defined in Algorithm 4 of
* https://eprint.iacr.org/2017/844.pdf
*
* @return permuted new field element
*/
Field2n Permute() const;
/**
* @brief Inverse operation for permutation operation defined in
* Algorithm 4 of https://eprint.iacr.org/2017/844.pdf
*
* @return non permuted version of the element
*/
Field2n InversePermute() const;
/**
* @brief Operation for scalar multiplication
*
* @param d scalar for multiplication
* @return the field element with the scalar multiplication
*/
Field2n ScalarMult(double d);
/**
* @brief Method for switching format of the field elements
*/
void SwitchFormat();
/**
* @brief Sets the evaluation or coefficient representation of the field
* elements
* @param &format the enum value corresponding to coefficient or evaluation
* representation
*/
inline void SetFormat(Format format) {
if (this->format != format) {
SwitchFormat();
}
}
/**
* @brief Method for getting the size of the element
*
* @return the size of the element
*/
size_t Size() const { return this->size(); }
/**
* @brief Indexing operator for field elements
*
* @param idx index of the element
* @return element at the index
*/
inline std::complex<double> &operator[](std::size_t idx) {
return (this->at(idx));
}
/**
* @brief Indexing operator for field elements
*
* @param idx index of the element
* @return element at the index
*/
inline const std::complex<double> &operator[](std::size_t idx) const {
return (this->at(idx));
}
/**
* @brief In-place addition operation for field elements
*
* @param &element right hand side element for operation
* @return result of the operation
*/
const Field2n &operator+=(const Field2n &element) {
return *this = this->Plus(element);
}
/**
* @brief In-place subtraction operation for field elements
*
* @param &element right hand side element for operation
* @return result of the operation
*/
const Field2n &operator-=(const Field2n &element) {
return *this = this->Minus(element);
}
/**
* @brief Unary minus on a field element.
* @return negation of the field element.
*/
Field2n operator-() const {
Field2n all0(size(), this->GetFormat(), true);
return all0 - *this;
}
/**
* @brief Substraction operator for field elements
*
* @param &a left hand side field element
* @param &b right hand side field element
* @return result of the substraction operation
*/
friend inline Field2n operator-(const Field2n &a, const Field2n &b) {
return a.Minus(b);
}
/**
* @brief Addition operator for field elements
*
* @param &a left hand side field element
* @param &b right hand side field element
* @return result of the addition operation
*/
friend inline Field2n operator+(const Field2n &a, const Field2n &b) {
return a.Plus(b);
}
/**
* @brief Scalar addition operator for field elements
*
* @param &a left hand side field element
* @param &b the scalar to be added
* @return result of the addition operation
*/
friend inline Field2n operator+(const Field2n &a, double scalar) {
return a.Plus(scalar);
}
/**
* @brief Multiplication operator for field elements
*
* @param &a left hand side field element
* @param &b right hand side field element
* @return result of the multiplication operation
*/
friend inline Field2n operator*(const Field2n &a, const Field2n &b) {
return a.Times(b);
}
template <class Archive>
void save(Archive &ar, std::uint32_t const version) const {
ar(::cereal::base_class<std::vector<std::complex<double>>>(this));
ar(::cereal::make_nvp("f", format));
}
save 和 load 函数
template <class Archive>
void save(Archive &ar, std::uint32_t const version) const {
ar(::cereal::base_class<std::vector<std::complex<double>>>(this));
ar(::cereal::make_nvp("f", format));
}
template <class Archive>
void load(Archive &ar, std::uint32_t const version) {
if (version > SerializedVersion()) {
PALISADE_THROW(deserialize_error,
"serialized object version " + std::to_string(version) +
" is from a later version of the library");
}
ar(::cereal::base_class<std::vector<std::complex<double>>>(this));
ar(::cereal::make_nvp("f", format));
}
std::string SerializedObjectName() const { return "Field2n"; }
static uint32_t SerializedVersion() { return 1; }
private:
// Format of the field element
Format format;
};
类结束
/**
* @brief Stream output operator
*
* @param &os stream
* @param &m matrix to be outputted
* @return the chained stream
*/
inline std::ostream &operator<<(std::ostream &os, const Field2n &m) {
os << "[ ";
for (size_t row = 0; row < m.size(); ++row) {
os << m.at(row) << " ";
}
os << " ]\n";
return os;
}
下面两个头文件应该是核心
\core\include\lattice\poly.h
class PolyImpl : public ILElement<PolyImpl, VecType>
Ideal lattice using a vector representation
public:
using Integer = typename VecType::Integer;
using Params = ILParamsImpl<Integer>;
typedef VecType Vector;
typedef PolyImpl<VecType> PolyType;
typedef DiscreteGaussianGeneratorImpl<VecType> DggType;
typedef DiscreteUniformGeneratorImpl<VecType> DugType;
typedef TernaryUniformGeneratorImpl<VecType> TugType;
typedef BinaryUniformGeneratorImpl<VecType> BugType;
typedef PolyImpl<NativeVector> PolyNative;
typedef PolyImpl<VecType> PolyLargeType;
private属性成员
private:
// stores either coefficient or Format::EVALUATION representation
unique_ptr<VecType> m_values;
// 1 for coefficient and 0 for Format::EVALUATION format
Format m_format;
// parameters for ideal lattices
shared_ptr<Params> m_params;
void ArbitrarySwitchFormat();
};
/**
* @brief Return the element name.
* @return This method returns "PolyImpl".
*/
static const std::string GetElementName() { return "PolyImpl"; }
构造函数
/**
* @brief Default constructor
*/
PolyImpl();
/**
* @brief Construct given parameters and format
* @param params - element parameters
* @param format - Format::EVALUATION or COEFFICIENT
* @param initializeElementToZero - if true, allocates an empty vector set to
* all 0s
*/
PolyImpl(const shared_ptr<Params> params, Format format = Format::EVALUATION,
bool initializeElementToZero = false);
PolyImpl(const shared_ptr<ILDCRTParams<Integer>> params,
Format format = Format::EVALUATION,
bool initializeElementToZero = false);
/**
* @brief Construct given parameters and format
* @param initializeElementToMax - if true, initializes entries in the vector
* to the maximum value
* @param params - element parameters
* @param format - Format::EVALUATION or COEFFICIENT
*/
PolyImpl(bool initializeElementToMax, const shared_ptr<Params> params,
Format format);
下面是四种根据不同分布的构造函数
/**
* @brief Construct with a vector from a given generator
*
* @param &dgg the input discrete Gaussian Generator.
* @param ¶ms the input params.
* @param format - Format::EVALUATION or COEFFICIENT
*/
PolyImpl(const DggType &dgg, const shared_ptr<Params> params,
Format format = Format::EVALUATION);
/**
* @brief Construct with a vector from a given generator
*
* @param &bug the input Binary Uniform Generator.
* @param ¶ms the input params.
* @param format - Format::EVALUATION or COEFFICIENT
*/
PolyImpl(const BugType &bug, const shared_ptr<Params> params,
Format format = Format::EVALUATION);
/**
* @brief Construct with a vector from a given generator
*
* @param &tug the input Ternary Uniform Generator.
* @param ¶ms the input params.
* @param format - Format::EVALUATION or COEFFICIENT
* @param h - Hamming weight for sparse ternary distribution (by default, when
* h = 0, the distribution is NOT sparse)
*/
PolyImpl(const TugType &tug, const shared_ptr<Params> params,
Format format = Format::EVALUATION, uint32_t h = 0);
/**
* @brief Construct with a vector from a given generator
*
* @param &dug the input discrete Uniform Generator.
* @param ¶ms the input params.
* @param format - Format::EVALUATION or COEFFICIENT
*/
PolyImpl(DugType &dug, const shared_ptr<Params> params,
Format format = Format::EVALUATION);
/**
* @brief Create lambda that allocates a zeroed element for the case when it
* is called from a templated class
* @param params the params to use.
* @param format - Format::EVALUATION or COEFFICIENT
*/
inline static function<PolyType()> Allocator(const shared_ptr<Params> params,
Format format) {
return [=]() { return PolyType(params, format, true); }; // 返回一个函数
}
/**
* @brief Allocator for discrete uniform distribution.
*
* @param params ILParams instance that is is passed.
* @param resultFormat resultFormat for the polynomials generated.
* @param stddev standard deviation for the discrete gaussian generator.
* @return the resulting vector.
*/
inline static function<PolyType()> MakeDiscreteGaussianCoefficientAllocator(
shared_ptr<Params> params, Format resultFormat, double stddev) {
return [=]() {
DiscreteGaussianGeneratorImpl<VecType> dgg(stddev);
PolyType ilvec(dgg, params, Format::COEFFICIENT);
ilvec.SetFormat(resultFormat);
return ilvec;
};
}
/**
* @brief Allocator for discrete uniform distribution.
*
* @param params ILParams instance that is is passed.
* @param format format for the polynomials generated.
* @return the resulting vector.
*/
inline static function<PolyType()> MakeDiscreteUniformAllocator(
shared_ptr<Params> params, Format format) {
return [=]() {
DiscreteUniformGeneratorImpl<VecType> dug;
dug.SetModulus(params->GetModulus());
return PolyType(dug, params, format);
};
}
拷贝构造函数
/**
* @brief Copy constructor.
*
* @param &element the copied element.
* @param parms ILParams instance that is is passed.
*/
PolyImpl(const PolyType &element, shared_ptr<Params> parms = 0);
/**
* @brief Copy constructor from a Poly of native integers.
*
* @param &element the copied element.
* @param &format sets the format for the new Poly object
*/
PolyImpl(const PolyNative &element, Format format);
/**
* @brief Move constructor.
*
* @param &&element the copied element.
* @param parms ILParams instance that is is passed.
*/
PolyImpl(PolyType &&element, shared_ptr<Params> parms = 0);
克隆函数
/**
* @brief Clone the object by making a copy of it and returning the copy
* @return new Element
*/
PolyType Clone() const { return PolyImpl(*this); }
/**
* @brief Clone the object, but have it contain nothing
* @return new Element
*/
PolyType CloneEmpty() const { return PolyImpl(); }
/**
* @brief Clone method that creates a new PolyImpl and clones only the params.
* The tower values are empty. The tower values can be filled by another
* process/function or initializer list.
* @return new Element
*/
PolyType CloneParametersOnly() const;
/**
* @brief Clone method with noise.
* Creates a new PolyImpl and clones the params. The tower values will be
* filled up with noise based on the discrete gaussian.
*
* @param &dgg the input discrete Gaussian generator. The dgg will be the seed
* to populate the towers of the PolyImpl with random numbers.
* @return new Element
*/
PolyType CloneWithNoise(const DiscreteGaussianGeneratorImpl<VecType> &dgg,
Format format) const;
析构函数
/**
* Destructor
*/
~PolyImpl();
赋值运算符重载
/**
* @brief Assignment Operator.
*
* @param &rhs the PolyImpl to be copied.
* @return the resulting PolyImpl.
*/
const PolyType &operator=(const PolyType &rhs);
/**
* @brief Move Assignment.
*
* @param &rhs the PolyImpl to be copied.
* @return the resulting PolyImpl.
*/
const PolyType &operator=(PolyType &&rhs);
/**
* @brief Initalizer list
*
* @param &rhs the list to set the PolyImpl to.
* @return the resulting PolyImpl.
*/
const PolyType &operator=(std::initializer_list<uint64_t> rhs);
/**
* @brief Creates a Poly from a vector of signed integers (used for trapdoor
* sampling)
*
* @param &rhs the vector to set the PolyImpl to.
* @return the resulting PolyImpl.
*/
const PolyType &operator=(std::vector<int64_t> rhs);
/**
* @brief Creates a Poly from a vector of signed integers (used for trapdoor
* sampling)
*
* @param &rhs the vector to set the PolyImpl to.
* @return the resulting PolyImpl.
*/
const PolyType &operator=(std::vector<int32_t> rhs);
/**
* @brief Initalizer list
*
* @param &rhs the list to set the PolyImpl to.
* @return the resulting PolyImpl.
*/
const PolyType &operator=(std::initializer_list<std::string> rhs);
/**
* @brief Assignment Operator. The usint val will be set at index zero and all
* other indices will be set to zero.
*
* @param val is the usint to assign to index zero.
* @return the resulting vector.
*/
const PolyType &operator=(uint64_t val);
getter函数
// GETTERS
/**
* @brief Get method to get ILParams for the current vector.
*
* @return the ring element params.
*/
const shared_ptr<Params> GetParams() const { return m_params; }
/**
* @brief Get format of the element
*
* @return COEFFICIENT or Format::EVALUATION
*/
Format GetFormat() const;
/**
* @brief Get the length of the element.
*
* @return length
*/
usint GetLength() const;
/**
* @brief Get modulus of the element
*
* @return the modulus.
*/
const Integer &GetModulus() const { return m_params->GetModulus(); }
/**
* @brief Get the values for the element
*
* @return the vector.
*/
const VecType &GetValues() const;
/**
* @brief Get the cyclotomic order
*
* @return order
*/
usint GetCyclotomicOrder() const { return m_params->GetCyclotomicOrder(); }
/**
* @brief Get the ring dimension.
*
* @return the ring dimension
*/
usint GetRingDimension() const { return m_params->GetRingDimension(); }
/**
* @brief Get the root of unity.
*
* @return the root of unity.
*/
const Integer &GetRootOfUnity() const { return m_params->GetRootOfUnity(); }
/**
* @brief Get value of element at index i.
*
* @return value at index i.
*/
Integer &at(usint i);
const Integer &at(usint i) const;
/**
* @brief Get value of element at index i.
*
* @return value at index i.
*/
Integer &operator[](usint i);
const Integer &operator[](usint i) const;
setter函数
// SETTERS
/**
* @brief Set VecType value to val
*
* @param index is the index at which the value is to be set.
* @param val is the value to be set.
*/
// SCALAR OPERATIONS
/**
* @brief Set method of the values.
*
* @param values is the set of values of the vector.
* @param format is the format, either COEFFICIENT or EVALUATION.
*/
void SetValues(const VecType &values, Format format);
/**
* @brief Set method of the values.
*
* @param values is the set of values of the vector.
* @param format is the format, either COEFFICIENT or EVALUATION.
*/
void SetValues(VecType &&values, Format format);
/**
* @brief Sets all values of element to zero.
*/
void SetValuesToZero();
/**
* @brief Sets all values of element to maximum.
*/
void SetValuesToMax();
标量运算
/**
* @brief Scalar addition - add an element to the first index only.
* This operation is only allowed in COEFFICIENT format.
*
* @param &element is the element to add entry-wise.
* @return is the return of the addition operation.
*/
PolyImpl Plus(const Integer &element) const;
/**
* @brief Scalar subtraction - subtract an element to all entries.
*
* @param &element is the element to subtract entry-wise.
* @return is the return value of the minus operation.
*/
PolyImpl Minus(const Integer &element) const;
/**
* @brief Scalar multiplication - multiply all entries.
*
* @param &element is the element to multiply entry-wise.
* @return is the return value of the times operation.
*/
PolyImpl Times(const Integer &element) const;
#if NATIVEINT != 64
/**
* @brief Scalar multiplication - by a signed integer.
*
* @param &element is the element to multiply entry-wise.
* @return is the return value of the times operation.
*/
PolyImpl Times(int64_t element) const {
return Times((bigintnat::NativeInteger::SignedNativeInt)element);
}
#endif
/**
* @brief Scalar multiplication - by a signed integer.
*
* @param &element is the element to multiply entry-wise.
* @return is the return value of the times operation.
*/
PolyImpl Times(bigintnat::NativeInteger::SignedNativeInt element) const;
向量运算
// VECTOR OPERATIONS
/**
* @brief Unary minus on a lattice element.
* @return negation of the lattice element.
*/
PolyImpl operator-() const { // 求负运算
PolyImpl all0(this->GetParams(), this->GetFormat(), true);
return all0 - *this;
}
/**
* @brief Performs an addition operation and returns the result.
*
* @param &element is the element to add with.
* @return is the result of the addition.
*/
PolyImpl Plus(const PolyImpl &element) const;
/**
* @brief Performs a subtraction operation and returns the result.
*
* @param &element is the element to subtract with.
* @return is the result of the subtraction.
*/
PolyImpl Minus(const PolyImpl &element) const;
/**
* @brief Performs a multiplication operation and returns the result.
*
* @param &element is the element to multiply with.
* @return is the result of the multiplication.
*/
PolyImpl Times(const PolyImpl &element) const;
标量运算
/**
* @brief Performs += operation with a Integer and returns the result.
*
* @param &element is the element to add
* @return is the result of the addition.
*/
const PolyImpl &operator+=(const Integer &element) {
return *this = this->Plus(element);
}
/**
* @brief Performs -= operation with a Integer and returns the result.
*
* @param &element is the element to subtract
* @return is the result of the subtraction.
*/
const PolyImpl &operator-=(const Integer &element) {
m_values->ModSubEq(element);
return *this;
}
/**
* @brief Performs *= operation with a Integer and returns the result.
*
* @param &element is the element to multiply by
* @return is the result of the multiplication.
*/
const PolyImpl &operator*=(const Integer &element) {
m_values->ModMulEq(element);
return *this;
}
向量运算
/**
* @brief Performs an addition operation and returns the result.
*
* @param &element is the element to add
* @return is the result of the addition.
*/
const PolyImpl &operator+=(const PolyImpl &element);
/**
* @brief Performs an subtraction operation and returns the result.
*
* @param &element is the element to subtract
* @return is the result of the subtract.
*/
const PolyImpl &operator-=(const PolyImpl &element);
/**
* @brief Performs an multiplication operation and returns the result.
*
* @param &element is the element to multiply by
* @return is the result of the multiplication.
*/
const PolyImpl &operator*=(const PolyImpl &element);
相等运算符重载
/**
* @brief Equality operator compares this element to the input element.
*
* @param &rhs is the specified PolyImpl to be compared with this element.
* @return true if this PolyImpl represents the same values as the specified
* element, false otherwise
*/
inline bool operator==(const PolyImpl &rhs) const {
if (this->GetFormat() != rhs.GetFormat()) {
return false;
}
if (m_params->GetRootOfUnity() != rhs.GetRootOfUnity()) {
return false;
}
if (this->GetValues() != rhs.GetValues()) {
return false;
}
return true;
}
/**
* @brief Scalar multiplication followed by division and rounding operation -
* operation on all entries.
*
* @param &p is the integer muliplicand.
* @param &q is the integer divisor.
* @return is the return value of the multiply, divide and followed by
* rounding operation.
*/
PolyImpl MultiplyAndRound(const Integer &p, const Integer &q) const;
/**
* @brief Scalar division followed by rounding operation - operation on all
* entries.
*
* @param &q is the element to divide entry-wise.
* @return is the return value of the divide, followed by rounding operation.
*/
PolyImpl DivideAndRound(const Integer &q) const;
/**
* @brief Performs a negation operation and returns the result.
*
* @return is the result of the negation.
*/
PolyImpl Negate() const;
其他函数
// OTHER METHODS
/**
* @brief Adds one to every entry of the PolyImpl.
*/
void AddILElementOne();
/**
* @brief Performs an automorphism transform operation and returns the result.
*
* @param &i is the element to perform the automorphism transform with.
* @return is the result of the automorphism transform.
*/
PolyImpl AutomorphismTransform(const usint &k) const;
/**
* @brief Performs an automorphism transform operation using precomputed bit
* reversal indices.
*
* @param &i is the element to perform the automorphism transform with.
* @param &map a vector with precomputed indices
* @return is the result of the automorphism transform.
*/
PolyImpl AutomorphismTransform(usint i, const std::vector<usint> &map) const;
/**
* @brief Interpolates based on the Chinese Remainder Transform Interpolation.
* Does nothing for PolyImpl. Needed to support the linear CRT interpolation
* in DCRTPoly.
*
* @return the original ring element.
*/
PolyImpl CRTInterpolate() const { return *this; }
PolyNative DecryptionCRTInterpolate(PlaintextModulus ptm) const;
PolyNative ToNativePoly() const;
PolyNative ToNativePolyCloneParams() const;
/**
* @brief Transpose the ring element using the automorphism operation
*
* @return is the result of the transposition.
*/
PolyImpl Transpose() const;
/**
* @brief Performs a multiplicative inverse operation and returns the result.
*
* @return is the result of the multiplicative inverse.
*/
PolyImpl MultiplicativeInverse() const;
/**
* @brief Perform a modulus by 2 operation. Returns the least significant
* bit.
*
* @return is the return value of the modulus by 2, also the least significant
* bit.
*/
PolyImpl ModByTwo() const;
/**
* @brief Modulus - perform a modulus operation. Does proper mapping of
* [-modulus/2, modulus/2) to [0, modulus)
*
* @param modulus is the modulus to use.
* @return is the return value of the modulus.
*/
PolyImpl Mod(const Integer &modulus) const;
/**
* @brief Switch modulus and adjust the values
*
* @param &modulus is the modulus to be set.
* @param &rootOfUnity is the corresponding root of unity for the modulus
* @param &modulusArb is the modulus used for arbitrary cyclotomics CRT
* @param &rootOfUnityArb is the corresponding root of unity for the modulus
* ASSUMPTION: This method assumes that the caller provides the correct
* rootOfUnity for the modulus.
*/
void SwitchModulus(const Integer &modulus, const Integer &rootOfUnity,
const Integer &modulusArb = Integer(0),
const Integer &rootOfUnityArb = Integer(0));
/**
* @brief Convert from Coefficient to Format::EVALUATION or vice versa; calls
* FFT and inverse FFT.
*/
void SwitchFormat();
/**
* @brief Make the element values sparse. Sets every index not equal to zero
* mod the wFactor to zero.
*
* @param &wFactor ratio between the original ring dimension and the new ring
* dimension.
*/
void MakeSparse(const uint32_t &wFactor);
/**
* @brief Returns true if the vector is empty/ m_values==nullptr
*/
bool IsEmpty() const;
/**
* @brief Determines if inverse exists
*
* @return is the Boolean representation of the existence of multiplicative
* inverse.
*/
bool InverseExists() const;
/**
* @brief Returns the infinity norm, basically the largest value in the ring
* element.
*
* @return is the largest value in the ring element.
*/
double Norm() const;
/**
* @brief Rounds the polynomial to an input integer.
*
* @param x is integer to round to.
* @return is the result of the rounding operation.
*/
PolyImpl Round(const Integer &x) const;
/**
* @brief Write the element as \f$ \sum\limits{i=0}^{\lfloor {\log q/base}
* \rfloor} {(base^i u_i)} \f$ and return the vector of \f$ \left\{u_0,
* u_1,...,u_{\lfloor {\log q/base} \rfloor} \right\} \in R_{{base}^{\lceil
* {\log q/base} \rceil}} \f$; This is used as a subroutine in the
* relinearization procedure.
*
* @param baseBits is the number of bits in the base, i.e., \f$ base =
* 2^{baseBits} \f$.
* @return is the pointer where the base decomposition vector is stored
*/
std::vector<PolyImpl> BaseDecompose(usint baseBits,
bool evalModeAnswer = true) const;
/**
* @brief Generate a vector of PolyImpl's as \f$ \left\{x, {base}*x,
* {base}^2*x, ..., {base}^{\lfloor {\log q/{base}} \rfloor} \right\}*x \f$,
* where \f$ x \f$ is the current PolyImpl object;
* used as a subroutine in the relinearization procedure to get powers of a
* certain "base" for the secret key element
*
* @param baseBits is the number of bits in the base, i.e., \f$ base =
* 2^{baseBits} \f$.
* @return is the pointer where the base decomposition vector is stored
*/
std::vector<PolyImpl> PowersOfBase(usint baseBits) const;
/**
* @brief Shift entries in the vector left a specific number of entries.
*
* @param n the number of entries to shift left.
* @return is the resulting vector from shifting left.
*/
PolyImpl ShiftLeft(unsigned int n) const;
/**
* @brief Shift entries in the vector right a specific number of entries.
*
* @param n the number of entries to shift right.
* @return is the resulting vector from shifting right.
*/
PolyImpl ShiftRight(unsigned int n) const;
友元函数,运算符重载
/**
* @brief ostream operator
* @param os the input preceding output stream
* @param vec the element to add to the output stream.
* @return a resulting concatenated output stream
*/
friend inline std::ostream &operator<<(std::ostream &os,
const PolyImpl &vec) {
os << (vec.m_format == Format::EVALUATION ? "EVAL: " : "COEF: ")
<< vec.GetValues();
return os;
}
/**
* @brief Element-element addition operator.
* @param a first element to add.
* @param b second element to add.
* @return the result of the addition operation.
*/
friend inline PolyImpl operator+(const PolyImpl &a, const PolyImpl &b) {
return a.Plus(b);
}
/**
* @brief Element-integer addition operator.
* @param a first element to add.
* @param b integer to add.
* @return the result of the addition operation.
*/
friend inline PolyImpl operator+(const PolyImpl &a, const Integer &b) {
return a.Plus(b);
}
/**
* @brief Integer-element addition operator.
* @param a integer to add.
* @param b element to add.
* @return the result of the addition operation.
*/
friend inline PolyImpl operator+(const Integer &a, const PolyImpl &b) {
return b.Plus(a);
}
/**
* @brief Element-element subtraction operator.
* @param a element to subtract from.
* @param b element to subtract.
* @return the result of the subtraction operation.
*/
friend inline PolyImpl operator-(const PolyImpl &a, const PolyImpl &b) {
return a.Minus(b);
}
/**
* @brief Element-integer subtraction operator.
* @param a element to subtract from.
* @param b integer to subtract.
* @return the result of the subtraction operation.
*/
friend inline PolyImpl operator-(const PolyImpl &a, const Integer &b) {
return a.Minus(b);
}
/**
* @brief Element-element multiplication operator.
* @param a element to multiply.
* @param b element to multiply.
* @return the result of the multiplication operation.
*/
friend inline PolyImpl operator*(const PolyImpl &a, const PolyImpl &b) {
return a.Times(b);
}
/**
* @brief Element-integer multiplication operator.
* @param a element to multiply.
* @param b integer to multiply.
* @return the result of the multiplication operation.
*/
friend inline PolyImpl operator*(const PolyImpl &a, const Integer &b) {
return a.Times(b);
}
/**
* @brief Integer-element multiplication operator.
* @param a integer to multiply.
* @param b element to multiply.
* @return the result of the multiplication operation.
*/
friend inline PolyImpl operator*(const Integer &a, const PolyImpl &b) {
return b.Times(a);
}
/**
* @brief Element-signed-integer multiplication operator.
* @param a element to multiply.
* @param b integer to multiply.
* @return the result of the multiplication operation.
*/
friend inline PolyImpl operator*(const PolyImpl &a, int64_t b) {
return a.Times((bigintnat::NativeInteger::SignedNativeInt)b);
}
/**
* @brief signed-integer-element multiplication operator.
* @param a integer to multiply.
* @param b element to multiply.
* @return the result of the multiplication operation.
*/
friend inline PolyImpl operator*(int64_t a, const PolyImpl &b) {
return b.Times((bigintnat::NativeInteger::SignedNativeInt)a);
}
template <class Archive>
void save(Archive &ar, std::uint32_t const version) const {
ar(::cereal::make_nvp("v", m_values));
ar(::cereal::make_nvp("f", m_format));
ar(::cereal::make_nvp("p", m_params));
}
template <class Archive>
void load(Archive &ar, std::uint32_t const version) {
if (version > SerializedVersion()) {
PALISADE_THROW(deserialize_error,
"serialized object version " + std::to_string(version) +
" is from a later version of the library");
}
ar(::cereal::make_nvp("v", m_values));
ar(::cereal::make_nvp("f", m_format));
ar(::cereal::make_nvp("p", m_params));
}
std::string SerializedObjectName() const { return "Poly"; }
static uint32_t SerializedVersion() { return 1; }
类外函数
template <>
inline PolyImpl<NativeVector> PolyImpl<NativeVector>::DecryptionCRTInterpolate(
PlaintextModulus ptm) const {
return this->Mod(ptm);
}
// biginteger version
template <>
inline PolyImpl<NativeVector> PolyImpl<BigVector>::ToNativePolyCloneParams()
const {
PolyImpl<NativeVector> interp(
std::make_shared<ILParamsImpl<NativeInteger>>(
this->GetCyclotomicOrder(), this->GetModulus().ConvertToInt(),
this->GetRootOfUnity().ConvertToInt()),
this->GetFormat(), true);
for (usint i = 0; i < this->GetLength(); i++) {
interp[i] = (*this)[i].ConvertToInt();
}
return interp;
}
// native poly version
template <>
inline PolyImpl<NativeVector> PolyImpl<NativeVector>::ToNativePolyCloneParams()
const {
return *this;
}
\core\include\lattice\dcrtpoly.h
Represents integer lattice elements with double-CRT
class DCRTPolyImpl : public ILElement<DCRTPolyImpl<VecType>, VecType>
#include "math/backend.h"
#include "utils/inttypes.h"
#include "utils/exception.h"
#include "lattice/elemparams.h"
#include "lattice/ildcrtparams.h"
#include "lattice/ilelement.h"
#include "lattice/ilparams.h"
#include "lattice/poly.h"
#include "math/distrgen.h"
/**
* @brief Ideal lattice for the double-CRT representation.
* The implementation contains a vector of underlying native-integer lattices
* The double-CRT representation of polynomials is a common optimization for
* lattice encryption operations. Basically, it allows large-modulus polynomials
* to be represented as multiple smaller-modulus polynomials. The double-CRT
* representations are discussed theoretically here:
* - Gentry C., Halevi S., Smart N.P. (2012) Homomorphic Evaluation of the AES
* Circuit. In: Safavi-Naini R., Canetti R. (eds) Advances in Cryptology –
* CRYPTO 2012. Lecture Notes in Computer Science, vol 7417. Springer, Berlin,
* Heidelberg
*/
private成员
private:
shared_ptr<Params> m_params;
// array of vectors used for double-CRT presentation
std::vector<PolyType> m_vectors;
// Either Format::EVALUATION (0) or Format::COEFFICIENT (1)
Format m_format;
};
} // namespace lbcrypto
template <typename VecType>
class DCRTPolyImpl : public ILElement<DCRTPolyImpl<VecType>, VecType> {
public:
using Integer = typename VecType::Integer;
using Params = ILDCRTParams<Integer>;
typedef VecType Vector;
typedef DCRTPolyImpl<VecType> DCRTPolyType;
typedef DiscreteGaussianGeneratorImpl<NativeVector> DggType;
typedef DiscreteUniformGeneratorImpl<NativeVector> DugType;
typedef TernaryUniformGeneratorImpl<NativeVector> TugType;
typedef BinaryUniformGeneratorImpl<NativeVector> BugType;
// this class contains an array of these:
using PolyType = PolyImpl<NativeVector>;
// the composed polynomial type
typedef PolyImpl<VecType> PolyLargeType;
static const std::string GetElementName() { return "DCRTPolyImpl"; }
构造函数
// CONSTRUCTORS
/**
* @brief Constructor that initialized m_format to EVALUATION and calls
* m_params to nothing
*/
DCRTPolyImpl();
/**
* Constructor that initializes parameters.
*
*@param params parameter set required for DCRTPoly.
*@param format the input format fixed to EVALUATION. Format is a enum type
*that indicates if the polynomial is in Evaluation representation or
*Coefficient representation. It is defined in inttypes.h.
*@param initializeElementToZero
*/
DCRTPolyImpl(const shared_ptr<Params> params, Format format = EVALUATION,
bool initializeElementToZero = false);
const DCRTPolyType &operator=(const PolyLargeType &element);
const DCRTPolyType &operator=(const NativePoly &element);
根据四种分布的构造函数
/**
* @brief Constructor based on discrete Gaussian generator.
*
* @param &dgg the input discrete Gaussian generator. The dgg will be the seed
* to populate the towers of the DCRTPoly with random numbers.
* @param params parameter set required for DCRTPoly.
* @param format the input format fixed to EVALUATION. Format is a enum type // 固定是EVALUATION format
* that indicates if the polynomial is in Evaluation representation or
* Coefficient representation. It is defined in inttypes.h.
*/
DCRTPolyImpl(const DggType &dgg, const shared_ptr<Params> params,
Format format = EVALUATION);
/**
* @brief Constructor based on binary distribution generator. This is not
* implemented. Will throw an error.
*
* @param &bug the input binary uniform generator. The bug will be the seed to
* populate the towers of the DCRTPoly with random numbers.
* @param params parameter set required for DCRTPoly.
* @param format the input format fixed to EVALUATION. Format is a enum type
* that indicates if the polynomial is in Evaluation representation or
* Coefficient representation. It is defined in inttypes.h.
*/
DCRTPolyImpl(const BugType &bug, const shared_ptr<Params> params,
Format format = EVALUATION);
/**
* @brief Constructor based on ternary distribution generator.
*
* @param &tug the input ternary uniform generator. The bug will be the seed
* to populate the towers of the DCRTPoly with random numbers.
* @param params parameter set required for DCRTPoly.
* @param format the input format fixed to EVALUATION. Format is a enum type
* that indicates if the polynomial is in Evaluation representation or
* Coefficient representation. It is defined in inttypes.h.
* @param h - Hamming weight for sparse ternary distribution (by default, when
* h = 0, the distribution is NOT sparse)
*/
DCRTPolyImpl(const TugType &tug, const shared_ptr<Params> params,
Format format = EVALUATION, uint32_t h = 0);
/**
* @brief Constructor based on discrete uniform generator.
*
* @param &dug the input discrete Uniform Generator.
* @param params the input params.
* @param &format the input format fixed to EVALUATION. Format is a enum type
* that indicates if the polynomial is in Evaluation representation or
* Coefficient representation. It is defined in inttypes.h.
*/
DCRTPolyImpl(DugType &dug, const shared_ptr<Params> params,
Format format = EVALUATION);
/**
* @brief Construct using a single Poly. The Poly is copied into every tower.
* Each tower will be reduced to it's corresponding modulus via GetModuli(at
* tower index). The format is derived from the passed in Poly.
*
* @param &element Poly to build other towers from.
* @param params parameter set required for DCRTPoly.
*/
DCRTPolyImpl(const PolyLargeType &element, const shared_ptr<Params> params);
/**
* @brief Construct using a single NativePoly. The NativePoly is copied into
* every tower. Each tower will be reduced to it's corresponding modulus via
* GetModuli(at tower index). The format is derived from the passed in
* NativePoly.
*
* @param &element Poly to build other towers from.
* @param params parameter set required for DCRTPoly.
*/
DCRTPolyImpl(const NativePoly &element, const shared_ptr<Params> params);
/**
* @brief Construct using an tower of ILVectro2ns. The params and format for
* the DCRTPoly will be derived from the towers.
*
* @param &towers vector of Polys which correspond to each tower of DCRTPoly.
*/
explicit DCRTPolyImpl(const std::vector<PolyType> &elements);
/**
* @brief Create lambda that allocates a zeroed element for the case when it
* is called from a templated class
* @param params the params to use.
* @param format - EVALUATION or COEFFICIENT
*/
inline static function<DCRTPolyType()> Allocator(
const shared_ptr<Params> params, Format format) {
return [=]() { return DCRTPolyType(params, format, true); };
}
/**
* @brief Allocator for discrete uniform distribution.
*
* @param params Params instance that is is passed.
* @param resultFormat resultFormat for the polynomials generated.
* @param stddev standard deviation for the discrete gaussian generator.
* @return the resulting vector.
*/
inline static function<DCRTPolyType()>
MakeDiscreteGaussianCoefficientAllocator(shared_ptr<Params> params,
Format resultFormat, double stddev) {
return [=]() {
DggType dgg(stddev);
DCRTPolyType ilvec(dgg, params, COEFFICIENT);
ilvec.SetFormat(resultFormat);
return ilvec;
};
}
/**
* @brief Allocator for discrete uniform distribution.
*
* @param params Params instance that is is passed.
* @param format format for the polynomials generated.
* @return the resulting vector.
*/
inline static function<DCRTPolyType()> MakeDiscreteUniformAllocator(
shared_ptr<Params> params, Format format) {
return [=]() {
DugType dug;
return DCRTPolyType(dug, params, format);
};
}
/**
* @brief Copy constructor.
*
* @param &element DCRTPoly to copy from
*/
DCRTPolyImpl(const DCRTPolyType &element);
/**
* @brief Move constructor.
*
* @param &&element DCRTPoly to move from
*/
explicit DCRTPolyImpl(const DCRTPolyType &&element);
// CLONE OPERATIONS
/**
* @brief Clone the object by making a copy of it and returning the copy
* @return new Element
*/
DCRTPolyType Clone() const { return DCRTPolyImpl(*this); }
/**
* @brief Makes a copy of the DCRTPoly, but it includes only a sequential
* subset of the towers that the original holds.
*
* @param startTower The index number of the first tower to clone
* @param endTower The index number of the last tower to clone
* @return new Element
*/
DCRTPolyType CloneTowers(uint32_t startTower, uint32_t endTower) const {
vector<NativeInteger> moduli(endTower - startTower + 1);
vector<NativeInteger> roots(endTower - startTower + 1);
for (uint32_t i = startTower; i <= endTower; i++) {
moduli[i - startTower] = this->GetParams()->GetParams()[i]->GetModulus();
roots[i - startTower] =
this->GetParams()->GetParams()[i]->GetRootOfUnity();
}
auto params = DCRTPolyImpl::Params(this->GetCyclotomicOrder(), moduli,
roots, {}, {}, 0);
auto res =
DCRTPolyImpl(std::make_shared<typename DCRTPolyImpl::Params>(params),
EVALUATION, false);
for (uint32_t i = startTower; i <= endTower; i++) {
res.SetElementAtIndex(i - startTower, this->GetElementAtIndex(i));
}
return res;
}
/**
* @brief Clone the object, but have it contain nothing
* @return new Element
*/
DCRTPolyType CloneEmpty() const { return DCRTPolyImpl(); }
/**
* @brief Clone method creates a new DCRTPoly and clones only the params. The
* tower values are empty. The tower values can be filled by another
* process/function or initializer list.
*/
DCRTPolyType CloneParametersOnly() const;
/**
* @brief Clone with noise. This method creates a new DCRTPoly and clones the
* params. The tower values will be filled up with noise based on the discrete
* gaussian.
*
* @param &dgg the input discrete Gaussian generator. The dgg will be the seed
* to populate the towers of the DCRTPoly with random numbers.
* @param format the input format fixed to EVALUATION. Format is a enum type
* that indicates if the polynomial is in Evaluation representation or
* Coefficient representation. It is defined in inttypes.h.
*/
DCRTPolyType CloneWithNoise(const DiscreteGaussianGeneratorImpl<VecType> &dgg,
Format format = EVALUATION) const;
/**
* @brief Destructor.
*/
~DCRTPolyImpl();
getter函数
// GETTERS
/**
* @brief returns the parameters of the element.
* @return the element parameter set.
*/
const shared_ptr<Params> GetParams() const { return m_params; }
/**
* @brief returns the element's cyclotomic order
* @return returns the cyclotomic order of the element.
*/
usint GetCyclotomicOrder() const { return m_params->GetCyclotomicOrder(); }
/**
* @brief returns the element's ring dimension
* @return returns the ring dimension of the element.
*/
usint GetRingDimension() const { return m_params->GetRingDimension(); }
/**
* @brief returns the element's modulus
* @return returns the modulus of the element.
*/
const Integer &GetModulus() const { return m_params->GetModulus(); }
/**
* @brief returns the element's original modulus, derived from Poly
* @return returns the modulus of the element.
*/
const Integer &GetOriginalModulus() const {
return m_params->GetOriginalModulus();
}
/**
* @brief returns the element's root of unity.
* @return the element's root of unity.
*/
const Integer &GetRootOfUnity() const {
static Integer t(0);
return t;
}
/**
* @brief Get method for length of each component element.
* NOTE assumes all components are the same size.
*
* @return length of the component element
*/
usint GetLength() const {
if (m_vectors.size() == 0) return 0;
return m_vectors[0].GetValues().GetLength();
}
/**
* @brief Get interpolated value of elements at all tower index i.
* Note this operation is computationally intense. // 注意,这个操作需要大量的计算。
* @return interpolated value at index i.
*/
Integer &at(usint i);
const Integer &at(usint i) const;
/**
* @brief Get interpolated value of element at index i.
* Note this operation is computationally intense.
* @return interpolated value at index i.
*/
Integer &operator[](usint i);
const Integer &operator[](usint i) const;
/**
* @brief Get method of individual tower of elements.
* Note this behavior is different than poly
* @param i index of tower to be returned.
* @returns a reference to the returned tower
*/
const PolyType &GetElementAtIndex(usint i) const;
/**
* @brief Get method of the number of component elements, also known as the
* number of towers.
*
* @return the number of component elements.
*/
usint GetNumOfElements() const;
/**
* @brief Get method that returns a vector of all component elements.
*
* @returns a vector of the component elements.
*/
const std::vector<PolyType> &GetAllElements() const;
/**
* @brief Get method of the format.
*
* @return the format, either COEFFICIENT or EVALUATION
*/
Format GetFormat() const;
/**
* @brief Write the element as \f$ \sum\limits{i=0}^{\lfloor {\log q/base}
* \rfloor} {(base^i u_i)} \f$ and return the vector of \f$ \left\{u_0,
* u_1,...,u_{\lfloor {\log q/base} \rfloor} \right\} \in R_{{base}^{\lceil
* {\log q/base} \rceil}} \f$; This is used as a subroutine in the
* relinearization procedure.
*
* @param baseBits is the number of bits in the base, i.e., \f$ base =
* 2^{baseBits} \f$.
* @return is the pointer where the base decomposition vector is stored
*/
std::vector<DCRTPolyType> BaseDecompose(usint baseBits,
bool evalModeAnswer = true) const;
/**
* @brief Generate a vector of PolyImpl's as \f$ \left\{x, {base}*x,
* {base}^2*x, ..., {base}^{\lfloor {\log q/{base}} \rfloor} \right\}*x \f$,
* where \f$ x \f$ is the current PolyImpl object;
* used as a subroutine in the relinearization procedure to get powers of a
* certain "base" for the secret key element.
*
* @param baseBits is the number of bits in the base, i.e., \f$ base =
* 2^{baseBits} \f$.
* @return is the pointer where the base decomposition vector is stored
*/
std::vector<DCRTPolyType> PowersOfBase(usint baseBits) const;
/**
* CRT basis decomposition of c as [c qi/q]_qi
*
* @param &baseBits bits in the base for additional digit decomposition if
* base > 0
* @return is the pointer where the resulting vector is stored
*/
std::vector<DCRTPolyType> CRTDecompose(uint32_t baseBits = 0) const;
向量运算
// VECTOR OPERATIONS
/**
* @brief Assignment Operator.
*
* @param &rhs the copied element.
* @return the resulting element.
*/
const DCRTPolyType &operator=(const DCRTPolyType &rhs);
/**
* @brief Move Assignment Operator.
*
* @param &rhs the copied element.
* @return the resulting element.
*/
const DCRTPolyType &operator=(DCRTPolyType &&rhs);
/**
* @brief Initalizer list
*
* @param &rhs the list to initalized the element.
* @return the resulting element.
*/
DCRTPolyType &operator=(std::initializer_list<uint64_t> rhs);
/**
* @brief Assignment Operator. The usint val will be set at index zero and all
* other indices will be set to zero.
*
* @param val is the usint to assign to index zero.
* @return the resulting vector.
*/
DCRTPolyType &operator=(uint64_t val);
/**
* @brief Creates a Poly from a vector of signed integers (used for trapdoor
* sampling)
*
* @param &rhs the vector to set the PolyImpl to.
* @return the resulting PolyImpl.
*/
DCRTPolyType &operator=(const std::vector<int64_t> &rhs);
/**
* @brief Creates a Poly from a vector of signed integers (used for trapdoor
* sampling)
*
* @param &rhs the vector to set the PolyImpl to.
* @return the resulting PolyImpl.
*/
DCRTPolyType &operator=(const std::vector<int32_t> &rhs);
/**
* @brief Initalizer list
*
* @param &rhs the list to set the PolyImpl to.
* @return the resulting PolyImpl.
*/
DCRTPolyType &operator=(std::initializer_list<std::string> rhs);
/**
* @brief Unary minus on a element.
* @return additive inverse of the an element.
*/
DCRTPolyType operator-() const {
DCRTPolyType all0(this->GetParams(), this->GetFormat(), true);
return all0 - *this;
}
/**
* @brief Equality operator.
*
* @param &rhs is the specified element to be compared with this element.
* @return true if this element represents the same values as the specified
* element, false otherwise
*/
bool operator==(const DCRTPolyType &rhs) const;
/**
* @brief Performs an entry-wise addition over all elements of each tower with
* the towers of the element on the right hand side.
*
* @param &rhs is the element to add with.
* @return is the result of the addition.
*/
const DCRTPolyType &operator+=(const DCRTPolyType &rhs);
/**
* @brief Performs an entry-wise subtraction over all elements of each tower
* with the towers of the element on the right hand side.
*
* @param &rhs is the element to subtract from.
* @return is the result of the addition.
*/
const DCRTPolyType &operator-=(const DCRTPolyType &rhs);
/**
* @brief Permutes coefficients in a polynomial. Moves the ith index to the
* first one, it only supports odd indices.
*
* @param &i is the element to perform the automorphism transform with.
* @return is the result of the automorphism transform.
*/
DCRTPolyType AutomorphismTransform(const usint &i) const {
DCRTPolyType result(*this);
for (usint k = 0; k < m_vectors.size(); k++) {
result.m_vectors[k] = m_vectors[k].AutomorphismTransform(i);
}
return result;
}
/**
* @brief Performs an automorphism transform operation using precomputed bit
* reversal indices.
*
* @param &i is the element to perform the automorphism transform with.
* @param &map a vector with precomputed indices
* @return is the result of the automorphism transform.
*/
DCRTPolyType AutomorphismTransform(usint i,
const std::vector<usint> &map) const {
DCRTPolyType result(*this);
for (usint k = 0; k < m_vectors.size(); k++) {
result.m_vectors[k] = m_vectors[k].AutomorphismTransform(i, map);
}
return result;
}
/**
* @brief Transpose the ring element using the automorphism operation
*
* @return is the result of the transposition.
*/
DCRTPolyType Transpose() const {
if (m_format == COEFFICIENT) {
PALISADE_THROW(not_implemented_error,
"DCRTPolyImpl element transposition is currently "
"implemented only in the Evaluation representation.");
} else {
usint m = m_params->GetCyclotomicOrder();
return AutomorphismTransform(m - 1);
}
}
/**
* @brief Performs an addition operation and returns the result.
*
* @param &element is the element to add with.
* @return is the result of the addition.
*/
DCRTPolyType Plus(const DCRTPolyType &element) const;
/**
* @brief Performs a multiplication operation and returns the result.
*
* @param &element is the element to multiply with.
* @return is the result of the multiplication.
*/
DCRTPolyType Times(const DCRTPolyType &element) const;
/**
* @brief Performs a subtraction operation and returns the result.
*
* @param &element is the element to subtract from.
* @return is the result of the subtraction.
*/
DCRTPolyType Minus(const DCRTPolyType &element) const;
标量运算
// SCALAR OPERATIONS
/**
* @brief Scalar addition - add an element to the first index of each tower.
*
* @param &element is the element to add entry-wise.
* @return is the result of the addition operation.
*/
DCRTPolyType Plus(const Integer &element) const;
/**
* @brief Scalar addition for elements in CRT format.
* CRT elements are represented as vector of integer elements which
* correspond to the represented number modulo the primes in the
* tower chain (in same order).
*
* @param &element is the element to add entry-wise.
* @return is the result of the addition operation.
*/
DCRTPolyType Plus(const vector<Integer> &element) const;
/**
* @brief Scalar subtraction - subtract an element to all entries.
*
* @param &element is the element to subtract entry-wise.
* @return is the return value of the minus operation.
*/
DCRTPolyType Minus(const Integer &element) const;
/**
* @brief Scalar subtraction for elements in CRT format.
* CRT elements are represented as vector of integer elements which
* correspond to the represented number modulo the primes in the
* tower chain (in same order).
*
* @param &element is the element to subtract entry-wise.
* @return is the result of the subtraction operation.
*/
DCRTPolyType Minus(const vector<Integer> &element) const;
/**
* @brief Scalar multiplication - multiply all entries.
*
* @param &element is the element to multiply entry-wise.
* @return is the return value of the times operation.
*/
DCRTPolyType Times(const Integer &element) const;
/**
* @brief Scalar multiplication - multiply by a signed integer
*
* @param &element is the element to multiply entry-wise.
* @return is the return value of the times operation.
*/
DCRTPolyType Times(bigintnat::NativeInteger::SignedNativeInt element) const;
#if NATIVEINT != 64
/**
* @brief Scalar multiplication - multiply by a signed integer
*
* @param &element is the element to multiply entry-wise.
* @return is the return value of the times operation.
*/
DCRTPolyType Times(int64_t element) const {
return Times((bigintnat::NativeInteger::SignedNativeInt)element);
}
#endif
/**
* @brief Scalar multiplication by an integer represented in CRT Basis.
*
* @param &element is the element to multiply entry-wise.
* @return is the return value of the times operation.
*/
DCRTPolyType Times(const std::vector<NativeInteger> &element) const;
/**
* @brief Scalar modular multiplication by an integer represented in CRT
* Basis.
*
* @param &element is the element to multiply entry-wise.
* @return is the return value of the times operation.
*/
DCRTPolyType Times(const std::vector<Integer> &element) const;
/**
* @brief Scalar multiplication followed by division and rounding operation -
* operation on all entries.
*
* @param &p is the element to multiply entry-wise.
* @param &q is the element to divide entry-wise.
* @return is the return value of the multiply, divide and followed by
* rounding operation.
*/
DCRTPolyType MultiplyAndRound(const Integer &p, const Integer &q) const;
/**
* @brief Scalar division followed by rounding operation - operation on all
* entries.
*
* @param &q is the element to divide entry-wise.
* @return is the return value of the divide, followed by rounding operation.
*/
DCRTPolyType DivideAndRound(const Integer &q) const;
/**
* @brief Performs a negation operation and returns the result.
*
* @return is the result of the negation.
*/
DCRTPolyType Negate() const;
const DCRTPolyType &operator+=(const Integer &element) {
for (usint i = 0; i < this->GetNumOfElements(); i++) {
this->m_vectors[i] +=
(element.Mod(this->m_vectors[i].GetModulus())).ConvertToInt();
}
return *this;
}
/**
* @brief Performs a subtraction operation and returns the result.
*
* @param &element is the element to subtract from.
* @return is the result of the subtraction.
*/
const DCRTPolyType &operator-=(const Integer &element) {
for (usint i = 0; i < this->GetNumOfElements(); i++) {
this->m_vectors[i] -=
(element.Mod(this->m_vectors[i].GetModulus())).ConvertToInt();
}
return *this;
}
/**
* @brief Performs a multiplication operation and returns the result.
*
* @param &element is the element to multiply by.
* @return is the result of the multiplication.
*/
const DCRTPolyType &operator*=(const Integer &element);
/**
* @brief Performs an multiplication operation and returns the result.
*
* @param &element is the element to multiply with.
* @return is the result of the multiplication.
*/
const DCRTPolyType &operator*=(const DCRTPolyType &element);
/**
* @brief Get value of element at index i.
*
* @return value at index i.
*/
PolyType &ElementAtIndex(usint i);
// multiplicative inverse operation
/**
* @brief Performs a multiplicative inverse operation and returns the result.
*
* @return is the result of the multiplicative inverse.
*/
DCRTPolyType MultiplicativeInverse() const;
/**
* @brief Perform a modulus by 2 operation. Returns the least significant
* bit.
*
* @return is the resulting value.
*/
DCRTPolyType ModByTwo() const;
/**
* @brief Modulus - perform a modulus operation. Does proper mapping of
* [-modulus/2, modulus/2) to [0, modulus)
*
* @param modulus is the modulus to use.
* @return is the return value of the modulus.
*/
DCRTPolyType Mod(const Integer &modulus) const {
PALISADE_THROW(not_implemented_error,
"Mod of an Integer not implemented on DCRTPoly");
}
// OTHER FUNCTIONS AND UTILITIES
/**
* @brief Get method that should not be used
*
* @return will throw an error.
*/
const VecType &GetValues() const {
PALISADE_THROW(not_implemented_error,
"GetValues not implemented on DCRTPoly");
}
/**
* @brief Set method that should not be used, will throw an error.
*
* @param &values
* @param format
*/
void SetValues(const VecType &values, Format format) {
PALISADE_THROW(not_implemented_error,
"SetValues not implemented on DCRTPoly");
}
/**
* @brief Sets element at index
*
* @param index where the element should be set
* @param element The element to store
*/
void SetElementAtIndex(usint index, const PolyType &element) {
m_vectors[index] = element;
}
/**
* @brief Sets element at index
*
* @param index where the element should be set
* @param element The element to store
*/
void SetElementAtIndex(usint index, PolyType &&element) {
m_vectors[index] = std::move(element);
}
/**
* @brief Sets all values of element to zero.
*/
void SetValuesToZero();
/**
* @brief Adds "1" to every entry in every tower.
*/
void AddILElementOne();
/**
* @brief Add uniformly random values to all components except for the first
* one
*/
DCRTPolyType AddRandomNoise(const Integer &modulus) const {
PALISADE_THROW(not_implemented_error,
"AddRandomNoise is not currently implemented for DCRTPoly");
}
/**
* @brief Make DCRTPoly Sparse. Sets every index of each tower not equal to
* zero mod the wFactor to zero.
*
* @param &wFactor ratio between the sparse and none-sparse values.
*/
void MakeSparse(const uint32_t &wFactor);
/**
* @brief Returns true if ALL the tower(s) are empty.
* @return true if all towers are empty
*/
bool IsEmpty() const;
/**
* @brief Drops the last element in the double-CRT representation. The
* resulting DCRTPoly element will have one less tower.
*/
void DropLastElement();
/**
* @brief Drops the last i elements in the double-CRT representation.
*/
void DropLastElements(size_t i);
/**
* @brief Drops the last element in the double-CRT representation and scales
* down by the last CRT modulus. The resulting DCRTPoly element will have one
* less tower.
* @param &QlQlInvModqlDivqlModq precomputed values for
* [Q^(l)*[Q^(l)^{-1}]_{q_l}/q_l]_{q_i}
* @param &QlQlInvModqlDivqlModqPrecon NTL-specific precomputations
* @param &qlInvModq precomputed values for [q_l^{-1}]_{q_i}
* @param &qlInvModqPrecon NTL-specific precomputations
*/
void DropLastElementAndScale(
const std::vector<NativeInteger> &QlQlInvModqlDivqlModq,
const std::vector<NativeInteger> &QlQlInvModqlDivqlModqPrecon,
const std::vector<NativeInteger> &qlInvModq,
const std::vector<NativeInteger> &qlInvModqPrecon);
/**
* @brief ModReduces reduces the DCRTPoly element's composite modulus by
* dropping the last modulus from the chain of moduli as well as dropping the
* last tower.
*
* @param &t is the plaintextModulus used for the DCRTPoly
* @param &tModqPrecon NTL-specific precomputations for [t]_{q_i}
* @param &negtInvModq precomputed values for [-t^{-1}]_{q_i}
* @param &negtInvModqPrecon NTL-specific precomputations for [-t^{-1}]_{q_i}
* @param &qlInvModq precomputed values for [q_{l}^{-1}]_{q_i}
* @param &qlInvModqPrecon NTL-specific precomputations for [q_{l}^{-1}]_{q_i}
*/
void ModReduce(const NativeInteger &t,
const std::vector<NativeInteger> &tModqPrecon,
const NativeInteger &negtInvModq,
const NativeInteger &negtInvModqPrecon,
const std::vector<NativeInteger> &qlInvModq,
const std::vector<NativeInteger> &qlInvModqPrecon);
/**
* @brief Interpolates the DCRTPoly to an Poly based on the Chinese Remainder
* Transform Interpolation. and then returns a Poly with that single element
*
* @return the interpolated ring element as a Poly object.
*/
PolyLargeType CRTInterpolate() const;
PolyType DecryptionCRTInterpolate(PlaintextModulus ptm) const;
NativePoly ToNativePoly() const;
/**
* @brief Interpolates the DCRTPoly to an Poly based on the Chinese Remainder
* Transform Interpolation, only at element index i, all other elements are
* zero. and then returns a Poly with that single element
*
* @return the interpolated ring element as a Poly object.
*/
PolyLargeType CRTInterpolateIndex(usint i) const;
/**
* @brief Computes and returns the product of primes in the current moduli
* chain. Compared to GetModulus, which always returns the product of all
* primes in the crypto parameters, this method will return a different
* modulus, based on the towers/moduli that are currently in the chain (some
* towers are dropped along the way).
*
* @return the product of moduli in the current towers.
*/
BigInteger GetWorkingModulus() const;
/**
* @brief Returns the element parameters for DCRTPoly elements in an extended
* CRT basis, which is the concatenation of the towers currently in "this"
* DCRTPoly, and the moduli in ParamsP.
*
* @return element parameters of the extended basis.
*/
shared_ptr<Params> GetExtendedCRTBasis(std::shared_ptr<Params> paramsP) const;
论文中RNS操作
/**
* @brief Performs approximate CRT basis switching:
* {X}_{Q} -> {X'}_{P}
* X' = X + alpha*Q for small alpha
* {Q} = {q_1,...,q_l}
* {P} = {p_1,...,p_k}
*
* Brief algorithm:
* [X']_{p_j} = [\sum_i([x_i*(Q/q_i)^{-1}]_{q_i}*(Q/q_i)]_{p_j}
*
* Source: "A full RNS variant of approximate homomorphic encryption" by
* Cheon, et. al.
*
* @param ¶msQ parameters for the CRT basis {q_1,...,q_l}
* @param ¶msP parameters for the CRT basis {p_1,...,p_k}
* @param &QHatinvModq precomputed values for [(Q/q_i)^{-1}]_{q_i}
* @param &QHatinvModqPrecon NTL-specific precomputations
* @param &QHatModp precomputed values for [Q/q_i]_{p_j}
* @param &modpBarrettMu 128-bit Barrett reduction precomputed values
* @return the representation of {X + alpha*Q} in basis {P}.
*/
DCRTPolyType ApproxSwitchCRTBasis(
const std::shared_ptr<Params> paramsQ,
const std::shared_ptr<Params> paramsP,
const std::vector<NativeInteger> &QHatInvModq,
const std::vector<NativeInteger> &QHatInvModqPrecon,
const std::vector<std::vector<NativeInteger>> &QHatModp,
const std::vector<DoubleNativeInt> &modpBarrettMu) const;
/**
* @brief Performs approximate modulus raising:
* {X}_{Q} -> {X'}_{Q,P}.
* X' = X + alpha*Q for small alpha
* {Q} = {q_1,...,q_l}
* {P} = {p_1,...,p_k}
*
* Brief algorithm:
* {X}_{Q} -> {X'}_Q : trivial
* {X}_{Q} -> {X'}_P : use DCRTPoly::ApproxSwitchCRTBasis
*
* Source: "A full RNS variant of approximate homomorphic encryption" by
* Cheon, et. al.
*
* @param ¶msQ parameters for the CRT basis {q_1,...,q_l}
* @param ¶msP parameters for the CRT basis {p_1,...,p_k}
* @param &QHatInvModq precomputed values for [(Q/q_i)^{-1}]_{q_i}
* @param &QHatInvModqPrecon NTL-specific precomputations
* @param &QHatModp precomputed values for [Q/q_i]_{p_j}
* @param &modpBarrettMu 128-bit Barrett reduction precomputed values for
* p_j
* @return the representation of {X + alpha*Q} in basis {Q,P}.
*/
void ApproxModUp(const shared_ptr<Params> paramsQ,
const shared_ptr<Params> paramsP,
const shared_ptr<Params> paramsQP,
const vector<NativeInteger> &QHatInvModq,
const vector<NativeInteger> &QHatInvModqPrecon,
const vector<vector<NativeInteger>> &QHatModp,
const vector<DoubleNativeInt> &modpBarrettMu);
/**
* @brief Performs approximate modulus reduction:
* {X}_{Q,P} -> {\approx(X/P)}_{Q}.
* {Q} = {q_1,...,q_l}
* {P} = {p_1,...,p_k}
*
* Brief algorithm:
* 1) use DCRTPoly::ApproxSwitchCRTBasis : {X}_{P} -> {X'}_{Q}
* 2) compute : {(X-X') * P^{-1}}_{Q}
*
* Source: "A full RNS variant of approximate homomorphic encryption" by
* Cheon, et. al.
*
* @param ¶msQ parameters for the CRT basis {q_1,...,q_l}
* @param ¶msP parameters for the CRT basis {p_1,...,p_k}
* @param &PInvModq precomputed values for (P^{-1} mod q_j)
* @param &PInvModqPrecon NTL-specific precomputations
* @param &PHatInvModp precomputed values for [(P/p_j)^{-1}]_{p_j}
* @param &PHatInvModpPrecon NTL-specific precomputations
* @param &PHatModq precomputed values for [P/p_j]_{q_i}
* @param &modqBarrettMu 128-bit Barrett reduction precomputed values for
* q_i
* @param &tInvModp precomputed values for [t^{-1}]_{p_j}
* used in BGVrns
* @param t often corresponds to the plaintext modulus
* used in BGVrns
* @return the representation of {\approx(X/P)}_{Q}
*/
DCRTPolyType ApproxModDown(
const shared_ptr<Params> paramsQ, const shared_ptr<Params> paramsP,
const vector<NativeInteger> &PInvModq,
const vector<NativeInteger> &PInvModqPrecon,
const vector<NativeInteger> &PHatInvModp,
const vector<NativeInteger> &PHatInvModpPrecon,
const vector<vector<NativeInteger>> &PHatModq,
const vector<DoubleNativeInt> &modqBarrettMu,
const vector<NativeInteger> &tInvModp = vector<NativeInteger>(),
const vector<NativeInteger> &tInvModpPrecon = vector<NativeInteger>(),
const NativeInteger &t = 0,
const vector<NativeInteger> &tModqPrecon = vector<NativeInteger>()) const;
/**
* @brief Performs CRT basis switching:
* {X}_{Q} -> {X}_{P}
* {Q} = {q_1,...,q_l}
* {P} = {p_1,...,p_k}
*
* Brief algorithm:
* 1) X=\sum_i[x_i*(Q/q_i)^{-1}]_{q_i}*(Q/q_i)-alpha*Q
* 2) compute round[[x_i*(Q/q_i)^{-1}]_{q_i} / q_i] to find alpha
* 3) [X]_{p_j}=[\sum_i[x_i*(Q/q_i)^{-1}]_{q_i}*(Q/q_i)]_{p_j}-[alpha*Q]_{p_j}
*
* Source: Halevi S., Polyakov Y., and Shoup V. An Improved RNS Variant of the
* BFV Homomorphic Encryption Scheme. Cryptology ePrint Archive, Report
* 2018/117. (https://eprint.iacr.org/2018/117)
*
* @param ¶msP parameters for the CRT basis {p_1,...,p_k}
* @param &QHatInvModq precomputed values for [(Q/q_i)^{-1}]_{q_i}
* @param &QHatInvModqPrecon NTL-specific precomputations
* @param &QHatModp precomputed values for [Q/q_i]_{p_j}
* @param &alphaQModp precomputed values for [alpha*Q]_{p_j}
* @param &modpBarrettMu 128-bit Barrett reduction precomputed values for
* p_j
* @params &qInv precomputed values for 1/q_i
* @return the representation of {X}_{P}
*/
DCRTPolyType SwitchCRTBasis(
const shared_ptr<Params> paramsP,
const std::vector<NativeInteger> &QHatInvModq,
const std::vector<NativeInteger> &QHatInvModqPrecon,
const std::vector<std::vector<NativeInteger>> &QHatModp,
const std::vector<std::vector<NativeInteger>> &alphaQModp,
const std::vector<DoubleNativeInt> &modpBarrettMu,
const std::vector<double> &qInv) const;
/**
* @brief Performs modulus raising:
* {X}_{Q} -> {X}_{Q,P}
* {Q} = {q_1,...,q_l}
* {P} = {p_1,...,p_k}
*
* Brief algorithm:
* {X}_{Q} -> {X}_P : use DCRTPoly::SwitchCRTBasis
* combine {X}_{Q} and {X}_{P}
* Outputs the resulting polynomial in CRT/RNS
*
* Source: Halevi S., Polyakov Y., and Shoup V. An Improved RNS Variant of the
* BFV Homomorphic Encryption Scheme. Cryptology ePrint Archive, Report
* 2018/117. (https://eprint.iacr.org/2018/117)
*
* @param ¶msQP parameters for the CRT basis {q_1,...,q_l,p_1,...,p_k}
* @param ¶msP parameters for the CRT basis {p_1,...,p_k}
* @param &QHatInvModq precomputed values for [QInv_i]_{q_i}
* @param &QHatInvModqPrecon NTL-specific precomputations
* @param &QHatModp precomputed values for [QHat_i]_{p_j}
* @param &alphaQModp precomputed values for [alpha*Q]_{p_j}
* @param &modpBarrettMu 128-bit Barrett reduction precomputed values for
* p_j
* @params &qInv precomputed values for 1/q_i
* @param resultFormat Specifies the format we want the result to be in
*
*/
void ExpandCRTBasis(const shared_ptr<Params> paramsQP,
const shared_ptr<Params> paramsP,
const std::vector<NativeInteger> &QHatInvModq,
const std::vector<NativeInteger> &QHatInvModqPrecon,
const std::vector<std::vector<NativeInteger>> &QHatModp,
const std::vector<std::vector<NativeInteger>> &alphaQModp,
const std::vector<DoubleNativeInt> &modpBarrettMu,
const std::vector<double> &qInv,
Format resultFormat = EVALUATION);
/**
* @brief Performs scale and round:
* {X}_{Q} -> {\round(t/Q*X)}_t
* {Q} = {q_1,...,q_l}
* {P} = {p_1,...,p_k}
*
* Brief algorithm:
* [\sum_i x_i*[t*QHatInv_i/q_i]_t + Round(\sum_i x_i*{t*QHatInv_i/q_i})]_t
*
* Source: Halevi S., Polyakov Y., and Shoup V. An Improved RNS Variant of the
* BFV Homomorphic Encryption Scheme. Cryptology ePrint Archive, Report
* 2018/117. (https://eprint.iacr.org/2018/117)
*
* @param &t often corresponds to the plaintext modulus
* @param &tQHatInvModqDivqModt precomputed values for
* [Floor{t*QHatInv_i/q_i}]_t
* @param &tQHatInvModqDivqModtPrecon NTL-specific precomputations
* @param &tQHatInvModqBDivqModt precomputed values for
* [Floor{t*QHatInv_i*B/q_i}]_t used when CRT moduli are 45..60 bits long
* @param &tQHatInvBDivqModtPrecon NTL-specific precomputations
* used when CRT moduli are 45..60 bits long
* @param &tQHatInvModqDivqFrac precomputed values for Frac{t*QHatInv_i/q_i}
* @param &tQHatInvBDivqFrac precomputed values for Frac{t*QHatInv_i*B/q_i}
* used when CRT moduli are 45..60 bits long
* @return the result of computation as a polynomial with native 64-bit
* coefficients
*/
PolyType ScaleAndRound(
const NativeInteger &t,
const std::vector<NativeInteger> &tQHatInvModqDivqModt,
const std::vector<NativeInteger> &tQHatInvModqDivqModtPrecon,
const std::vector<NativeInteger> &tQHatInvModqBDivqModt,
const std::vector<NativeInteger> &tQHatInvModqBDivqModtPrecon,
const std::vector<double> &tQHatInvModqDivqFrac,
const std::vector<double> &tQHatInvModqBDivqFrac) const;
/**
* @brief Computes approximate scale and round:
* {X}_{Q,P} -> {\approx{t/Q * X}}_{P}
* {Q} = {q_1,...,q_l}
* {P} = {p_1,...,p_k}
*
* Brief algorithm:
* Let S = {Q,P}
* 1) [\sum_k x_k * alpha_k]_{p_j}
* 2) alpha_k = [Floor[t*P*[[SHatInv_k]_{s_k}/s_k]]_{p_j}
*
* Source: Halevi S., Polyakov Y., and Shoup V. An Improved RNS Variant of the
* BFV Homomorphic Encryption Scheme. Cryptology ePrint Archive, Report
* 2018/117. (https://eprint.iacr.org/2018/117)
*
* @param ¶msP parameters for the CRT basis {p_1,...,p_k}
* @param &tPSHatInvModsDivsModp precomputed values for
* [\floor[t*P*[[SHatInv_k]_{s_k}/s_k]]_{p_j}
* @param &modpBarretMu 128-bit Barrett reduction precomputed values for
* p_j
* @return the result {\approx{t/Q * X}}_{P}
*/
DCRTPolyType ApproxScaleAndRound(
const shared_ptr<Params> paramsP,
const std::vector<std::vector<NativeInteger>> &tPSHatInvModsDivsModp,
const std::vector<DoubleNativeInt> &modpBarretMu) const;
/**
* @brief Computes scale and round:
* {X}_{Q,P} -> {t/Q * X}_{P}
* {Q} = {q_1,...,q_l}
* {P} = {p_1,...,p_k}
*
* Brief algorithm:
* Let S = {Q,P}
* 1) [\sum_k x_k * alpha_k + Round(\sum_k beta_k * x_k)]_{p_j}
* 2) alpha_k = [Floor[t*P*[[SHatInv_k]_{s_k}/s_k]]_{p_j}
* 3) beta_k = {t*P*[[SHatInv_k]_{s_k}/s_k}
*
* Source: Halevi S., Polyakov Y., and Shoup V. An Improved RNS Variant of the
* BFV Homomorphic Encryption Scheme. Cryptology ePrint Archive, Report
* 2018/117. (https://eprint.iacr.org/2018/117)
*
* @param ¶msP parameters for the CRT basis {p_1,...,p_k}
* @param &tPSHatInvModsDivsModp precomputed values for
* [\floor[t*P*[[SHatInv_k]_{s_k}/s_k]]_{p_j}
* @param &tPSHatInvModsDivsFrac precomputed values for
* {t*P*[[SHatInv_k]_{s_k}/s_k}
* @param &modpBarretMu 128-bit Barrett reduction precomputed values for
* p_j
* @return the result {t/Q * X}_{P}
*/
DCRTPolyType ScaleAndRound(
const shared_ptr<Params> paramsP,
const std::vector<std::vector<NativeInteger>> &tPSHatInvModsDivsModp,
const std::vector<double> &tPSHatInvModsDivsFrac,
const std::vector<DoubleNativeInt> &modpBarretMu) const;
/**
* @brief Computes scale and round for fast rounding:
* {X}_{Q} -> {\round(t/Q * X)}_t
* {Q} = {q_1,...,q_l}
*
* Brief algorithm:
*
* Source: Jean-Claude Bajard and Julien Eynard and Anwar Hasan and Vincent
* Zucca. A Full RNS Variant of FV like Somewhat Homomorphic Encryption
* Schemes. Cryptology ePrint Archive: Report 2016/510.
* (https://eprint.iacr.org/2016/510)
*
* @param &moduliQ moduli {q_1,...,q_l}
* @param &t often corresponds to the plaintext modulus
* @param &tgamma t * gamma : t * 2^26 reduction
* @param &tgammaQHatModq [t*gamma*(Q/q_i)]_{q_i}
* @param &tgammaQHatModqPrecon NTL-specific precomputations
* @param &negInvqModtgamma [-q^{-1}]_{t*gamma}
* @param &negInvqModtgammaPrecon NTL-specific precomputations
* @return
*/
PolyType ScaleAndRound(
const std::vector<NativeInteger> &moduliQ, const NativeInteger &t,
const NativeInteger &tgamma,
const std::vector<NativeInteger> &tgammaQHatModq,
const std::vector<NativeInteger> &tgammaQHatModqPrecon,
const std::vector<NativeInteger> &negInvqModtgamma,
const std::vector<NativeInteger> &negInvqModtgammaPrecon) const;
/**
* @brief Expands basis:
* {X}_{Q} -> {X}_{Q,Bsk,mtilde}
* mtilde is a redundant modulus used to remove q overflows generated from
* fast conversion. Outputs the resulting polynomial in CRT/RNS
* {Q} = {q_1,...,q_l}
* {Bsk} = {bsk_1,...,bsk_k}
*
*
* Source: Jean-Claude Bajard and Julien Eynard and Anwar Hasan and Vincent
* Zucca. A Full RNS Variant of FV like Somewhat Homomorphic Encryption
* Schemes. Cryptology ePrint Archive: Report 2016/510.
* (https://eprint.iacr.org/2016/510)
*
* @param paramsBsk: container of Bsk moduli and roots on unity
* @param &moduliQ: basis {Q} = {q_1,q_2,...,q_l}
* @param &moduliBsk: basis {Bsk U mtilde} ...
* @param &modbskBarrettMu: 128-bit Barrett reduction precomputed values for
* bsk_j
* @param &mtildeQHatInvModq: [mtilde*(Q/q_i)^{-1}]_{q_i}
* @param &mtildeQHatInvModqPrecon NTL-specific precomputations
* @param &QHatModbsk: [Q/q_i]_{bsk_j}
* @param &QHatModmtilde: [Q/q_i]_{mtilde}
* @param &QModbsk: [Q]_{bsk_j}
* @param &QModbskPrecon NTL-specific precomputations
* @param &negQInvModmtilde: [-Q^{-1}]_{mtilde}
* @param &mtildeInvModbsk: [mtilde^{-1}]_{bsk_j}
* @param &mtildeInvModbskPrecon NTL-specific precomputations
*/
void FastBaseConvqToBskMontgomery(
const shared_ptr<Params> paramsBsk,
const std::vector<NativeInteger> &moduliQ,
const std::vector<NativeInteger> &moduliBsk,
const std::vector<DoubleNativeInt> &modbskBarrettMu,
const std::vector<NativeInteger> &mtildeQHatInvModq,
const std::vector<NativeInteger> &mtildeQHatInvModqPrecon,
const std::vector<std::vector<NativeInteger>> &QHatModbsk,
const std::vector<uint16_t> &QHatModmtilde,
const std::vector<NativeInteger> &QModbsk,
const std::vector<NativeInteger> &QModbskPrecon,
const uint16_t &negQInvModmtilde,
const std::vector<NativeInteger> &mtildeInvModbsk,
const std::vector<NativeInteger> &mtildeInvModbskPrecon);
/**
* @brief Computes scale and floor:
* {X}_{Q,Bsk} -> {\floor{t/Q * X}}_{Bsk}
* {Q} = {q_1,...,q_l}
* {Bsk} = {bsk_1,...,bsk_k}
* Outputs the resulting polynomial in CRT/RNS
*
* Source: Jean-Claude Bajard and Julien Eynard and Anwar Hasan and Vincent
* Zucca. A Full RNS Variant of FV like Somewhat Homomorphic Encryption
* Schemes. Cryptology ePrint Archive: Report 2016/510.
* (https://eprint.iacr.org/2016/510)
*
* @param &t: plaintext modulus
* @param &moduliQ: {Q} = {q_1,...,q_l}
* @param &moduliBsk: {Bsk} = {bsk_1,...,bsk_k}
* @param &modbskBarrettMu: 128-bit Barrett reduction precomputed values for
* bsk_j
* @param &tQHatInvModq: [(Q/q_i)^{-1}]_{q_i}
* @param &tQHatInvModqPrecon: NTL-specific precomputations
* @param &QHatModbsk: [Q/q_i]_{bsk_i}
* @param &qInvModbsk: [(q_i)^{-1}]_{bsk_j}
* @param &tQInvModbsk: [t*Q^{-1}]_{bsk_j}
* @param &tQInvModbskPrecon: NTL-specific precomputations
*/
void FastRNSFloorq(const NativeInteger &t,
const std::vector<NativeInteger> &moduliQ,
const std::vector<NativeInteger> &moduliBsk,
const std::vector<DoubleNativeInt> &modbskBarrettMu,
const std::vector<NativeInteger> &tQHatInvModq,
const std::vector<NativeInteger> &tQHatInvModqPrecon,
const std::vector<std::vector<NativeInteger>> &QHatModbsk,
const std::vector<std::vector<NativeInteger>> &qInvModbsk,
const std::vector<NativeInteger> &tQInvModbsk,
const std::vector<NativeInteger> &tQInvModbskPrecon);
/**
* @brief @brief Converts basis:
* {X}_{Q,Bsk} -> {X}_{Bsk}
* {Q} = {q_1,...,q_l}
* {Bsk} = {bsk_1,...,bsk_k}
* using Shenoy Kumaresan method.
* Outputs the resulting polynomial in CRT/RNS
*
* Source: Jean-Claude Bajard and Julien Eynard and Anwar Hasan and Vincent
* Zucca. A Full RNS Variant of FV like Somewhat Homomorphic Encryption
* Schemes. Cryptology ePrint Archive: Report 2016/510.
* (https://eprint.iacr.org/2016/510)
*
* Note in the source paper, B is referred to by M.
*
* @param &moduliQ: basis Q = {q_1,...,q_l}
* @param &modqBarrettMu precomputed Barrett Mu for q_i
* @param &moduliBsk: basis {Bsk} = {bsk_1,...,bsk_k}
* @param &modbskBarrettMu: precomputed Barrett Mu for bsk_j
* @param &BHatInvModb: [(B/b_j)^{-1}]_{b_j}
* @param &BHatInvModbPrecon NTL precomptations for [(B/b_j)^{-1}]_{b_j}
* @param &BHatModmsk: [B/b_j]_{msk}
* @param &BInvModmsk: [B^{-1}]_{msk}
* @param &BInvModmskPrecon NTL precomptation for [B^{-1}]_{msk}
* @param &BHatModq: [B/b_j]_{q_i}
* @param &BModq: [B]_{q_i}
* @param &BModqPrecon NTL precomptations for [B]_{q_i}
*/
void FastBaseConvSK(const std::vector<NativeInteger> &moduliQ,
const std::vector<DoubleNativeInt> &modqBarrettMu,
const std::vector<NativeInteger> &moduliBsk,
const std::vector<DoubleNativeInt> &modbskBarrettMu,
const std::vector<NativeInteger> &BHatInvModb,
const std::vector<NativeInteger> &BHatInvModbPrecon,
const std::vector<NativeInteger> &BHatModmsk,
const NativeInteger &BInvModmsk,
const NativeInteger &BInvModmskPrecon,
const std::vector<std::vector<NativeInteger>> &BHatModq,
const std::vector<NativeInteger> &BModq,
const std::vector<NativeInteger> &BModqPrecon);
/**
* @brief Convert from Coefficient to CRT or vice versa; calls FFT and inverse
* FFT.
*/
void SwitchFormat();
/**
* @brief Switch modulus and adjust the values
*
* @param &modulus is the modulus to be set
* @param &rootOfUnity is the corresponding root of unity for the modulus
* @param &modulusArb is the modulus used for arbitrary cyclotomics CRT
* @param &rootOfUnityArb is the corresponding root of unity for the modulus
* ASSUMPTION: This method assumes that the caller provides the correct
* rootOfUnity for the modulus
*/
void SwitchModulus(const Integer &modulus, const Integer &rootOfUnity,
const Integer &modulusArb = Integer(0),
const Integer &rootOfUnityArb = Integer(0)) {
PALISADE_THROW(not_implemented_error,
"SwitchModulus not implemented on DCRTPoly");
}
/**
* @brief Switch modulus at tower i and adjust the values
*
* @param index is the index for the tower
* @param &modulus is the modulus to be set
* @param &rootOfUnity is the corresponding root of unity for the modulus
* ASSUMPTION: This method assumes that the caller provides the correct
* rootOfUnity for the modulus
*/
void SwitchModulusAtIndex(usint index, const Integer &modulus,
const Integer &rootOfUnity);
/**
* @brief Determines if inverse exists
*
* @return is the Boolean representation of the existence of multiplicative
* inverse.
*/
bool InverseExists() const;
/**
* @brief Returns the infinity norm, basically the largest value in the ring
* element.
*
* @return is the largest value in the ring element.
*/
double Norm() const;
/**
* @brief ostream operator
* @param os the input preceding output stream
* @param vec the element to add to the output stream.
* @return a resulting concatenated output stream
*/
friend inline std::ostream &operator<<(std::ostream &os,
const DCRTPolyType &vec) {
// os << (vec.m_format == EVALUATION ? "EVAL: " : "COEF: ");
for (usint i = 0; i < vec.GetAllElements().size(); i++) {
if (i != 0) os << std::endl;
os << i << ": ";
os << vec.GetAllElements()[i];
}
return os;
}
/**
* @brief Element-element addition operator.
* @param a first element to add.
* @param b second element to add.
* @return the result of the addition operation.
*/
friend inline DCRTPolyType operator+(const DCRTPolyType &a,
const DCRTPolyType &b) {
return a.Plus(b);
}
/**
* @brief Element-integer addition operator.
* @param a first element to add.
* @param b integer to add.
* @return the result of the addition operation.
*/
friend inline DCRTPolyType operator+(const DCRTPolyType &a,
const Integer &b) {
return a.Plus(b);
}
/**
* @brief Integer-element addition operator.
* @param a integer to add.
* @param b element to add.
* @return the result of the addition operation.
*/
friend inline DCRTPolyType operator+(const Integer &a,
const DCRTPolyType &b) {
return b.Plus(a);
}
/**
* @brief Element-integer addition operator with CRT integer.
* @param a first element to add.
* @param b integer to add.
* @return the result of the addition operation.
*/
friend inline DCRTPolyType operator+(const DCRTPolyType &a,
const vector<Integer> &b) {
return a.Plus(b);
}
/**
* @brief Integer-element addition operator with CRT integer.
* @param a integer to add.
* @param b element to add.
* @return the result of the addition operation.
*/
friend inline DCRTPolyType operator+(const vector<Integer> &a,
const DCRTPolyType &b) {
return b.Plus(a);
}
/**
* @brief Element-element subtraction operator.
* @param a element to subtract from.
* @param b element to subtract.
* @return the result of the subtraction operation.
*/
friend inline DCRTPolyType operator-(const DCRTPolyType &a,
const DCRTPolyType &b) {
return a.Minus(b);
}
/**
* @brief Element-integer subtraction operator with CRT integer.
* @param a first element to subtract.
* @param b integer to subtract.
* @return the result of the subtraction operation.
*/
friend inline DCRTPolyType operator-(const DCRTPolyType &a,
const vector<Integer> &b) {
return a.Minus(b);
}
/**
* @brief Integer-element subtraction operator with CRT integer.
* @param a integer to subtract.
* @param b element to subtract.
* @return the result of the subtraction operation.
*/
friend inline DCRTPolyType operator-(const vector<Integer> &a,
const DCRTPolyType &b) {
return b.Minus(a);
}
/**
* @brief Element-integer subtraction operator.
* @param a element to subtract from.
* @param b integer to subtract.
* @return the result of the subtraction operation.
*/
friend inline DCRTPolyType operator-(const DCRTPolyType &a,
const Integer &b) {
return a.Minus(b);
}
/**
* @brief Element-element multiplication operator.
* @param a element to multiply.
* @param b element to multiply.
* @return the result of the multiplication operation.
*/
friend inline DCRTPolyType operator*(const DCRTPolyType &a,
const DCRTPolyType &b) {
return a.Times(b);
}
/**
* @brief Element-integer multiplication operator.
* @param a element to multiply.
* @param b integer to multiply.
* @return the result of the multiplication operation.
*/
friend inline DCRTPolyType operator*(const DCRTPolyType &a,
const Integer &b) {
return a.Times(b);
}
/**
* @brief Element-CRT number multiplication operator.
* @param a element to multiply.
* @param b integer to multiply, in CRT format.
* @return the result of the multiplication operation.
*/
friend inline DCRTPolyType operator*(const DCRTPolyType &a,
const vector<Integer> &b) {
return a.Times(b);
}
/**
* @brief Integer-element multiplication operator.
* @param a integer to multiply.
* @param b element to multiply.
* @return the result of the multiplication operation.
*/
friend inline DCRTPolyType operator*(const Integer &a,
const DCRTPolyType &b) {
return b.Times(a);
}
/**
* @brief Element-signed-integer multiplication operator.
* @param a element to multiply.
* @param b integer to multiply.
* @return the result of the multiplication operation.
*/
friend inline DCRTPolyType operator*(const DCRTPolyType &a, int64_t b) {
return a.Times((bigintnat::NativeInteger::SignedNativeInt)b);
}
/**
* @brief signed-Integer-element multiplication operator.
* @param a integer to multiply.
* @param b element to multiply.
* @return the result of the multiplication operation.
*/
friend inline DCRTPolyType operator*(int64_t a, const DCRTPolyType &b) {
return b.Times((bigintnat::NativeInteger::SignedNativeInt)a);
}
save和load
template <class Archive>
void save(Archive &ar, std::uint32_t const version) const {
ar(::cereal::make_nvp("v", m_vectors));
ar(::cereal::make_nvp("f", m_format));
ar(::cereal::make_nvp("p", m_params));
}
template <class Archive>
void load(Archive &ar, std::uint32_t const version) {
if (version > SerializedVersion()) {
PALISADE_THROW(deserialize_error,
"serialized object version " + std::to_string(version) +
" is from a later version of the library");
}
ar(::cereal::make_nvp("v", m_vectors));
ar(::cereal::make_nvp("f", m_format));
ar(::cereal::make_nvp("p", m_params));
}
std::string SerializedObjectName() const { return "DCRTPoly"; }
static uint32_t SerializedVersion() { return 1; }
namespace lbcrypto {
typedef DCRTPolyImpl<BigVector> DCRTPoly;
}