HElib

摘要:
HElib是一个基于C++语言的同态加密开源软件库。底层依赖于NTL数论库和GMP多精度库的实现。主要开发人员是IBM的Halevi。最新版本为1.0.2。它实现了支持“引导”的BGV方案和基于近似数字的CKKS方案。HElib在上述原始方案中引入了许多优化来加快同态运算,包括Smart Vercauten密文打包技术和Gentry Halevi Smart优化,这提高了算法的整体运算效率。这样,您可以移动HElib库,但不能依赖它的依赖项,因为它们是绝对路径。请注意,如果NTL不是作为共享库构建的,则构建HElib将

什么是HElib?

HElib是一个基于C++语言的同态加密开源软件库,底层依赖于NTL数论运算库GMP多精度运算库实现,主要开发者为IBM的Halevi,目前最新版本为1.0.2,实现了支持“Bootstrapping”的BGV方案和基于近似数的CKKS方案。 HElib在上述原始方案中引入了许多优化以加速同态运算,包括Smart-Vercauteren密文打包技术和Gentry-Halevi-Smart优化,提升了算法的整体运行效率。

HElib提供了一种“同态加密汇编语言”,支持“set”、“add”、“multiply”、“shift”等基本操作指令,此外还提供了自动噪声管理、改进的“Bootstrapping”方法、多线程等功能。

HElib的github主页:https://github.com/homenc/HElib 

相关论文:Halevi S , Shoup V . Algorithms in HElib[J]. Lecture Notes in Computer Science, 2014, 8616:554-571.

如何安装?

//CentOS 8安装HElib

##一般先决条件

GNU make

//-GNU make> = 3.82

yum install make

HElib第1张

pthreads

什么是Pthreads?

参考:链接 

git

//-git> = 1.8.3(需要构建和运行HElib测试套件)

yum install git

HElib第2张

** Linux环境:**

g ++

// -g ++> = 7.3.1

yum install gcc-c++

HElib第3张

cmake

// -cmake> = 3.10.2

yum install cmake

HElib第4张

第一种方法

自动下载并构建GMP和NTL依赖关系并打包可重定位文件夹中的库

此选项将HElib及其依赖项(NTL和GMP)捆绑在一个目录中,然后可以在系统上自由移动。 NTL和GMP将自动获取和编译。 它可以全局安装(即在/ usr / local下),如果未指定CMAKE_INSTALL_PREFIX,这是默认选项,但是由于要覆盖现有版本的NTL,GMP或HElib,因此应谨慎操作。在这种情况下,还需要另外两个前提条件:

m4

什么是m4?

m4是一个宏处理器,将输入拷贝到输出,同时将宏展开。宏可以是内嵌的,也可以是用户定义的,它还有一些内建函数,可以引用文件、执行命令和计算等。m4既可以作为编译器的前端,也可以单独作为一个宏处理器。

更多:链接

//  -m4> = 1.4.16

yum install m4

HElib第5张

patchelf

什么是patchelf ?

patchelf 是一个用来修改elf格式的动态库和可执行程序的小工具,可以修改动态链接库的库名字,以及链接库的RPATH。

更多:链接

//  -patchelf> = 0.9(如果在Linux上构建)

yum install patchelf

HElib第6张

PS:一般用云服务器的话,镜像里没有 patchelf 的话,会自动去github上下载

如果用的是服务器测试的话,一般是yum 不了patchelf的,所以请采用其他方式安装

参考:链接

开始1

1、下载

wget https://github.com/homenc/HElib/archive/v2.1.0.tar.gz

链接 

2、解压

tar -zxvf v2.1.0.tar.gz

HElib第7张

3、构建目录

mv HElib-2.1.0/ HElib
cd HElib
mkdir build
cd build

4、运行cmake

cmake -DPACKAGE_BUILD=ON -DCMAKE_INSTALL_PREFIX=/home/alice/helib_install .. 

PS:运行cmake配置步骤,指定要构建软件包(通过-DPACKAGE_BUILD = ON)并说出您希望安装到的位置,例如,要在`/home/alice/helib_install`中安装

可以在此处指定其他选项,例如使用以下命令启用HElib测试 -DENABLE_TEST = ON

5、编译

编译,并指定可选数量的线程(在此示例中为16),其输出将在可重定位文件夹“ helib_pack”中

make -j16

HElib第8张

PS:1核 2GB 20Mbps 的服务器,CPU直接100%,需要稍微高点的配置。或者输入小的进程数,例如: make -j5

1核 4GB 20Mbps的服务器make时:

HElib第9张

6、可选

(1)如果步骤2是通过-DENABLE_TEST = ON执行的,则HElib测试可以运行如下: 

ctest

可以在以下位置找到详细的HElib特定测试日志 :`Testing / Temporary / LastTest.log`

(2)运行安装步骤,将文件夹“ helib_pack”复制到 :$ {CMAKE_INSTALL_PREFIX}(在此示例中为/home/alice/helib_install

make install

当然,如果将“ CMAKE_INSTALL_PREFIX”保留为默认的“ /usr /local”,或者其他系统范围的路径,步骤6(2)可能需要`sudo`特权

默认按上面安装的流程,此时已安装完毕:

1、解压后的目录:

HElib第10张

examples:里面有三个工程项目,稍后在下面可以演示

tests:里面有很多小例子,均引用了该库,后期会运行演示

2、安装目录

/home/alice/helib_install/helib_pack

HElib第11张

所有的头文件都在 include

第二种方法

MacOS10.15下安装HElib库

HElib第12张

安装并在系统中可用的依赖项

此选项涉及自行构建HElib,并链接到系统上预先存在的依赖项(NTL和GMP)。这样,可以移动HElib库,但不能依赖其依赖项(NTL和GMP),因为它们是绝对路径。对于此选项,您必须自己构建GMP> = 6.0.0NTL> = 11.4.3
在整个安装选项中,都假定将环境变量$ GMPDIR和$ NTLDIR设置为分别指向GMP和NTL的安装目录。请注意,如果从软件包构建更改为库构建,则更安全使用一个干净的构建目录

GMP 

GMP多精度运算库,许多发行版都预装有GMP。如果没有,您可以将GMP安装为如下:

1、下载,确保版本GMP> = 6.0.0

链接

2、解压缩并cd到gmp目录

3、GMP以标准的unix方式编译

./configure
make
sudo make install    

默认情况下,这会将GMP安装到`/ usr / local`中 

NTL

NTL数论运算库,您可以按如下方式安装NTL:

1、下载,确保版本NTL> = 11.4.3

链接

2、解压缩并cd进入目录,例如`ntl-11.4.3 / src`
3、以标准的Unix方式配置,构建和安装NTL(但请记住指定以下标志以进行“配置”):

./configure NTL_GMP_LIP=on SHARED=on  NTL_THREADS=on NTL_THREAD_BOOST=on

make

sudo make install

这应该将NTL安装到`/usr/local`中

注意:如果要链接到非系统GMP,请将`GMP_PREFIX = <path / to / gmp>`传递给 `/configure`步骤

参数介绍

通用:

-`BUILD_SHARED = ON / OFF`(默认为`OFF`):构建为共享库。请注意,如果未将NTL构建为共享库,则构建HElib(无论“ BUILD_SHARED”如何)都将失败。 NTL的默认值是静态库,要在共享库中构建NTL,请在步骤1中使用`./configure SHARED = on`。

-`CMAKE_BUILD_TYPE` :(默认值为`RelWithDebInfo`):选择构建类型,选项包括:`Debug`,`RelWithDebInfo`,`Release`,`MinSizeRel`。

-`CMAKE_INSTALL_PREFIX`:HElib的所需安装目录。

-`ENABLE_TEST = ON / OFF`(默认为`OFF`):启用测试构建。这将包括针对Google测试框架稳定版本(googletest v1.10.0)的自动下载步骤。

-`ENABLE_THREADS = ON / OFF`(默认为`ON`):启用线程支持。当且仅当NTL是使用`NTL_THREADS = ON`构建的时,此选项才必须打开。

-`PEDANTIC_BUILD = ON / OFF`(默认为`ON`):使用`-Wall -Wpedantic -Wextra
  -Werror`在构建期间。

-`HELIB_DEBUG = ON / OFF`(默认为`OFF`):构建HElib时激活调试模块(通过定义`HELIB_DEBUG`宏)。当调试模块处于活动状态时,这会生成用于调试目的的其他信息。
  当使用cmake时,`HELIB_DEBUG`会传播到使用HElib的程序中。启用此功能后,使用HElib的程序将在配置过程中生成警告。这是为了提醒用户,如果未正确初始化调试模块,则可能会导致诸如“ sigsegv”之类的问题。

方法1:

-`PACKAGE_DIR`:软件包内部版本的安装位置。默认为`$ {CMAKE_INSTALL_PREFIX} / helib_pack`。
-`FETCH_GMP`:是否获取和构建GMP。默认为ON。如果设置为“ OFF”,则应该存在系统安装的GMP库,或者“ GMP_DIR”应指向有效的GMP前缀。
-`GMP_DIR`:GMP库的前缀。如果`FETCH_GMP = ON`被忽略

方法2:

- `GMP_DIR`: Prefix of the GMP library.
- `NTL_DIR`: Prefix of the NTL library.

第三种方法

采用Docker容器安装,请参考:FHE-Toolkit 安装

如何使用?

在项目中使用HElib

前提

在方法1或方法2中运行“ make install”后,可以在lib中找到要链接的必需共享库文件,并在 include 中找到头文件【我这里是 /home/alice/helib_install/helib_pack/include

例子的使用参考:examples/README.md

examples

1、介绍

`examples'目录包含教程和独立的示例程序表示各种API以及使用HElib的简单用例。

2、提供了什么

[tutorials]要涵盖CKKS方案,并包含8个记录在案的示例从基本操作到更复杂的序列化。

提供的示例程序使用BGV方案,包括:

-[BGV_binary_arithmetic](二进制算法)

-[BGV_country_db_lookup](BGV国家数据库查找)

-[BGV_packed_arithmetic](BGV压缩算法)

HElib第13张

3、安装

要编译示例,您必须在系统上已经安装了HElib。这个过程是纯CMake的。首先,创建一个构建目录并移入该目录。在“ examples / build”中运行CMake,

mkdir build
cd build
cmake -Dhelib_DIR=/share/cmake/helib  ..

PS:我这里的目录不是 /share/cmake/helib,而是 /home/alice/helib_install/helib_pack/share/cmake/helib 故应该:

cmake -Dhelib_DIR=/home/alice/helib_install/helib_pack/share/cmake/helib  ..

4、编译

例如 BGV_country_db_lookup,进入 BGV_country_db_lookup 目录

cd BGV_country_db_lookup
make -j6

HElib第14张

100%,显示编译完成,下面可以运行试试看

5、运行

进入/bin

cd ../bin
./BGV_country_db_lookup

HElib第15张

此时应该会报错,大概的意思就是没有找到 countries_dataset.csv 文件,现在要将该文件复制到该位置即可,文件位置在:examples/BGV_country_db_lookup
HElib第16张

cp countries_dataset.csv ../bin

再次运行即可

HElib第17张

其他两个例子也如此!

examples/tests

1、示例的所有测试均以bats(bash的测试框架)编写,并且需要bats-core。
2、请注意,测试要求示例已在build目录中成功编译并且可在build / bin中使用。 要运行测试,只需在examples / tests目录中执行脚本即可。
3、要运行所有测试,请键入以下命令。 (可选)-j标志可以使用线程来并行化测试。 注意,这需要与GNU并行,请参阅bats文档以获取更多信息。

前提安装:bats

举例运行:

cd  test
bats BGV_binary_arithmetic.bats 

有报错,暂时不知道咋回事!

HElib第18张

examples/tutorial

1、在examples目录下

make 

HElib第19张

2、在bin下执行

cd  ../bin

例如:01_ckks_basics

/* Copyright (C) 2020-2021 IBM Corp.
 * This program is Licensed under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *   http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. See accompanying LICENSE file.
 */

// In the CKKS encryption scheme, plaintexts are vectors of real or complex
// numbers.  The length, n, of these vectors is determined by the choice of
// parameters, as discussed below.  We often refer to the components of these
// vectors as "slots", which are indexed 0, ..., n-1.  We can add, subtract, or
// multiply two ciphertexts, and the corresponding operations are carried out
// slot by slot.  This is sometimes referred to as a "SIMD operation" (SIMD
// means Single Instruction Multiple Data), since we can effectively perform
// the same scalar operation in parallel on all n slots.

#include <helib/helib.h>

using namespace std;
using namespace helib;

int main(int argc, char* argv[])
{
  // To get started, we need to choose some parameters.  This is done by
  // initializing a Context object.  Since there are a lot of parameters, many
  // of them optional, HElib provides a "builder pattern" than lets you provide
  // these parameters "by name".

  Context context =

      // initialize a Context object using the builder pattern
      ContextBuilder<CKKS>()

          .m(16 * 1024)
          // m is the "cyclotomic index". For CKKS, m must be a power of 2.  As
          // m increases, you get more security and more slots, but the
          // performance degrades and the size of a ciphertext increases. See
          // table below for more information.

          .bits(119)
          // bits specifies the number of bits in the "ciphertext modulus".  As
          // bits increases, you get less security, but you can perform deeper
          // homomorphic computations; in addition, the size of a ciphertext
          // increases.  See table below for more information. Also see
          // 02_depth.cpp for more information about how depth and bits are
          // related.

          .precision(20)
          // precision specifies the number of bits of precision when data is
          // encoded, encrypted, or decrypted.  More precisely, each of these
          // operations are designed to add an error term of at most
          // 2^{-precision} to each slot.  As precision increases, the allowed
          // depth of homomorphic computations decreases (but security and
          // performance are not affected).  It is not recommended to use
          // precision greater than about 40 or so.

          .c(2)
          // c specifies the number of columns in key-switching matrices.  Yes,
          // it sounds very technical, and it is.  However, all you have to know
          // about this parameter is that as c increases, you get a little more
          // security, but performance degrades and the memory requirement for
          // the public key increases. c must be at least 2 and it is not
          // recommended to set c higher than 8.  See table below for more
          // information.

          .build();
  // last step of the builder pattern

  // The following table lists settings of m, bits, and c that yield (at least)
  // 128-bit security.  It is highly recommended to only use settings from this
  // table.
  //
  //	m	bits	c
  //	16384	119	2
  //	32768	358	6
  //	32768	299	3
  //	32768	239	2
  //	65536	725	8
  //	65536	717	6
  //	65536	669	4
  //	65536	613	3
  //	65536	558	2
  //	131072	1445	8
  //	131072	1435	6
  //	131072	1387	5
  //	131072	1329	4
  //	131072	1255	3
  //	131072	1098	2
  //	262144	2940	8
  //	262144	2870	6
  //	262144	2763	5
  //	262144	2646	4
  //	262144	2511	3
  //	262144	2234	2

  // We can print out the estimated security level.
  // This estimate is based on the LWE security estimator.
  cout << "securityLevel=" << context.securityLevel() << "
";

  // Get the number of slots, n.  Note that for CKKS, we always have n=m/4.
  long n = context.getNSlots();

  // Construct a secret key. A secret key must be associated with a specific
  // Context, which is passed (by reference) to the constructor.  Programming
  // note: to avoid dangling pointers, the given Context object must not be
  // destroyed while any objects associated with it are still in use.
  SecKey secretKey(context);

  // Constructing a secret key does not actually do very much.  To actually
  // build a full-fledged secret key, we have to invoke the GenSecKey method.
  secretKey.GenSecKey();

  // In HElib, the SecKey class is actually a subclass if the PubKey class.  So
  // one way to initialize a public key object is like this:
  const PubKey& publicKey = secretKey;

  // TECHNICAL NOTE: Note the "&" in the declaration of publicKey. Since the
  // SecKey class is a subclass of PubKey, this particular PubKey object is
  // ultimately a SecKey object, and through the magic of C++ polymorphism,
  // encryptions done via publicKey will actually use the secret key, which has
  // certain advantages.  If one left out the "&", then encryptions done via
  // publicKey will NOT use the secret key.

  //===========================================================================

  // Let's encrypt something!
  // HElib provides a number of idioms for encrypting and decrypting.  We focus
  // on one particular idiom here.

  // We start by declaring a vector of length n, and we fill it with some
  // arbitrary numbers. Note that PI is defined by HElib.
  vector<double> v0(n);
  for (long i = 0; i < n; i++)
    v0[i] = sin(2.0 * PI * i / n);

  // Next, we load the plaintext vector v0 into a special type of container,
  // called a PtxtArray.  Note that a PtxtArray is associated with a Context
  // object, which is passed (by reference) to the constructor.
  PtxtArray p0(context, v0);

  // Note that many types of vectors can be loaded into a PtxtArray object
  // (including, vectors of int, long, double, or even complex<double>).  Also
  // note that constructing p0 and loading v0 into could have been done in two
  // separate steps:
  //   PtxtArray p0(context); p0.load(v0);

  // Next, we construct a ciphertext c0. A ciphertext is associated with a
  // PubKey object, which is passed (by reference) to the constructor.
  // Programming note: to avoid dangling pointers, the given PubKey object must
  // not be destroyed while any objects associated with it are still in use.
  Ctxt c0(publicKey);

  // Finally, we can encrypt p0 and store it in c0:
  p0.encrypt(c0);
  // Note that since a ciphertext is always associated with a public key, there
  // is no need to pass a public key as a separate parameter to the encryption
  // method.

  //===========================================================================

  // We next create another ciphertext c1, in a slightly different way.
  // First, we construct another PtxtArray p1:
  PtxtArray p1(context);

  // Next, we fill all n slots of p1 with random numbers in the interval [0,1]:
  p1.random();

  // Finally, we encrypt p1 and store it in c1, as above:
  Ctxt c1(publicKey);
  p1.encrypt(c1);

  //===========================================================================

  // We next create a ciphertext c2, in the same as was we did c1:
  PtxtArray p2(context);
  p2.random();
  Ctxt c2(publicKey);
  p2.encrypt(c2);

  //===========================================================================

  // Now we homorphically compute c3 = c0*c1 + c2*1.5:
  Ctxt c3 = c0;
  c3 *= c1;
  Ctxt c4 = c2;
  c4 *= 1.5;
  c3 += c4;

  // When this is done, if we denote the i-th slot of a ciphertext c by c[i],
  // then we have c3[i] = c0[i]*c1[i] + c2[i]*1.5 for i = 0..n-1.

  // More generally, for a Ctxt c, one can perform c *= d, c += d, or c -= d,
  // where d can be (among other things) a long, a double, or even a PtxtArray.

  //===========================================================================

  // Next we decrypt c3.
  // First, we construct a new PtxtArray pp3.
  PtxtArray pp3(context);

  // Next, we decrypt c3, storing the plaintext in p3:
  pp3.decrypt(c3, secretKey);

  // Finally, we store the PtxtArray p3 into a standard vector v3:
  vector<double> v3;
  pp3.store(v3);

  //===========================================================================

  // If we like, we can test the accuracy of the computation.
  // First, we perform the same computation directly on plaintexts.
  // The PtxtArray class allows this to be done very easily:
  PtxtArray p3 = p0;
  p3 *= p1;
  PtxtArray p4 = p2;
  p4 *= 1.5;
  p3 += p4;

  // Then, we compute the distance between p3 (computed on plaintexts) and pp3
  // (computed homomorphically on ciphertexts). This is computed as
  // max{ |p3[i]-pp3[i]| : i = 0..n-1 }
  double distance = Distance(p3, pp3);

  cout << "distance=" << distance << "
";

  return 0;
}

运行结果:

securityLevel=157.866
distance=2.82273e-06

其余的例子类似

参考

1、官方安装文档

2、官方例子

3、不懂球的2大业

免责声明:文章转载自《HElib》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇使用pageHelper遇到的问题数组的遍历下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Cmake命令之add_subdirectory介绍

命令格式 add_subdirectory (source_dir [binary_dir] [EXCLUDE_FROM_ALL])添加一个子目录并构建该子目录。 命令解析 source_dir必选参数。该参数指定一个子目录,子目录下应该包含CMakeLists.txt文件和代码文件。子目录可以是相对路径也可以是绝对路径,如果是相对路径,则是...

用cmake构建gtk程序

情况说明 先前已经在windows下基于GDI实现了一个简陋的imshow:基于GDI的imshow:使用stb_image读取图像并修正绘制。考虑跨平台,也考虑万一某天M$不让我们用盗版系统了,还是需要实现一个Linux/Mac下的imshow。 GTK相当于GDI在Linux下的一个替代。我用的是GTK-3 官方GTK文档的tutorial给出了一个能...

CMake安装(linux)

环境:CentOS6.5 1、下载网址: http://www.cmake.org/download/ (选择linux版本,编译安装) 2、安装 # tar zxvf cmake-3.2.1.tar.gz   # cd cmake-3.2.1   # ./bootstrap --prefix=/usr/local/cmake   # gmake  ...

Windows下QtCreator使用CMake编译GUI程序

一、前言 为什么要用 CMake 来构建 Qt 的项目呢?Qt 不是有 qmake 吗?这样,岂不是多此一举?其实,应用 CMake 来构建项目还是非常有必要的,特别是当你的项目涉及到很多第三方库的时候,CMake 的优势非常突出。 Qt5.15.2 在之前选择安装模块的时候,自动帮我们勾选了 CMake_64 模块,你也可以另外选择勾选 CMake_32...

Android Studio的串口通讯开发

基于android-serialport-api实现 前言RS232标准接口UARTRS232与UART转接下载 NDK 和构建工具创建支持 C/C++ 的新项目编译C/C++代码串口通讯原理关于校验位HexString与Bytes的转换参考 前言 软件代码写久了,总会对嵌入式开发感兴趣,因为软件的东西写来写去看不见摸不着,而嵌入式硬件开发,可以捣...

protobuf编译

win10   cmake   vs2017编译 protobuf编译 cmake Selecting Windows SDK version 10.0.17134.0 to target Windows 10.0.19042. The C compiler identification is MSVC 19.15.26732.1 The CXX com...