HElib:安装 & 使用

参考文献:

  1. HElib 源码
  2. googletest 源码
  3. bats-core 源码
  4. [HS13] Halevi S, Shoup V. Design and implementation of a homomorphic-encryption library[J]. IBM Research (Manuscript), 2013, 6(12-15): 8-36.
  5. [HS14] Halevi S, Shoup V. Algorithms in helib[C]//Advances in Cryptology–CRYPTO 2014: 34th Annual Cryptology Conference, Santa Barbara, CA, USA, August 17-21, 2014, Proceedings, Part I 34. Springer Berlin Heidelberg, 2014: 554-571.
  6. [HS15] Halevi S, Shoup V. Bootstrapping for helib[J]. Journal of Cryptology, 2021, 34(1): 7.
  7. [HS18] Halevi S, Shoup V. Faster homomorphic linear transformations in HElib[C]//Annual International Cryptology Conference. Cham: Springer International Publishing, 2018: 93-120.
  8. [HS20] Halevi S, Shoup V. Design and implementation of HElib: a homomorphic encryption library[J]. Cryptology ePrint Archive, 2020.
  9. 安装 GMP、NTL、CTMalloc
  10. 全同态加密:BGV
  11. 全同态加密:CKKS
  12. Full-RNS BGV/BFV
  13. FHE 的槽置换:Benes Network
  14. Level FHE 的快速算法:Double-CRT & Dot Multiplication
  15. 基于插值的同态比较算法 & Paterson-Stockmeyer 多项式求值算法

HElib

编译

配置环境,

sudo apt-get install patchelf #安装patchelf

cd ./googletest-main #编译安装gtest

cmake ./

sudo make && make install

cd ./bats-core-master #安装bats

sudo ./install.sh /usr/local lib64

正式编译,

mkdir build

cd ./build

cmake -DPACKAGE_BUILD=ON -DENABLE_TEST=ON -DGMP_DIR="${GMPDIR}" -DNTL_DIR="${NTLDIR}" .. #开启一些选项

make -j 16 #多线程编译, build/helib_pack

ctest #测试编译是否正确, build/xunit_test_result

sudo make install #安装到计算机

详细安装信息查看 install_manifest.txt,因为 HElib 应该没有编写 make uninstall,可以使用命令 xargs rm < install_manifest.txt 简单删除文件。

示例

编译示例

cd /examples

mkdir build

cd ./build

cmake ..

make

运行 CKKS 用例:

>>> bin/01_ckks_basics

securityLevel=157.866
distance=3.15527e-06

>>> bin/02_ckks_depth

securityLevel=129.741
c.capacity=328.497 c.errorBound=1.28242e-06
c.capacity=289.748 c.errorBound=2.69368e-06
c.capacity=252.063 c.errorBound=5.73764e-06
c.capacity=213.502 c.errorBound=1.16416e-05
c.capacity=176.579 c.errorBound=2.37458e-05
c.capacity=139.634 c.errorBound=4.79519e-05
distance=4.17908e-05

>>> bin/03_ckks_data_movement

securityLevel=129.741
c.capacity=318.497 c.errorBound=1.25236e-09
c.capacity=310.254 c.errorBound=6.4202e-09
c.capacity=310.254 c.errorBound=1.64714e-08
c.capacity=271.254 c.errorBound=1.71435e-08
c.capacity=232.254 c.errorBound=1.78156e-08
c.capacity=219.254 c.errorBound=0.000145946
distance=0.000135014
GOOD

运行 BGV 用例:

>>> bin/BGV_packed_arithmetic

Initialising context object...
m = 32109, p = 4999, phi(m) = 16560
  ord(p) = 690
  normBnd = 2.32723
  polyNormBnd = 58.2464
  factors = [3 7 11 139]
  generator 320 has order (== Z_m^*) of 6
  generator 3893 has order (== Z_m^*) of 2
  generator 14596 has order (== Z_m^*) of 2
  T = [ 1 14596 3893 21407 320 14915 25618 11023 6073 20668 9965 27479 16820 31415 10009 27523 20197 2683 24089 9494 9131 23726 2320 19834 ]
r = 1
nslots = 24
hwt = 0
ctxtPrimes = [6,7,8,9,10,11,12,13,14]
specialPrimes = [15,16,17,18,19]
number of bits = 773

security level = 62.4783

Security: 62.4783
Creating secret key...
Generating key-switching matrices...
Number of slots: 24
Initial Plaintext: {"HElibVersion":"2.2.0","content":{"scheme":"BGV","slots":[[0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23]]},"serializationVersion":"0.0.1","type":"Ptxt"}
Operation: 2(a*a)/(a*a) - 2(a*a)/(a*a) = 0
Decrypted Result: {"HElibVersion":"2.2.0","content":{"scheme":"BGV","slots":[[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0]]},"serializationVersion":"0.0.1","type":"Ptxt"}
Plaintext Result: {"HElibVersion":"2.2.0","content":{"scheme":"BGV","slots":[[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0]]},"serializationVersion":"0.0.1","type":"Ptxt"}
Operation: Enc{(0 + 1)*1} + (0 + 1)*1
Decrypted Result: {"HElibVersion":"2.2.0","content":{"scheme":"BGV","slots":[[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2],[2]]},"serializationVersion":"0.0.1","type":"Ptxt"}

除了 ./examples 中介绍基本用法,./tests 中其实有更详细的示例。

各个模块的作用

HElib 的各个结构好复杂啊,./example 给的例子太简单了,编写工程代码需要更多的接口。花了两天时间翻看 ./include./src 源码,记录下它们的结构和接口。文章 [HS13] 解释了某些结构的设计原理。

在这里插入图片描述

scheme.h

定义了 struct CKKSstruct BGV,用于确定方案的底层代数结构。

  • CKKS 方案,明文槽结构 std::complex<double>,也就是 C \mathbb C C 的浮点数近似
  • BGV 方案,明文槽结构 PolyMod,形如 Z p r [ X ] / ( G ( X ) ) \mathbb Z_{p^r}[X]/(G(X)) Zpr[X]/(G(X)),其中 G G G Φ m ( X ) \Phi_m(X) Φm(X) 的不可约因子

Context.h

安全性:

  • double lweEstimateSecurity(int n, double log2AlphaInv, int hwt),输入维度 n n n,噪声比率 α \alpha α,以及 s k ∈ { 0 , ± 1 } ∗ sk \in \{0,\pm1\}^* sk{ 0,±1} 的汉明重量,估计它的安全强度。
  • long FindM(long k, long nBits, long c, long p, long d, long s, long chosen_m, bool verbose = false),输入密文模数 Q 0 ≈ 2 n B i t s Q_0 \approx 2^{nBits} Q02nBits,KeySwitch 矩阵列数 c c c,明文空间特征 p p p,明文槽的度数 d d d 和个数 s s s,确定出参数 m m m 的大小。

定义了 struct Context::ModChainParamsstruct Context::BootStrapParamsstruct Context::SerializableContent,分别记录密文模数、自举参数、序列化(用于读写数据)

定义了 class Context,用于存储方案的关键信息,下面的其他模块依赖于此。

  • std::vector<Cmodulus> moduli,私有属性,用于存储不同的素数,这个列表只增(不减不改)
  • zMStar, alMod, slotRing,私有属性,记录代数结构 Z m ∗ \mathbb Z_m^* Zm Z [ X ] / ( Φ m ( X ) , p r ) \mathbb Z[X]/(\Phi_m(X),p^r) Z[X]/(Φm(X),pr) Z [ X ] / ( G ( X ) , p r ) \mathbb Z[X]/(G(X),p^r) Z[X]/(G(X),pr)
  • stdev = 3.2, scale = 10,私有属性,记录噪声和明文缩放因子
  • ctxtPrimes, specialPrimes,smallPrimes,私有属性,记录 pk 和 ct 的模数,记录 Key-Switch 使用的模数,记录 modulus-Switch 使用的模数
  • std::vector<IndexSet> digits,私有属性,记录 Key-Switch 中的数字分解,每个 digits[i] 是多个素数的乘积
  • ThinRecryptData rcData,私有属性,记录 “thin” 或者 “thick” 自举信息
  • Context(unsigned long m, unsigned long p, unsigned long r, const std::vector<long>& gens, const std::vector<long>& ords),构造函数,CKKS 方案的 r 是 bit precision,BGV 方案的 r 是 Hensel lifting parameter,gens, ords 是群 Z m ∗ \mathbb Z_m^* Zm 的循环结构
  • getM, getP, getPhiM, getOrdP, getNSlots, getScale, getStdev, getR, getPPowR, getrecision, getSlotRing, getsCtxtPrimes, getsDigit, getRcData,获取相关参数
  • getZMStar, getAlMod, getEA, sharedEA,获取 PAlgebra zMStarPAlgebraMod alModstd::shared_ptr<const EncryptedArray> ea 的引用
  • noiseBoundForUniform, noiseBoundForMod, noiseBoundForGaussian, noiseBoundForSmall, noiseBoundForHWt,高概率的噪声估计
  • stdDevForRecryption, boundForRecryption,自举噪声估计
  • void enableBootStrapping(const NTL::Vec<long>& mvec, bool build_cache = false, bool alsoThick = true),初始化自举数据 rcData,输入的 mvec 是参数 m m m 的唯一素分解
  • fullPrimes, allPrimes,前者获取 ctxtPrimes + specialPrimes,后者还额外获取 smallPrimes,返回值都是 IndexSet 句柄
  • ithPrime, ithModulus,获取特定位置的素数、模数
  • logOfPrime, logOfProduct, bitSizeOfQ,获取某些数值的规模
  • double securityLevel(),估计安全强度,其中 s = 3.2 ⋅ m s=3.2 \cdot \sqrt m s=3.2m α = s / q \alpha=s/q α=s/q n = ϕ ( m ) n=\phi(m) n=ϕ(m)
  • clearModChain, buildModChain, endBuildModChain,构造密文模数链

定义了 template <typename SCHEME> class ContextBuilder,用于构造 Context 对象,

  • gens_, ords_, m_, p_, r_, c_, ...,私有的数据属性,存储若干的必要参数
  • m, p, r, precision, scale, stdev, c, gens, ords, bits, skHwt, ...,公开的函数属性,用于初始化
  • mvec, thinboot, thickboot, buildCache, bootstrappable,BGV 方案的自举相关
  • Context build(),根据自身存储的信息,构造上下文对象

primeChain.h

定义了 class ModuliSizes,用于根据 modulo-size 确定 primeSets

  • typedef std::pair<double, IndexSet> Entry,存储 (size, set-of-primes) 元组
  • void init(const Context& context),初始化素数存储表
  • IndexSet getSet4Size(double low, double high, const IndexSet& fromSet, bool reverse),确定指标集 formSet 中的最大子集,使得这些素数的乘积满足区间 [low, high]

DoubleCRT.h

定义了 class DoubleCRT,构造 L L L ϕ ( m ) \phi(m) ϕ(m) 列矩阵,第 i i i 行使用 p i p_i pi 素数执行 FFT/NTT。所包含的属性:

  • const Context& context,私有属性,绑定到某个上下文,记录了 ctxtPrimesspecialPrimes 信息
  • DoubleCRT(const NTL::ZZX& poly, const Context& _context, const IndexSet& indexSet),根据上下文(记录了可用的素数 context.ithPrime(i))以及使用的素数索引 IndexSet(动态数组),将 poly 转变为 DoubleCRT 格式
  • long getOneRow(NTL::zz_pX& row, long idx),获取 DoubleCRT 的某一行多项式(系数表示)
  • void toPoly(NTL::ZZX& p, const IndexSet& s, bool positive = false),将指定行的数据合成为多项式
  • void addPrimes(const IndexSet& s1, NTL::ZZX* poly_p = 0),将 DoubleCRT 扩展一些行(先将现有的数据 IFFT,然后对新添的素数做 FFT)
  • void removePrimes(const IndexSet& s1),将 DoubleCRT 删除一些行(简单删除,效果是简单取模)
  • void setPrimes(const IndexSet& s1),从当前 CRT 基转换到 IndexSet 指定的基
  • DoubleCRT& SetZero(), DoubleCRT& SetOne(),设置数值
  • DoubleCRT& Negate(), +=, -=, *=, /=, ==, !=,基本运算符

hypercube.h

定义了 class CubeSignature,存储高阶立方(明文槽)的维度信息。

  • dims, prods,私有属性,前者存储各个维度的大小,后者存储 slice 的规模 p r o d s [ d ] = ∏ j = d n − 1 d i m s [ j ] prods[d] = \prod_{j=d}^{n-1} dims[j] prods[d]=j=dn1dims[j](固定前 d 个坐标,遍历后 n-d 个坐标;特别地,仅固定第 0 个坐标称为 col
  • getNumDims, getSize, getDim, getProd, numSlices, sliceSize, numCols,获取 dim, slice, col 的信息
  • long getCoord(long i, long d),计算索引 i 在第 d 维上的坐标
  • void getAllCoords(VecType& v, long i),获取索引 i 的高阶立方上的坐标 v
  • long assembleCoords(VecType& v),将坐标 v 重构为索引 i
  • long addCoord(long i, long d, long offset),确定索引 i 在第 d 维上的坐标偏移 offset 之后的新索引 i'
  • bool incrementCoords(VecType& v),根据坐标 v,确定它的索引 i 的下一个索引

定义了 template <typename T> class HyperCube,管理高阶立方中的数据对象。

  • NTL::Vec<T> data,存储数据(高阶立方被存储为单个向量)
  • ==, !=,判断两个立方的形状和数据是否完全相同
  • getSig, getData, getDim, getNumDims, getProd, getCoord, numSlices, sliceSize, numCols,获取相关的维度、规模信息
  • at, [],获取索引 i 的数据引用
  • rotate1D(i, k), shift1D(i, k),将维度 i 右旋/右移 k

定义了 class ConstCubeSlice, class CubeSlice,用于管理某个 slice

另外,getHyperColumn, setHyperColumn,获取/设置高阶立方的某个 col

PAlgebra.h

定义了 class PAlgebra,用于支持 Z m ∗ ≅ ( p ) × ( g 1 , g 2 , ⋯   ) × ( f 1 , f 2 , ⋯   ) \mathbb Z_m^* \cong (p) \times (g_1,g_2,\cdots) \times (f_1,f_2,\cdots) Zm(p)×(g1,g2,)×(f1,f2,),它同构于分圆整数环 A : = Z [ X ] / ( Φ m ( X ) ) \mathbb A:=\mathbb Z[X]/(\Phi_m(X)) A:=Z[X]/(Φm(X)) 的 Galois 群。此结构完全由 m , p m,p m,p 决定,其中 p p p 是满足 p ∤ m p \nmid m pm 的素数。群 ( g 1 , g 2 , ⋯   ) (g_1,g_2,\cdots) (g1,g2,) 包含所有的 ”在 Z m ∗ \mathbb Z_m^* Zm Z m ∗ / ( p , g 1 , ⋯   , g i − 1 ) \mathbb Z_m^*/(p,g_1,\cdots,g_{i-1}) Zm/(p,g1,,gi1) 中拥有相同阶“ 的那些元素,群 ( f 1 , f 2 , ⋯   ) (f_1,f_2,\cdots) (f1,f2,) 生成商群 Z m ∗ / ( p , g 1 , g 2 , ⋯   ) \mathbb Z_m^*/(p,g_1,g_2,\cdots) Zm/(p,g1,g2,)

查找表 T ⊆ Z m ∗ T \subseteq \mathbb Z_m^* TZm 是商群 Z m ∗ / ( p ) \mathbb Z_m^*/(p) Zm/(p) 的代表,
T : = { ∏ i g i e i ⋅ ∏ j h j e j ∣ e i ∈ [ o r d ( g i ) ] , e j ∈ [ o r d ( h j ) ] } T:=\left\{\prod_i g_i^{e_i} \cdot \prod_j h_j^{e_j} \Big| e_i \in [ord(g_i)], e_j \in [ord(h_j)]\right\} T:={ igieijhjej ei[ord(gi)],ej[ord(hj)]}
假设 ∣ T ∣ = l |T|=l T=l,令 d = ϕ ( m ) / l d=\phi(m)/l d=ϕ(m)/l,那么有如下分圆多项式的分解
Φ m ( X ) = ∏ t ∈ T F t ( X ) \Phi_m(X) = \prod_{t \in T} F_t(X) Φm(X)=tTFt(X)
易知 1 ∈ T 1 \in T 1T,首先确定任意的不可约因子设为 F 1 ( X ) F_1(X) F1(X),然后计算其他的因子 F t ( X ) = gcd ⁡ ( F 1 ( X t ) , Φ m ( X ) ) F_t(X)=\gcd(F_1(X^t),\Phi_m(X)) Ft(X)=gcd(F1(Xt),Φm(X)),这些 l l l 个不可约因子次数都为 d d d。固定多项式环 R : = Z p [ X ] / ( F 1 ( X ) ) R:=\mathbb Z_p[X]/(F_1(X)) R:=Zp[X]/(F1(X)),假如 ρ \rho ρ F 1 F_1 F1 的根,那么 ρ 1 / t \rho^{1/t} ρ1/t 的极小多项式是 F t ( X ) F_t(X) Ft(X)

class PAlgebra 的属性:

  • m, p, phiM, ordP, nfactors, radm, normBnd, polyNormBnd,私有属性,管理相关参数
  • std::vector<long> gens,私有属性,管理 Z m ∗ \mathbb Z_m^* Zm 的生成元
  • NTL::Vec<bool> native,私有属性,native[i]=true 指示 gens[i] 落在子群 ( g 1 , g 2 , ⋯   ) (g_1,g_2,\cdots) (g1,g2,)
  • NTL::Vec<long> frob_perturb,私有属性,frob_perturb[i]=j 指示 gens[i] 的乘法阶为 p j p^j pj
  • CubeSignature cube,私有属性,管理 Z m ∗ / ( p ) \mathbb Z_m^*/(p) Zm/(p) 的高阶立方的结构
  • std::vector<long> T, Tidx,私有属性,前者 T[i]=t 记录了各个代表元 t ∈ Z m ∗ / ( p ) t \in \mathbb Z_m^*/(p) tZm/(p),后者 Tidx[t]=i 是反过来的
  • std::vector<long> zmsIdx, zmsRep,私有属性,前者 zmsIdx[t]=i 记录了 t ∈ Z m ∗ t \in \mathbb Z_m^* tZm 的次序 i,后者是反过来的
  • long getPhiM(),返回 ϕ ( m ) \phi(m) ϕ(m)(多项式 Φ m ( X ) \Phi_m(X) Φm(X) 的次数)
  • long getRadM(),返回 R a d ( m ) Rad(m) Rad(m)(不同素因子的乘积)
  • const NTL::ZZX& getPhimX(),返回 Φ m ( X ) \Phi_m(X) Φm(X)
  • long getNSlots(),返回明文槽的数量 l l l
  • double get_cM(),返回环常数 c M c_M cM(随机元素在不同 bases 下无穷范数的比值,仅用于自举)
  • long numOfGens(),返回 Z m ∗ / ( p ) \mathbb Z_m^*/(p) Zm/(p) 的生成元个数
  • long ZmStarGen(long i),返回 Z m ∗ / ( p ) \mathbb Z_m^*/(p) Zm/(p) 的生成元 gens[i]
  • long OrderOf(long i),返回 gens[i] 的乘法阶(高阶立方 cubei 维度的规模)
  • long frobeniusPow(long j),返回 Frobenius 映射的指数 p j ( m o d m ) p^j \pmod m pj(modm)
  • long ith_rep(long i),返回第 i i i 个明文槽的代表 T[i]
  • long indexInZmstar(long t),返回元素 t ∈ Z m ∗ t \in \mathbb Z_m^* tZm 的索引 zmsIdx[t]
  • long coordinate(long i, long k),返回索引 k 在维度 i 上的坐标

定义了 class MappingData,用于管理 encoding/decoding slots 的映射信息

  • G, degG,私有属性,域扩张多项式 G ( X ) G(X) G(X),它是 Φ m ( X ) ( m o d p r ) \Phi_m(X) \pmod{p^r} Φm(X)(modpr) 的任意不可约因子
  • maps, matrix_maps, rmaps,私有属性,存储了映射

定义了 class PAlgebraMod,用于支持 Z p r [ X ] \mathbb Z_{p^r}[X] Zpr[X] 上的 encode/decode slots 过程。各个明文槽的结构为 Z p r [ X ] / ( F t ( X ) ) ≅ Z p r [ X ] / ( F 1 ( X ) ) \mathbb Z_{p^r}[X]/(F_t(X)) \cong \mathbb Z_{p^r}[X]/(F_1(X)) Zpr[X]/(Ft(X))Zpr[X]/(F1(X)),简记 R [ X ] : = Z p r [ X ] R[X]:=\mathbb Z_{p^r}[X] R[X]:=Zpr[X]

首先定义了 template <typename type> class PAlgebraModDerived : public PAlgebraModBase 实例化,包含的属性有:

  • const PAlgebra& zMStar,私有属性,管理 Z m ∗ \mathbb Z_m^* Zm 的高阶立方结构
  • r, pPowR, PhimXMod,私有属性,管理相关的参数
  • const vec_RX& getFactors(),返回 Φ m ( X ) ( m o d p r ) \Phi_m(X) \pmod{p^r} Φm(X)(modpr) 的分解 F t ∈ R [ X ] F_t \in R[X] FtR[X]
  • const vec_RX& getCrtCoeffs(),返回 CRT 基 ( ∏ j ≠ i F j ) − 1 ( m o d F i ) (\prod_{j \neq i}F_j)^{-1} \pmod{F_i} (j=iFj)1(modFi)
  • CRT_decompose, CRT_reconstruct,计算多项式 RX H 的 CRT 分解 vector<RX> crt
  • void mapToSlots(MappingData<type>& mappingData, const RX& G),根据 G ( X ) G(X) G(X) 计算出到 slots 的映射
  • void embedInSlots(RX& H, const std::vector<RX>& alphas, const MappingData<type>& mappingData),将 [ α 0 , ⋯   , α l − 1 ] [\alpha_0,\cdots,\alpha_{l-1}] [α0,,αl1] 编码到 H ∈ R [ X ] / ( Φ m ( X ) ) H \in R[X]/(\Phi_m(X)) HR[X]/(Φm(X)) 的 slots 上

class PAlgebraMod 就是某个 PAlgebraModBase 对象实例的指针,

  • ClonedPtr<PAlgebraModBase> rep,私有属性
  • explicit PAlgebraMod(const PAlgebra& zMStar, long r),根据 A p \mathbb A_p Ap r r r 构造 A p r \mathbb A_{p^r} Apr
  • const PAlgebra& getZMStar(),返回底层的 PAlgebra 结构(在 rep 里存储)
  • const std::vector<NTL::ZZX>& getFactorsOverZZ(),返回 Φ m ( X ) ( m o d p r ) \Phi_m(X) \pmod{p^r} Φm(X)(modpr) 的分解(在 rep 里存储)

permutatios.h

使用 typedef NTL::Vec<long> Permut 描述简单置换 p [ i ] = π i p[i] = \pi_i p[i]=πi

  • void applyPermToVec(std::vector<T>& out, const std::vector<T>& in, const Permut& p1),执行一个置换,输出 o u t [ i ] = i n [ p 1 [ i ] ] out[i] = in[p_1[i]] out[i]=in[p1[i]]
  • void applyPermsToVec(std::vector<T>& out, const std::vector<T>& in, const Permut& p2, const Permut& p1),连续执行两个置换,输出 o u t [ i ] = i n [ p 2 [ p 1 [ i ] ] ] out[i] = in[p_2[p_1[i]]] out[i]=in[p2[p1[i]]]

定义了 class ColPerm : public HyperCube<long>,用于置换高阶立方的某一列

定义了 class GeneralBenesNetwork,使用 Benes Network 实现任意的置换(自同构仅提供简单的移位置换)

定义了 template <typename T> class FullBinaryTree,代数结构 Z m ∗ / ( p ) \mathbb Z_m^*/(p) Zm/(p) 的各个生成元,都需要一棵完全二叉树,用于高阶立方各个维度的任意置换

定义了 class PermNetwork,这是一个 “背靠背” 蝴蝶网络,

  • NTL::Vec<PermNetLayer> layers,私有属性,记录了置换网络的各层信息
  • PermNetwork(const Permut& pi, const GeneratorTrees& trees),根据映射 pi 构造置换网络
  • void applyToCtxt(Ctxt& c, const EncryptedArray& ea),密文槽的同态置换

定义了 class PermIndepPrecompclass PermPrecomp,前者是 permutation-independent 预计算,后者是 permutation-dependent 预计算。

PolyModRing.h

定义了 struct PolyModRing,它是明文槽的环结构,都同构于 Z [ X ] / ( G ( X ) , p r ) \mathbb Z[X]/(G(X), p^r) Z[X]/(G(X),pr),其中 G = F t G=F_t G=Ft 是分圆多项式 Φ m ( X ) ( m o d p r ) \Phi_m(X) \pmod{p^r} Φm(X)(modpr) 的任意不可约因子。属性如下:

  • PolyModRing(long p, long r, const NTL::ZZX& G),根据参数构造明文槽的环结构
  • friend std::ostream& operator<<(std::ostream& os, const PolyModRing& ring),打印环结构的参数

PolyMod.h

定义了 class PolyMod,用于存储 Z p r [ X ] / ( G ( X ) ) \mathbb Z_{p^r}[X]/(G(X)) Zpr[X]/(G(X)) 中的多项式。

  • PolyMod(const std::vector<long>& input, const std::shared_ptr<PolyModRing>& ringDescriptor),根据 PolyModRing 将系数表示(input[i]表示 x i x^i xi 的系数)转化为环元素
  • ==, !=, -, *, +, -, *=, +=, -=,基本运算
  • friend std::ostream& operator<<(std::ostream& os, const PolyMod& poly),打印多项式

EncryptedArray.h

定义了 class EncryptedArrayBase,这是 virtual 的类,用于明文槽的数据移动

  • getContext, getPAlgebra, getDegree, getP2R,获取相关参数
  • rotate, shift, rotate1D, shift1D,右旋、右移
  • encode, decode,数组和多项式之间的转换
  • decrypt, rawDecrypt, decryptComplex, rawDecryptComplex, rawDecryptReal, decryptReal,解密函数
  • void buildLinPolyCoeffs(std::vector<NTL::ZZX>& C, const std::vector<NTL::ZZX>& L),根据线性映射 L 构造线性多项式列表 C,两者都是公开的多项式
    • 输入向量 L ∈ ( Z p r [ X ] ) deg ⁡ G L \in (\mathbb Z_p^r[X])^{\deg G} L(Zpr[X])degG,它描述了 Z p r [ X ] / ( G ( X ) ) \mathbb Z_{p^r}[X]/(G(X)) Zpr[X]/(G(X)) 中的某线性映射,满足 M : X j   m o d   G ↦ L [ j ]   m o d   G ,    j = 0 , 1 , ⋯   , deg ⁡ G − 1 M: X^j \bmod G \mapsto L[j] \bmod G,\,\, j=0,1,\cdots,\deg G-1 M:XjmodGL[j]modG,j=0,1,,degG1,也就是 L 描述了 M 对于标准 Power Basis 的作用
    • 输出向量 C ∈ ( Z p r [ X ] ) deg ⁡ G C \in (\mathbb Z_p^r[X])^{\deg G} C(Zpr[X])degG,其中的每一个多项式都是线性的,用于计算 M : h ( X )   m o d   G ↦ ∑ j = 0 deg ⁡ G − 1 C [ j ] ⋅ h ( X p j )   m o d   G M: h(X) \bmod G \mapsto \sum_{j=0}^{\deg G-1} C[j] \cdot h(X^{p^j}) \bmod G M:h(X)modGj=0degG1C[j]h(Xpj)modG,我们称 CM 的线性化多项式(Linearized polynomials)
  • long coordinate(long i, long k),返回索引 k 的维度 i 上坐标

定义了 template <typename type> class EncryptedArrayDerived : public EncryptedArrayBase 实例化,

  • R, vec_R, mat_R, RX, vec_RX, RXModulus, RE, vec_RE, mat_RE, REX, vec_REX,公开属性,管理多项式信息
  • const Context& context,私有属性,管理各种参数
  • MappingData<type> mappingData,私有属性,管理 encode/decode slots 信息
  • rotate, shift, rotate1D, shift1D,循环右移、零填充右移,高阶立方某维度上的右移
  • encode, decode, decrypt, genericEncode, genericDecode, genericDecrypt,编码,解码,解密

定义了 class EncryptedArray,定义了多种与密文有关的接口,但是似乎自身并不存储密文。

  • const PAlgebraMod& alMod,私有属性,支持 Z p r [ X ] \mathbb Z_{p^r}[X] Zpr[X] 上的 encode/decode slots 过程
  • ClonedPtr<EncryptedArrayBase> rep,私有属性
  • rotate, shift, rotate1D, shift1D,循环右移、零填充右移,高阶立方某维度上的右移
  • encode, decode,若干个编码/解码函数
  • encrypt, decrypt, decryptReal, decryptComplex,若干个加密/解密函数

首先定义了 class PlaintextArrayDerived : public PlaintextArrayBase,它携带 std::vector<RX> data 属性存储数据。接着定义了 class PlaintextArray(弃用) 和 class PtxtArray(建议),包含了运算接口:

  • const EncryptedArray& ea,公开属性,定义了加密接口
  • PlaintextArray pa,公开属性,用于存储明文数据
  • void encode(EncodedPtxt& eptxt, double mag = -1, OptLong prec = OptLong()),利用 eapa 编码
  • void encrypt(Ctxt& ctxt, double mag = -1, OptLong prec = OptLong()),利用 eapa 加密(Ctxt 携带属性 PubKey
  • void decrypt(const Ctxt& ctxt, const SecKey& sKey, OptLong prec = OptLong()),利用 eapa 解密(额外输入 SecKey
  • load, store,读写 GF2X, ZZX, vector<long>, vector<double> 等数据
  • buildLinPolyCoeffs,根据线性变换 L 构造线性化多项式 C

定义了一些关于 PtxtArray 的自由函数,

  • ==, !=, +=, -=, *=,明文的基本运算
  • rotate, shift, rotate1D, shift1D,循环右移、零填充右移,高阶立方某维度上的右移
  • frobeniusAutomorph, conjugate, extractRealPart, extractImPart,自同构映射
  • totalSums, runningSums, power,高级的加法/乘法

定义了一些关于 EncryptedArray 的自由函数,

  • totalSums, runningSums,高级的同态加法/乘法
  • void mapTo01(const EncryptedArray& ea, Ctxt& ctxt, bool multithread = true),判断 ctxt 各个明文槽是否是零
  • void incrementalZeroTest(Ctxt* res[], const EncryptedArray& ea, const Ctxt& ctxt, long n),专用于 p − 2 , r = 1 p-2,r=1 p2,r=1 的情况,密文 res[i] 的第 j 个槽是零,如果 ctxt 的第 j 个槽的前 0...i 比特是否都是零
  • void applyLinPoly1(const EncryptedArray& ea, Ctxt& ctxt, const std::vector<NTL::ZZX>& C),将生成的映射 C = ea.buildLinPolyCoeffs 作用到 ctxt 的所有槽上
  • void applyLinPolyMany(const EncryptedArray& ea, Ctxt& ctxt, const std::vector<std::vector<NTL::ZZX>>& Cvec),将若干个映射 Cvec 分别作用到 ctxt 不同的明文槽上,其中 Cvec[0...nslots-1][0...degree-1] 包含 nslots 个长度 degree 的行向量(都由 ea.buildLinPolyCoeffs 生成)

Ptxt.h

定义了明文空间的一些功能,

  • std::vector<typename Scheme::SlotType> convertDataToSlotVector(const std::vector<From>& data, const Context& context)
    • BGV方案,将 vector<From> 转换为 vector<PolyMod>,这里的 From 可以是 NTL::ZZX
    • CKKS 方案,将 vector<From> 转换为 vector<std::complex<double>>,这里的 From 可以是 double

定义了 template <typename Scheme> class Ptxt

  • explicit Ptxt(const Context& context),根据上下文初始化
  • Ptxt(const Context& context, const SlotType& value),将明文槽都设置为 value
  • template <typename T> Ptxt(const Context& context, const std::vector<T>& data),将向量 data 转化到明文槽中
  • size_t size(),返回明文槽的数量 size
  • const Context& getContext(),返回自身的上下文
  • void setData(const SlotType& value),设置明文槽的值
  • void decodeSetData(const NTL::ZZX& data),使用多项式 ZZX 解码后的 slots 设置明文,BGV 专用
  • void clear(), Ptxt<Scheme>& random(),清理明文、随机明文
  • const std::vector<SlotType>& getSlotRepr(),获取明文的 slots 表示
  • NTL::ZZX getPolyRepr(),获取明文的 coeff 表示
  • void encode(EncodedPtxt& eptxt, double mag = -1, OptLong prec = OptLong()),将自身(solts 形式)编码为 EncodedPtxt(poly 形式)
  • ==, !=, *, +, -, *=, +=, -=, negate,基本运算
  • Ptxt<Scheme>& addConstant(const Scalar& scalar),全部明文槽都加常数,BGV 专用
  • Ptxt<Scheme>& addConstantCKKS(const Scalar& scalar),全部明文槽都加常数,CKKS 专用
  • multiplyBy, multiplyBy2, square, cube, power,乘法、幂次
  • Ptxt<Scheme>& rotate(long amount),循环右移,槽 i 移动到 i+amount mod size
  • Ptxt<Scheme>& rotate1D(long dim, long amount),高阶立方体 dim 维度上的循环右移,是由 Z m ∗ \mathbb Z_m^* Zm 的循环群结构 PAlgebra& zMStar = context->getZMStar() 所诱导的
  • Ptxt<Scheme>& shift(long amount),零填充右移
  • Ptxt<Scheme>& shift1D(long dim, long amount),高阶立方体 dim 维度上的零填充右移
  • Ptxt<Scheme>& automorph(long k),自同构映射 a ( X ) ↦ a ( X k ) ( m o d Φ m ( X ) ) a(X) \mapsto a(X^k) \pmod{\Phi_m(X)} a(X)a(Xk)(modΦm(X)),其中 k ∈ Z m ∗ k \in \mathbb Z_m^* kZm
  • Ptxt<Scheme>& frobeniusAutomorph(long j),Frobenius 自同构 a ( X ) ↦ a ( X p j ) ( m o d Φ m ( X ) ) a(X) \mapsto a(X^{p^j}) \pmod{\Phi_m(X)} a(X)a(Xpj)(modΦm(X)),BGV 专用
  • Ptxt<Scheme>& replicate(long pos),第 pos 个明文槽的广播复制
  • complexConj, real, imag,复数变换,CKKS 专用
  • runningSums, totalSums,明文槽加和,前者是前缀槽的和,后者是全部槽的和
  • incrementalProduct, totalProduct,明文槽乘积,前者是前缀槽的积,后者是全部槽的积

EncodedPtxt.h

定义了 class EncodedPtxt_BGV

  • EncodedPtxt_BGV(const zzX& poly_, long ptxtSpace_, const Context& context_),构造函数
  • getPoly, getPtxtSpace, getContext,查看存储的信息

定义了 class EncodedPtxt_CKKS

  • EncodedPtxt_CKKS(const zzX& poly_, double mag_, double scale_, double err_, const Context& context_),构造函数
  • getPoly, getMag, getScale, getErr, getContext,查看存储的信息

定义了 class EncodedPtxt,它要么存储 EncodedPtxt_BGV 要么存储 EncodedPtxt_CKKS,存储结构是 zzX poly

  • eptxt.isBGV(), eptxt.isCKKS(),判断自己是哪个方案
  • eptxt.getBGV(), eptxt.getCKKS(),生成只读的 EncodedPtxt_BGVEncodedPtxt_CKKS 对象引用
  • eptxt.resetBGV(), eptxt.resetCKKS(),重置 EncodedPtxt_BGVEncodedPtxt_CKKS 对象

定义了 FatEncodedPtxt_BGVclass FatEncodedPtxt_CKKSclass FatEncodedPtxt,接口是一样的,但是存储结构为 DoubleCRT dcrt

Ctxt.h

定义了 class SKHandle,用于描述满足形式 s r ( X t ) s^r(X^t) sr(Xt) 的私钥元素(没看懂这是干嘛的),属性 powerOfS, powerOfX, secretKeyID(并没有存储私钥数据,是仅描述位置信息么)

定义了 class CtxtPart : public DoubleCRT,用于存储密文中的单个多项式,包含一个 SKHandle 对象,并继承了 DoubleCRT 的属性(以 DCRT 格式存储和计算)

定义了 class Ctxt,使用 std::vector<CtxtPart> parts 对象来存储密文 c[i] = part[i]

  • context, pubKey,私有属性,密文相关参数的指针
  • parts, primeSet, ptxtSpace, noiseBound,私有属性,存储密文各个分量、用到的素数、明文模数、平均噪声估计
  • intFactor, ratFactor, ptxtMag,私有属性,前者用于 BGV 纠错,后两者用于 CKKS 纠错(尾数部分,指数部分)
  • tensorProduct, subPart, addPart, keySwitchPart, keySwitchDigits,私有属性,用于同态运算
  • ==, !=,检查两个 Ctxt 对象的 size, primeSet, intFactor, noiseBound 是否相同
  • negate, +=, -=, *=,基本的同态运算
  • xorConstant, nxorConstant,根据公式 a ⊕ b = a + b − 2 a b a \oplus b = a+b-2ab ab=a+b2ab ( a ⊕ b ) ‾ = 1 − a − b + 2 a b \overline{(a \oplus b)}=1-a-b+2ab (ab)=1ab+2ab,计算任意明文模数下的异或运算(需要同态乘法)
  • void automorph(long k),自同构映射 F ( X ) → F ( X k ) F(X) \to F(X^k) F(X)F(Xk),其中 gcd ⁡ ( k , m ) = 1 \gcd(k,m)=1 gcd(k,m)=1
  • void smartAutomorph(long k),计算自同构,紧接着执行重线性化
  • void frobeniusAutomorph(long j),也就是 smartAutomorph(p^j mod m)
  • divideByP, multByP,简单作用到密文上,使得明文模数分别变为 p r − 1 , r > 1 p^{r-1},r>1 pr1,r>1 p r + 1 , r ≥ 1 p^{r+1},r\ge1 pr+1,r1
  • multiplyBy, multiplyBy2, square, cube, power,高等同态乘法
  • void evalPoly(const NTL::ZZX& poly),执行同态多项式求值
  • reducePtxtSpace, hackPtxtSpace,模切换过程,后者在明文高位引入噪声
  • void Ctxt::reLinearize(long keyID),重线性化过程,keyID 确定要切换到的私钥 ( 1 , s i ) (1,s_i) (1,si)
  • void blindCtxt(const NTL::ZZX& poly),盲化 BGV 密文,加上常数 poly 的高噪声密文
  • NTL::xdouble modSwitchAddedNoiseBound(),估计模切换带来的额外噪声
  • modUpToSet, modDownToSet, bingToSet,模切换过程,后者先 UpDown
  • void dropSmallAndSpecialPrimes(),移除 Key-Switch 过程的副作用(密文模数放大了 SpecialPrimes),同时会自动添加一些 ctxtPrimes 使得模切换的额外噪声可忽略
  • totalNoiseBound, errorBound,前者估计相位中的噪声(CKKS 要加上 ptxtMag * ratFactor 精度损失),后者估计明文中的噪声(BGV 的是零)
  • capacity, bitcapacity,两者返回的都是 log ⁡ 2 ( Q / B ) \log_2(Q/B) log2(Q/B),标志着同态运算的能力,其中 B = totalNoiseBound() 是噪声界
  • bool isCorrect(),判断是否能够正确解密
  • getContext, getPubKey, getPrimeSet, getPtxtSpace, getNoiseBound, getRatFactor, getPtxtMag, getKeyID,获取本密文的相关信息
  • addedNoiseForCKKSDecryption,对 CKKS 解密结果添加噪声,防止 Approximate FHE IND-CPA+ 攻击

定义了一些自由函数,

  • totalProduct, incrementalProduct, innerProduct,特殊同态乘法的加速实现(二叉树、统一重线性化)
  • conjugate, extractRealPart, extractImPart,CKKS 专用,利用自同构 ctxt.frobeniusAutomorph(1)(同态复共轭)同态提取实部/虚部
  • void extractDigits(std::vector<Ctxt>& digits, const Ctxt& c, long r = 0),BGV 专用,提取明文槽 Z p r [ X ] / ( G ) \mathbb Z_{p^r}[X]/(G) Zpr[X]/(G) 的各个 mod- p p p deigits,其中 digit[j] 的明文模数分别是 p r − j p^{r-j} prj,但是这些密文的 Level 相同
  • extractBits, extendExtractDigits,其他的数字分解
  • void CheckCtxt(const Ctxt& c, const char* label),打印密文的错误信息

polyEval.h

定义了同态多项式计算的接口,使用了 BSGS 算法、Paterson-Stockmeyer 算法,

  • void polyEval(Ctxt& ret, const NTL::Vec<Ctxt>& poly, const Ctxt& x),同态计算明文多项式 ret = poly(x)
  • void evalPoly(const NTL::ZZX& poly),这是 Ctxt 的一个属性
  • void polyEval(Ctxt& ret, const NTL::Vec<Ctxt>& poly, const Ctxt& x),同态计算密文多项式,参数 Vec<Ctxt>& poly 记录了多项式的系数表示, r e t = ∑ i p o l y [ i ] ⋅ x i ret = \sum_i poly[i] \cdot x^i ret=ipoly[i]xi

定义了 class DynamicCtxtPowers,用于同态计算密文 c = Ctxt(X) 的幂次

  • std::vector<Ctxt> v,私有属性,记录 X i X^i Xi 的密文
  • DynamicCtxtPowers(const Ctxt& c, long nPowers),构造函数,初始化长度 nPowers 的数组,简单存储 v[0] = c
  • Ctxt& getPower(long e),如果 X e X^e Xe(存储在 v[e-1] 中)还没有被计算,那么执行同态乘法,否则直接输出已有数据
  • bool isPowerComputed(long i),判断是否预计算过

Key.h

定义了 class PubKey,管理公钥数据以及相关接口,

  • Ctxt pubEncrKey,私有属性,公钥就是零的密文 p k = R L W E s ( 0 ) pk = RLWE_s(0) pk=RLWEs(0)
  • std::vector<KeySwitch> keySwitching,私有属性,记录了多个秘钥切换矩阵 W [ s ′ → s ] W[s' \to s] W[ss]
  • std::vector<std::vector<long>> keySwitchMap,私有属性,这是个指针数组,keySwitchMap[i][n] = j 记录了对 s i ( X n ) s_i(X^n) si(Xn) 重线性化时应当使用 keySwitching[j]
  • Ctxt recryptEkey,私有属性,存储了自举秘钥
  • void Encrypt(Ctxt& ctxt, const EncodedPtxt& eptxt),公钥加密
  • void reCrypt(Ctxt& ctxt), void thinReCrypt(Ctxt& ctxt),自举程序,后者要求 slots 内加密的是数值而非多项式
  • void hackPtxtSpace(long p2r),强行提升明文模数,在 BGV 中会引入高位噪声

定义了 class SecKey : public PubKey,管理私钥数据以及相关接口,

  • std::vector<DoubleCRT> sKeys,私有属性,存储了 s k = s sk=s sk=s
  • GenSecKey, GenKeySWmatrix, getRecryptKey,生成各种秘钥 SK, KSK, BSK
  • void Decrypt(NTL::ZZX& plaintxt, const Ctxt& ciphertxt),解密
  • long skEncrypt(Ctxt& ctxt, const zzX& ptxt, long ptxtSpace, long skIdx),对称加密

此外,double RLWE(DoubleCRT& c0, DoubleCRT& c1, const DoubleCRT& s, long p, NTL::ZZ* prgSeed = nullptr),产生随机的 RLWE 样本,返回的 double 是典范嵌入的无穷范数。

KeySwitching.h

有两种 KS 程序,其一是 [BV11] 的数字分解技术,其二是 [GHS12] 的模数扩展技术。这里的实现是 Hybrid 技巧。

定义了 class KeySwitch,它存储形如 W [ s ′ → s ] = ( a ⃗ , b ⃗ ) T ∈ R q 2 × t W[s' \to s]=(\vec a, \vec b)^T \in R_q^{2 \times t} W[ss]=(a ,b )TRq2×t 的 KSK 矩阵

  • SKHandle fromKeylong toKeyID,分别记录了 s ′ s' s s s s 的句柄/索引
  • NTL::ZZ prgSeedstd::vector<DoubleCRT> b,分别记录了 a ⃗ \vec a a (PRG seed)和 b ⃗ \vec b b

SecKey 内构造添加 KeySwitch 的自由函数,

  • void addAllMatrices(SecKey& sKey, long keyID = 0),生成所有映射 s ( X e ) ↦ s ( X ) , ∀ e ∈ Z m ∗ s(X^e) \mapsto s(X), \forall e \in \mathbb Z_m^* s(Xe)s(X),eZm 的 KSK 矩阵
  • void addFewMatrices(SecKey& sKey, long keyID = 0),生成少量映射的 KSK 矩阵,确保 s ( X e ) ↦ s ( X ) , ∀ e ∈ Z m ∗ s(X^e) \mapsto s(X), \forall e \in \mathbb Z_m^* s(Xe)s(X),eZm 都可以两步以内被线性化(看不懂)
  • void add1DMatrices(SecKey& sKey, long keyID = 0),生成全部形如 s ( X g ± i ) ↦ s ( X ) s(X^{g^{\large{\pm i}}}) \mapsto s(X) s(Xg±i)s(X) 映射的 KSK 矩阵,其中 Z m ∗ / ( p ) = ( g ) \mathbb Z_m^*/(p) = (g) Zm/(p)=(g) i < o r d ( g ) i<ord(g) i<ord(g)
  • void addFrbMatrices(SecKey& sKey, long keyID = 0),生成全部形如 s ( X p i ) ↦ s ( X ) s(X^{p^i}) \mapsto s(X) s(Xpi)s(X) 映射的 KSK 矩阵
  • void addMatrices4Network(SecKey& sKey, const PermNetwork& net, long keyID = 0),生成置换网络 net 所需的那些 KSK 矩阵

intraSlot.h

定义了一些关于 G F ( p d ) GF(p^d) GF(pd) 上明文槽的 Packing/Unpacking 功能,

  • void buildUnpackSlotEncoding(std::vector<zzX>& unpackSlotEncoding, const EncryptedArray& ea),预计算解包相关的信息
  • long repack(const CtPtrs& packed, const CtPtrs& unpacked, const EncryptedArray& ea),打包函数
  • long unpack(const CtPtrs& unpacked, const CtPtrs& packed, const EncryptedArray& ea, const std::vector<zzX>& unpackSlotEncoding),解包函数

recryption.h

BGV 存在 [HS15], [CH18] 两种自举算法。

定义了 class RecryptData,用于存储自举相关的数据

  • NTL::Vec<long> mvec,参数 m m m 的素分解
  • e, ePrime, skHwt,明文空间、私钥重量
  • alMod, ea,明文槽的结构和编码解码接口
  • init, setAE,配置自举数据

定义了 class ThinRecryptData : public RecryptData,专用于 “thin” bootstrapping 的自举数据。

recryption.cpp 中定义了一些没有在 recryption.h 内声明的自由函数,可能包含在其他的头文件里,

  • extractDigitsPackedextractDigitsThin,同态数字提取
  • void PubKey::reCrypt(Ctxt& ctxt)void PubKey::thinReCrypt(Ctxt& ctxt),单个密文的自举程序
  • void packedRecrypt(const CtPtrs& cPtrs, const std::vector<zzX>& unpackConsts, const EncryptedArray& ea),利用 repack, unpackCtPtrs 中的每 deg ⁡ d \deg d degd 个密文打包在一起,批量自举

binaryArith.h

binaryArith.cpp 中实现了 class DAGnodeclass AddDAG,用于存储管理布尔加法中的进位信息(同态乘法)。

对于 CtPtrs 对象(加密布尔值的密文列表的指针),定义了一些布尔运算,

  • void binaryCond(CtPtrs& output, const Ctxt& cond, const CtPtrs& trueValue, const CtPtrs& falseValue),根据控制位 cond(在明文槽中)确定 output 各个槽的数值(挑选 trueValuefalseValue),也就是 CMux Gate 运算
  • void binaryMask(CtPtrs& binaryNums, const Ctxt& mask),根据掩码 mask(取值 0 / 1 0/1 0/1)将某些明文槽值为零
  • concatBinaryNums, splitBinaryNums,二进制数的级联和切分
  • leftBitwiseShift, bitwiseRotate,布尔电路上的移位运算
  • bitwiseXOR, bitwiseOr, bitwiseAnd, bitwiseNot,布尔电路上的逻辑运算
  • addTwoNumbers, negateBinary, subtractBinary, addManyNumbers, multTwoNumbers, fifteenOrLess4Four,布尔电路上的算术运算
  • void decryptBinaryNums(std::vector<long>& pNums, const CtPtrs& eNums, const SecKey& sKey, const EncryptedArray& ea, bool twosComplement = false, bool allSlots = true),解密二进制数的密文 eNums,获得各个槽的整数明文 pNums,参数 twosComplement 用于确定是无符号数(二进制)还是带符号数(二补码)
  • void packedRecrypt(const CtPtrs& a, const CtPtrs& b, std::vector<zzX>* unpackSlotEncoding),批量自举两个二进制数的密文

binaryCompare.h

binaryCompare.cpp 中定义了 runningSums, compProducts, compEqGt,然后用线性迭代布尔比较算法(这很慢吧)实现 compareTwoNumbersImplementation 函数。比较之前它会自动地执行 packedRecrypt,确保乘法深度足够支持比较电路。

定义了布尔比较电路,前者仅执行 comp,后者还执行了 swap,

  • void compareTwoNumbers(Ctxt& mu, Ctxt& ni, const CtPtrs& a, const CtPtrs& b, bool twosComplement = false, std::vector<zzX>* unpackSlotEncoding = nullptr),比较 a,b 大小关系,输出 m u = ( a > b ) mu=(a>b) mu=(a>b) n i = ( a < b ) ni=(a<b) ni=(a<b)
  • void compareTwoNumbers(CtPtrs& max, CtPtrs& min, Ctxt& mu, Ctxt& ni, const CtPtrs& a, const CtPtrs& b, bool twosComplement = false, std::vector<zzX>* unpackSlotEncoding = nullptr),比较 a,b 大小关系,额外输出 max ⁡ ( a , b ) \max(a,b) max(a,b) min ⁡ ( a , b ) \min(a,b) min(a,b),也就是 Swap 运算

multicore.h

用于多线程的加锁和同步,

  • std::atomic_long, std::atomic_ulong,原子的整数类型
  • std::mutex, std::lock_guard<std::mutex>,资源锁

helib::BGV

BGV 方案的 SIMD 技术,

  • 模数 p ≥ 2 p\ge 2 p2,Hensel Lifting 指数 r ≥ 1 r \ge 1 r1,分圆环的次数 m ∈ Z m \in \mathbb Z mZ
  • 明文空间:多项式环 A p r = Z p r [ X ] / ( Φ m ( X ) ) \mathbb A_{p^r} = \mathbb Z_{p^r}[X]/(\Phi_m(X)) Apr=Zpr[X]/(Φm(X))
  • 明文槽:多项式环 Z p r [ X ] / ( F i ( X ) ) \mathbb Z_{p^r}[X]/(F_i(X)) Zpr[X]/(Fi(X)),其中 Φ m = ∏ i F i ( m o d p r ) \Phi_m = \prod_i F_i \pmod{p^r} Φm=iFi(modpr) 是环 Z p r \mathbb Z_{p^r} Zpr 上的不可约分解

示例

代码示例

#include <helib/helib.h>

int main(){
	
	return 0;
}

测试

编写 CMakeLists.txt,编译执行

helib::CKKS

CKKS 方案的 SIMD 技术,

  • 参数 p ≥ 0 p \ge 0 p0 是(缩放)明文尾数的系数上界
  • 明文空间:多项式环 A Q = Z Q [ X ] / ( Φ m ( X ) ) \mathbb A_{Q} = \mathbb Z_{Q}[X]/(\Phi_m(X)) AQ=ZQ[X]/(Φm(X))
  • 明文槽:多项式环 Z Q [ X ] / ( X − ζ m i ) \mathbb Z_{Q}[X]/(X-\zeta_m^i) ZQ[X]/(Xζmi),其中 Φ m = ∏ i ( X − ζ m i ) \Phi_m = \prod_i (X-\zeta_m^i) Φm=i(Xζmi) 是域 C \mathbb C C 上的完全分解

示例

代码示例

#include <helib/helib.h>

int main(){
	
	return 0;
}

测试

猜你喜欢

转载自blog.csdn.net/weixin_44885334/article/details/135445255