HElib:编译安装

参考文献:

  1. HElib 源码
  2. HEXL 源码
  3. googletest 源码
  4. bats-core 源码
  5. [HS13] Halevi S, Shoup V. Design and implementation of a homomorphic-encryption library[J]. IBM Research (Manuscript), 2013, 6(12-15): 8-36.
  6. [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.
  7. [HS15] Halevi S, Shoup V. Bootstrapping for helib[J]. Journal of Cryptology, 2021, 34(1): 7.
  8. [HS18] Halevi S, Shoup V. Faster homomorphic linear transformations in HElib[C]//Annual International Cryptology Conference. Cham: Springer International Publishing, 2018: 93-120.
  9. [HS20] Halevi S, Shoup V. Design and implementation of HElib: a homomorphic encryption library[J]. Cryptology ePrint Archive, 2020.
  10. 安装 GMP、NTL、CTMalloc
  11. 全同态加密:BGV
  12. 全同态加密:CKKS
  13. Full-RNS BGV/BFV
  14. FHE 的槽置换:Benes Network
  15. Level FHE 的快速算法:Double-CRT & Dot Multiplication
  16. 基于插值的同态比较算法 & 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

安装 Intel/hexl 硬件加速库(我的 Intel® Core™ i9-12900H 不支持 AVX512 指令集,反而 Intel® Core™ i9-11900H 是支持的,本机查看 cat /proc/cpuinfo),

git config --global url."https://hub.nuaa.cf/".insteadOf "https://github.com/" #首先换个源,git 总是连不上 github

git clone --recurse-submodules https://github.com/intel/hexl.git/

cd ./hexl

cmake -S . -B build #配置 makefile,它会连接 github 拉取一些 cpu-features 文件

cmake --build build #编译 hexl

sudo cmake --install build #安装位置 install_manifest.txt

假如你的 NTL 依赖于 gf2x,那么还需要修改下 src/CMakeLists.txt(否则出现未定义函数),添加如下的编译配置:

add_link_options(
  -lstdc++ -lm -lntl -pthread -lgf2x
)

find_package(gf2x)

......

target_link_libraries(helib gf2x)

正式编译,

mkdir build

cd ./build

cmake -DPACKAGE_BUILD=OFF -DENABLE_TEST=ON -DENABLE_THREADS=ON -DUSE_INTEL_HEXL=ON -DGMP_DIR="${GMPDIR}" -DNTL_DIR="${NTLDIR}" .. #开启一些选项,使用 hexl 需要关闭 PACKAGE_BUILD 选项

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] 解释了某些结构的设计原理。

在这里插入图片描述

Math Layer

NumbTh.h

实现了许多有用的数学函数:

  • mcMod, mcDiv,计算数学意义上的取模运算和除法运算(计算机实现并不正确)
  • long balRem(long a, long q),平衡的余数
  • long multOrd(long p, long m),乘法阶
  • ppsolve, ppInvert,求解方阵的方程组,求方阵的逆
  • double log2(const NTL::xdouble& x),底 2 的对数
  • void factorize(std::vector<long>& factors, long N),较小整数的因子分解
  • void pp_factorize(std::vector<long>& factors, long N),分解为素数幂
  • void phiN(long& phiN, std::vector<long>& facts, long N),欧拉函数
  • findGenerators,计算 Z m ∗ / ( p ) \mathbb Z_m^*/(p) Zm/(p) 的生成元以及它们的阶
  • FindPrimitiveRoot,本原单位根
  • long mobius(long n),莫比乌斯函数
  • NTL::ZZX Cyclotomic(long N),分圆环
  • NTL::ZZX makeIrredPoly(long p, long d),不可约多项式
  • long primroot(long N, long phiN),本原根
  • PolyRed, vecRed,取模
  • MulMod, balanced_MulMod,模乘
  • convert,一大堆不同数据类型之间的转换函数
  • long computeProd(const std::vector<long>& vec),连乘积
  • long is_in(long x, int* X, long sz),隶属问题
  • long argminmax(std::vector<T>& v),最大值、最小值
  • bool closeToOne(const NTL::xdouble& x, long p),是否落在 ( 1 − 1 / p , 1 + 1 / p ) (1-1/p,1+1/p) (11/p,1+1/p)
  • std::pair<long, long> rationalApprox(double x, long denomBound = 0),浮点数的有理数近似
  • void reverse(NTL::Vec<T>& v, long lo, long hi),就地的向量翻转
  • void rotate(NTL::Vec<T>& v, long k),就地的向量旋转
  • void killVec(std::vector<T>& vec),释放向量的内存
  • bool sameObject(const T1* p1, const T2* p2),检查两个输入是否是同一个对象
  • void ModComp(NTL::ZZX& res,const NTL::ZZX& g, const NTL::ZZX& h, const NTL::ZZX& f),多项式复合 g ( h ) ( m o d f ) g(h)\pmod f g(h)(modf)
  • long polyEvalMod(const NTL::ZZX& f, long x, long p),多项式求值 f ( x ) ( m o d p ) f(x) \pmod p f(x)(modp)
  • void interpolateMod(NTL::ZZX& poly, const NTL::vec_long& x, const NTL::vec_long& y, long p, long e = 1),拉格朗日插值
  • double Norm(const std::vector<T>& x),无穷范数
  • double Distance(const std::vector<T>& x, const std::vector<U>& y),无穷范数诱导的距离
  • bool approx_equal(const T& x, const U& y, double tolerance, double floor),近似相等
  • double NextPow2(double 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]

CModulus.h

文件 bluestein.hNumbTh.h 实现了 Bluestein-FFT/NTT 算法,它可以计算任意长度(不只是二的幂次)的卷积运算。渐进复杂度中的常数因子比常规 FFT/NTT 大了 3 3 3 倍。

这个算法的高级接口是 class Cmodulus,数据类型是 NTL::zz_pX(也就是 long

  • q, qinv, root, rInv, m_inv, zMStar,私有属性,记录相关参数
  • powers, powers_aux, Rb, ipowers, ipowers_aux, iRb,私有属性,用于辅助存储一些预计算数据
  • void FFT(NTL::vec_long& y, const zzX& x),正向 FFT/NTT 运算
  • void iFFT(NTL::zz_pX& x, const NTL::vec_long& y),逆向 FFT/NTT 运算

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:={ igie

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值