zoukankan      html  css  js  c++  java
  • 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
    

    pthreads

    什么是Pthreads?

    参考:链接 

    git

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

    yum install git
    

    ** Linux环境:**

    g ++

    // -g ++> = 7.3.1

    yum install gcc-c++

    cmake

    // -cmake> = 3.10.2

    yum install cmake
    

    第一种方法

    自动下载并构建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
    

    patchelf

    什么是patchelf ?

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

    更多:链接

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

    yum install patchelf
    

    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

    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
    

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

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

    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、解压后的目录:

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

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

    2、安装目录

    /home/alice/helib_install/helib_pack
    

    所有的头文件都在 include

    第二种方法

    MacOS10.15下安装HElib库

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

    此选项涉及自行构建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压缩算法)

    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
    

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

    5、运行

    进入/bin

    cd ../bin
    ./BGV_country_db_lookup

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

    cp countries_dataset.csv ../bin
    

    再次运行即可

    其他两个例子也如此!

    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 

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

    examples/tutorial

    1、在examples目录下

    make 

    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大业

    作者: Pam

    出处: https://www.cnblogs.com/pam-sh/>

    关于作者:网安在读

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 原文链接 如有问题, 可邮件(mir_soh@163.com)咨询.

  • 相关阅读:
    AJAX
    选择器
    断电原则
    radio为什么不能选择。急急急
    IBase<T>
    委托
    Log4Net
    博弈论 学习笔记
    解决You have new mail in /var/spool/mail/root提示
    Zookeeper分布式安装部署
  • 原文地址:https://www.cnblogs.com/pam-sh/p/14524581.html
Copyright © 2011-2022 走看看