IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    HE-API项目简介

    nanxiao发表于 2017-02-24 08:58:32
    love 0

    HE-API提供一个统一的接口,屏蔽了底层使用的SHE library的细节,使对加密不是很了解的人也可以轻松掌握(代码在这里)。HE-API目前只支持HElib,通过使用不同的编译选项(FXPT,BINARY)来生成支持不同数据类型的库:helib.a.fxpt,helib.a.binary和helib.a.ulong。下面以testInteger函数为例,来分析如何使用:

    template <unsigned long nb_tests>
    int testInteger() {
      // Determine if the test should run
      #ifdef BINARY
      unsigned long run = HE::supports_bit_encryption;
      #else
      unsigned long run = HE::supports_unsigned_encryption;
      #endif
    
      if (!run) {
        return 0;
      }
    
      timing t;
    
      gmp_randclass prng(gmp_randinit_default);
    //  prng.seed(0);
      prng.seed(time(NULL)); // To set different seeds
    
      void* parameters = nullptr;
      void* sk = nullptr;
      void* pk = nullptr;
      void* evk = nullptr;
    
      // Init
      t.start();
      HE::init(&parameters);
      t.stop("Init");
    
      // Keygen
      t.start();
      HE::keygen(parameters, &sk, &pk, &evk);
      t.stop("Keygen");
      // HE::serialize_sk("sk.bin", sk);
      // std::cout << "serialized?" << std::endl;
    
      // Random messages
      unsigned long* messages1 = new unsigned long[nb_tests];
      unsigned long* messages2 = new unsigned long[nb_tests];
      for (unsigned long i = 0; i < nb_tests; i++) {
        messages1[i] =
            mpz_class(prng.get_z_range(HE::plaintext_modulus)).get_ui();
        messages2[i] =
            mpz_class(prng.get_z_range(HE::plaintext_modulus)).get_ui();
      }
    
      // Encrypt
      void** ciphertexts1 = new void* [nb_tests];
      void** ciphertexts2 = new void* [nb_tests];
      t.start();
      for (unsigned long i = 0; i < nb_tests; i++) {
        HE::encryptInteger(pk, &(ciphertexts1[i]), messages1[i]);
        HE::encryptInteger(pk, &(ciphertexts2[i]), messages2[i]);
      }
      t.stop("Encrypt Integer", nb_tests * 2);
    
      // Decrypt
      unsigned long* messages1_decrypted = new unsigned long[nb_tests];
      unsigned long* messages2_decrypted = new unsigned long[nb_tests];
      t.start();
      for (unsigned long i = 0; i < nb_tests; i++) {
        HE::decryptInteger(sk, pk, ciphertexts1[i], &(messages1_decrypted[i]));
        HE::decryptInteger(sk, pk, ciphertexts2[i], &(messages2_decrypted[i]));
      }
      t.stop("Decrypt Integer", nb_tests * 2);
    
      // Correctness of decryption
      for (unsigned long i = 0; i < nb_tests; i++) {
        assert(messages1[i] == messages1_decrypted[i]);
        assert(messages2[i] == messages2_decrypted[i]);
      }
    
      // Homomorphic additions
      unsigned long* messages_added = new unsigned long[nb_tests];
      for (unsigned long i = 0; i < nb_tests; i++) {
        messages_added[i] = (messages1[i] + messages2[i]) % HE::plaintext_modulus;
      }
      void** ciphertexts_added = new void* [nb_tests];
      t.start();
      for (unsigned long i = 0; i < nb_tests; i++) {
        HE::add(pk, evk, &(ciphertexts_added[i]), ciphertexts1[i], ciphertexts2[i]);
      }
      t.stop("Homomorphic Addition", nb_tests);
    
      // Correctness of addition
      unsigned long* messages_added_decrypted = new unsigned long[nb_tests];
      for (unsigned long i = 0; i < nb_tests; i++) {
        HE::decryptInteger(sk, pk, ciphertexts_added[i],
                         &(messages_added_decrypted[i]));
        assert(messages_added_decrypted[i] == messages_added[i]);
      }
    
      // Homomorphic multiplications
      unsigned long* messages_multiplied = new unsigned long[nb_tests];
      for (unsigned long i = 0; i < nb_tests; i++) {
        messages_multiplied[i] = (messages1[i] * messages2[i]) % HE::plaintext_modulus;
      }
      void** ciphertexts_multiplied = new void* [nb_tests];
      t.start();
      for (unsigned long i = 0; i < nb_tests; i++) {
        HE::mul(pk, evk, &(ciphertexts_multiplied[i]), ciphertexts1[i],
              ciphertexts2[i]);
      }
      t.stop("Homomorphic Multiplication", nb_tests);
    
      // Correctness of multiplication
      unsigned long* messages_multiplied_decrypted = new unsigned long[nb_tests];
      for (unsigned long i = 0; i < nb_tests; i++) {
        HE::decryptInteger(sk, pk, ciphertexts_multiplied[i],
                         &(messages_multiplied_decrypted[i]));
        assert(messages_multiplied_decrypted[i] == messages_multiplied[i]);
      }
    
      delete[] messages1;
      delete[] messages2;
      delete[] messages_added;
      delete[] messages_added_decrypted;
      delete[] messages_multiplied;
      delete[] messages_multiplied_decrypted;
    
      for(long i=0; i< nb_tests; i++)
      {
          HE::freeup_ciphertext(pk,ciphertexts1[i]);
          HE::freeup_ciphertext(pk,ciphertexts2[i]);
          HE::freeup_ciphertext(pk,ciphertexts_added[i]);
          HE::freeup_ciphertext(pk,ciphertexts_multiplied[i]);
      }
    
      delete[] ciphertexts1;
      delete[] ciphertexts2;
      delete[] ciphertexts_added;
      delete[] ciphertexts_multiplied;
    
      HE::freeup_keys(parameters,sk,pk,evk);
    
      return 0;
    }
    

    (1)HE-API使用了gmp项目:
    a)gmp_randclass类用来生成随机数:

    ......
    gmp_randclass prng(gmp_randinit_default);
    //  prng.seed(0);
    prng.seed(time(NULL)); // To set different seeds
    ......
    messages1[i] =
            mpz_class(prng.get_z_range(HE::plaintext_modulus)).get_ui();
    messages2[i] =
            mpz_class(prng.get_z_range(HE::plaintext_modulus)).get_ui();
    

    b)mpz_class用来表示整数。get_ui()返回mpz_class的最低位的unsigned long。以Binary为例,mpz_class(prng.get_z_range(HE::plaintext_modulus)).get_ui();随机返回0和1。

    (2)另外就是需要注意加法和乘法时的取模运算:

    ......
    messages_added[i] = (messages1[i] + messages2[i]) % HE::plaintext_modulus;
    ......
    messages_multiplied[i] = (messages1[i] * messages2[i]) % HE::plaintext_modulus;
    

    仍以Binary为例,此时PLAINTEXT_MODULUS的值为2,即要对2取模。操作数是1个bit,取值为0或1,加密结果对应的也是0或1。



沪ICP备19023445号-2号
友情链接