参考文献:
- HElib 源码
- googletest 源码
- bats-core 源码
- [HS13] Halevi S, Shoup V. Design and implementation of a homomorphic-encryption library[J]. IBM Research (Manuscript), 2013, 6(12-15): 8-36.
- [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.
- [HS15] Halevi S, Shoup V. Bootstrapping for helib[J]. Journal of Cryptology, 2021, 34(1): 7.
- [HS18] Halevi S, Shoup V. Faster homomorphic linear transformations in HElib[C]//Annual International Cryptology Conference. Cham: Springer International Publishing, 2018: 93-120.
- [HS20] Halevi S, Shoup V. Design and implementation of HElib: a homomorphic encryption library[J]. Cryptology ePrint Archive, 2020.
- 安装 GMP、NTL、CTMalloc
- 全同态加密:BGV
- 全同态加密:CKKS
- Full-RNS BGV/BFV
- FHE 的槽置换:Benes Network
- Level FHE 的快速算法:Double-CRT & Dot Multiplication
- 基于插值的同态比较算法 & 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 CKKS
和 struct 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} Q0≈2nBits,KeySwitch 矩阵列数 c c c,明文空间特征 p p p,明文槽的度数 d d d 和个数 s s s,确定出参数 m m m 的大小。
定义了 struct Context::ModChainParams
,struct Context::BootStrapParams
,struct 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 zMStar
,PAlgebraMod alMod
,std::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.2⋅m, α = 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
,私有属性,绑定到某个上下文,记录了ctxtPrimes
和specialPrimes
信息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=dn−1dims[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 p∤m 的素数。群 ( 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,⋯,gi−1) 中拥有相同阶“ 的那些元素,群 ( 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^* T⊆Zm∗ 是商群 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:={
i∏giei⋅j∏hjej
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)=t∈T∏Ft(X)
易知 1 ∈ T 1 \in T 1∈T,首先确定任意的不可约因子设为 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 pjCubeSignature 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) t∈Zm∗/(p),后者Tidx[t]=i
是反过来的std::vector<long> zmsIdx, zmsRep
,私有属性,前者zmsIdx[t]=i
记录了 t ∈ Z m ∗ t \in \mathbb Z_m^* t∈Zm∗ 的次序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 ldouble 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]
的乘法阶(高阶立方cube
第i
维度的规模)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^* t∈Zm∗ 的索引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] Ft∈R[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,⋯,αl−1] 编码到 H ∈ R [ X ] / ( Φ m ( X ) ) H \in R[X]/(\Phi_m(X)) H∈R[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} Aprconst 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 PermIndepPrecomp
和 class 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:XjmodG↦L[j]modG,j=0,1,⋯,degG−1,也就是
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)modG↦∑j=0degG−1C[j]⋅h(Xpj)modG,我们称
C
是M
的线性化多项式(Linearized polynomials)
- 输入向量 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:XjmodG↦L[j]modG,j=0,1,⋯,degG−1,也就是
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())
,利用ea
将pa
编码void encrypt(Ctxt& ctxt, double mag = -1, OptLong prec = OptLong())
,利用ea
将pa
加密(Ctxt
携带属性PubKey
)void decrypt(const Ctxt& ctxt, const SecKey& sKey, OptLong prec = OptLong())
,利用ea
将pa
解密(额外输入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 p−2,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
- BGV方案,将
定义了 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^* k∈Zm∗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_BGV
和EncodedPtxt_CKKS
对象引用eptxt.resetBGV(), eptxt.resetCKKS()
,重置EncodedPtxt_BGV
和EncodedPtxt_CKKS
对象
定义了 FatEncodedPtxt_BGV
,class FatEncodedPtxt_CKKS
和 class 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 a⊕b=a+b−2ab 和 ( a ⊕ b ) ‾ = 1 − a − b + 2 a b \overline{(a \oplus b)}=1-a-b+2ab (a⊕b)=1−a−b+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)=1void smartAutomorph(long k)
,计算自同构,紧接着执行重线性化void frobeniusAutomorph(long j)
,也就是smartAutomorph(p^j mod m)
divideByP, multByP
,简单作用到密文上,使得明文模数分别变为 p r − 1 , r > 1 p^{r-1},r>1 pr−1,r>1 和 p r + 1 , r ≥ 1 p^{r+1},r\ge1 pr+1,r≥1multiplyBy, 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
,模切换过程,后者先Up
再Down
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} pr−j,但是这些密文的 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[s′→s]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=sGenSecKey, 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[s′→s]=(a,b)T∈Rq2×t 的 KSK 矩阵
SKHandle fromKey
和long toKeyID
,分别记录了 s ′ s' s′ 和 s s s 的句柄/索引NTL::ZZ prgSeed
和std::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),∀e∈Zm∗ 的 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),∀e∈Zm∗ 都可以两步以内被线性化(看不懂)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
内声明的自由函数,可能包含在其他的头文件里,
extractDigitsPacked
和extractDigitsThin
,同态数字提取void PubKey::reCrypt(Ctxt& ctxt)
和void PubKey::thinReCrypt(Ctxt& ctxt)
,单个密文的自举程序void packedRecrypt(const CtPtrs& cPtrs, const std::vector<zzX>& unpackConsts, const EncryptedArray& ea)
,利用repack, unpack
将CtPtrs
中的每 deg d \deg d degd 个密文打包在一起,批量自举
binaryArith.h
在 binaryArith.cpp
中实现了 class DAGnode
和 class AddDAG
,用于存储管理布尔加法中的进位信息(同态乘法)。
对于 CtPtrs
对象(加密布尔值的密文列表的指针),定义了一些布尔运算,
void binaryCond(CtPtrs& output, const Ctxt& cond, const CtPtrs& trueValue, const CtPtrs& falseValue)
,根据控制位cond
(在明文槽中)确定output
各个槽的数值(挑选trueValue
或falseValue
),也就是 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 p≥2,Hensel Lifting 指数 r ≥ 1 r \ge 1 r≥1,分圆环的次数 m ∈ Z m \in \mathbb Z m∈Z
- 明文空间:多项式环 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 p≥0 是(缩放)明文尾数的系数上界
- 明文空间:多项式环 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;
}