2021SC@SDUSC-PALISADE(八)Evaluation中的乘法评估

2021SC@SDUSC

密文的乘法同态

由于密文的减法同态运算与加法同态运算类似,我们就不重复分析了,重点分析密文的乘法同态核心。

函数的申明,返回一个密文对象,输入两个密文对象作为同态操作数

template <class Element>
    // 返回一个密文对象,输入两个密文对象作为同态操作数
Ciphertext<Element> 
LPAlgorithmSHEBGVrns<Element>::EvalMultCore(
    ConstCiphertext<Element> ciphertext1,
    ConstCiphertext<Element> ciphertext2) const {

接着通过两个if语句限定乘法同态的适用范围:

  // 乘法同态操作的适用范围
  if (ciphertext1->GetElements()[0].GetFormat() == Format::COEFFICIENT ||
      ciphertext2->GetElements()[0].GetFormat() == Format::COEFFICIENT) {
    PALISADE_THROW(not_available_error,
                   "EvalMult cannot multiply in COEFFICIENT domain.");
  }

    // 两个密文的CRT等级不同也无法进行乘法同态
  if (ciphertext1->GetLevel() != ciphertext2->GetLevel()) {
    PALISADE_THROW(config_error,
                   "EvalMultCore cannot multiply ciphertexts with different "
                   "number of CRT components.");
  }

声明一个密文对象用于存放乘法同态的结果密文向量:

    //声明一个密文对象用于存放乘法同态的结果向量
  Ciphertext<Element> result = ciphertext1->CloneEmpty();

提取函数参数中的密文对象的密文向量

    //提取函数参数中的密文对象的蜜文向量
  const std::vector<Element> &cv1 = ciphertext1->GetElements();
  const std::vector<Element> &cv2 = ciphertext2->GetElements();

乘法结果的维数计算:计算乘法同态的过程是多项式乘法,多项式的每一项都要与乘法同态的另一个多项式的所有向相乘,再合并相同的维数的项,记两个密文多项式向量分别为c1、c2,所以结果的维数 = c1维数+c2维数-1(0维占据一个维数),因为c1的第0维与c2第2维的结果要与c1的第1维与c2第1维的结果储存在cResult的第2维,所以结果向量最小维数为0,最大的维数为c1.max+c2.max-1

  size_t cResultSize = cv1.size() + cv2.size() - 1;

我们声明一个密文向量 存放乘法同态的运算结果

  std::vector<Element> cvMult(cResultSize);

利用一个结果维数大小的bool数组来说明结果向量数组中某个维数是否第一次赋值

    // 标记结果向量数组的某个维数是否是第一次赋值
  bool isFirstAdd[cResultSize];
    // 填充默认值True
  std::fill_n(isFirstAdd, cResultSize, true);

同多项式乘法的过程,按照cv1与cv2的维数遍历,设当前计算的维数为n=i+j,如果cvMult[n]第一次赋值(isFirstAdd[n]=true),则直接赋值cvMult[i + j] = cv1[i] * cv2[j];,其他情况进行+=运算。

    // 按照cv1与cv2的维数遍历
  for (size_t i = 0; i < cv1.size(); i++) {
    for (size_t j = 0; j < cv2.size(); j++) {
        // 数组第一次赋值
      if (isFirstAdd[i + j] == true) {
          //进行乘法运算
        cvMult[i + j] = cv1[i] * cv2[j];
        isFirstAdd[i + j] = false;
      } else {
          // 数组已被赋过值
        cvMult[i + j] += cv1[i] * cv2[j];
      }
    }
  }

最后我们将运算结果保存在result密文对象中,返回它,函数结束。

 // 将结果向量保存在结果密文对象中
  result->SetElements(std::move(cvMult));

  result->SetDepth(ciphertext1->GetDepth() + ciphertext2->GetDepth());
  result->SetLevel(ciphertext1->GetLevel());

    // 返回密文对象
  return result;
}

完整代码如下:

template <class Element>
    // 返回一个密文对象,输入两个密文对象作为同态操作数
Ciphertext<Element> 
LPAlgorithmSHEBGVrns<Element>::EvalMultCore(
    ConstCiphertext<Element> ciphertext1,
    ConstCiphertext<Element> ciphertext2) const {
    // 乘法同态操作的适用范围
  if (ciphertext1->GetElements()[0].GetFormat() == Format::COEFFICIENT ||
      ciphertext2->GetElements()[0].GetFormat() == Format::COEFFICIENT) {
    PALISADE_THROW(not_available_error,
                   "EvalMult cannot multiply in COEFFICIENT domain.");
  }

    // 两个密文的CRT等级不同也无法进行乘法同态
  if (ciphertext1->GetLevel() != ciphertext2->GetLevel()) {
    PALISADE_THROW(config_error,
                   "EvalMultCore cannot multiply ciphertexts with different "
                   "number of CRT components.");
  }

    //声明一个密文对象用于存放乘法同态的结果向量
  Ciphertext<Element> result = ciphertext1->CloneEmpty();

    //提取函数参数中的密文对象的蜜文向量
  const std::vector<Element> &cv1 = ciphertext1->GetElements();
  const std::vector<Element> &cv2 = ciphertext2->GetElements();

    // 计算乘法同态的过程是多项式乘法,多项式的每一项都要与另一个多项式的所有向相乘,在合并相同的维数,所以结果的维数 = c1维数+c2维数-1
    // 因为c1的第0维与c2第2维的结果要与c1的第1维与c2第1维的结果储存在cResult的第2维,所以结果向量最小维数为0,最大的维数为c1.max+c2.max-1
  size_t cResultSize = cv1.size() + cv2.size() - 1;

    //声明一个密文向量 存放乘法同态的运算结果
  std::vector<Element> cvMult(cResultSize);

    // 标记结果向量数组的某个维数是否是第一次赋值
  bool isFirstAdd[cResultSize];
    // 填充默认值True
  std::fill_n(isFirstAdd, cResultSize, true);

    // 按照cv1与cv2的维数遍历
  for (size_t i = 0; i < cv1.size(); i++) {
    for (size_t j = 0; j < cv2.size(); j++) {
        // 数组第一次赋值
      if (isFirstAdd[i + j] == true) {
          //进行乘法运算
        cvMult[i + j] = cv1[i] * cv2[j];
        isFirstAdd[i + j] = false;
      } else {
          // 数组已被赋过值
        cvMult[i + j] += cv1[i] * cv2[j];
      }
    }
  }

    // 将结果向量保存在结果密文对象中
  result->SetElements(std::move(cvMult));

  result->SetDepth(ciphertext1->GetDepth() + ciphertext2->GetDepth());
  result->SetLevel(ciphertext1->GetLevel());

    // 返回密文对象
  return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sunburst7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值