2021SC@SDUSC-PALISADE decryption function Decrypt

Keywords: cryptology

2021SC@SDUSC

This section continues to analyze the decryption process of BGV. The specific implementation of the decryption process is mainly in bgvrns-impl.cpp.

1 CryptoContext in palisade

The core class of PALISADE is the CryptoContext class, which provides all PALISADE encryption functions. All objects used in the PALISADE implementation are created by the CryptoContext class. [1]

All operations of the PALISADE object must be performed on the same object belonging to the CryptoContext class. The process of encrypting plaintext to generate ciphertext is as follows:

The encryption process analyzed in the previous section belongs to this process. The CryptoContext of each encryption process is unique and is generated by scheme, element type, elementparams and encoding params. Therefore, if a person creates a CryptoContext with the same scheme, element type, elementparams and encoding params in front of two computers, the two cryptocontexts should be the same.

2 decryption

According to the analysis in the previous section, PALISADE has three built-in element types: Poly, NativePoly and DCRTPoly. The encryption process is only for the DCRTPoly element type, so the decryption process naturally only supports the DCRTPoly element type. The following is a description of the bgvrns-impl.cpp class that does not support elements of poly and NativePoly types:

template <>
DecryptResult LPAlgorithmBGVrns<Poly>::Decrypt(
    const LPPrivateKey<Poly> privateKey, ConstCiphertext<Poly> ciphertext,
    Poly *plaintext) const {
  NOPOLY
}

template <>
DecryptResult LPAlgorithmBGVrns<NativePoly>::Decrypt(
    const LPPrivateKey<NativePoly> privateKey,
    ConstCiphertext<NativePoly> ciphertext, NativePoly *plaintext) const {
  NONATIVEPOLY
}

NOPOLY, NONATIVEPOLY is the predefined error message at the beginning:

#define NOPOLY                                                                \
  std::string errMsg = "BGVrns does not support Poly. Use DCRTPoly instead."; \
  PALISADE_THROW(not_implemented_error, errMsg);

#define NONATIVEPOLY                                               \
  std::string errMsg =                                             \
      "BGVrns does not support NativePoly. Use DCRTPoly instead."; \
  PALISADE_THROW(not_implemented_error, errMsg);

Therefore, focus on the decryption process for DCRTPloy type. The decryption function is defined in about 900 lines. Before analyzing the source code, let's review the decryption process of PALISADE series articles (III) [2]:

In the public key generation step of PALISADE series (IV) [3], p k 0 + s ∗ p k 1 = t ∗ e pk_0+s*pk_1 = t*e pk0 + s * pk1 = t * e, the rest is the modulus multiplied by noise, a very small error, which can be ignored. This is our general decryption process. If you are unclear, you can review the PALISADE series (3)

The function definition and some variable declarations of the decryption function are as follows:

template<>
//Decryption function
DecryptResult LPAlgorithmBGVrns<DCRTPoly>::Decrypt(
    const LPPrivateKey<DCRTPoly> privateKey,//Pass in the private key, ciphertext encapsulation object, and a plaintext object as the decrypted plaintext
    ConstCiphertext<DCRTPoly> ciphertext, NativePoly *plaintext) const {
  const auto cryptoParams =
      std::static_pointer_cast<LPCryptoParametersBGVrns<DCRTPoly>>(
          ciphertext->GetCryptoParameters());//Get encryption parameters
  const NativeInteger t = cryptoParams->GetPlaintextModulus();//Get modulus in plaintext

  const std::vector<DCRTPoly> &cv = ciphertext->GetElements();//Gets the ciphertext vector in the ciphertext object
  const DCRTPoly &s = privateKey->GetPrivateElement();//Get private key element

  size_t sizeQl = cv[0].GetParams()->GetParams().size();
  size_t sizeQ = s.GetParams()->GetParams().size();

  size_t diffQl = sizeQ - sizeQl;

  auto scopy(s);//Copy private key
  scopy.DropLastElements(diffQl);

  DCRTPoly sPower(scopy);

  DCRTPoly b, ci;

The following is the specific decryption process:

 b = cv[0];//The first element of the ciphertext vector
 for (size_t i = 1; i < cv.size(); i++) {
    ci = cv[i];//Subsequent elements of ciphertext vector
    ci.SetFormat(Format::EVALUATION);

    b += sPower * ci;
    sPower *= scopy;
 }
 b.SetFormat(Format::COEFFICIENT);

The operation in the sixth line is the operation of the decrypted joint part:

Finally, we assign the decrypted ciphertext to the plaintext pointer passed in by the decryption function to realize the decryption process.

*plaintext = b.GetElementAtIndex(0).Mod(t);

return DecryptResult(plaintext->GetLength());

reference resources

[1]PALISADE Lattice Cryptography Library User Manual (v1.11.5)
[2]The same series of articles: PALISADE (III) BGV principle analysis and python implementation
[3]Same series of articles: PALISADE (IV) key generation KeyGen

Posted by tomd79 on Fri, 05 Nov 2021 16:04:07 -0700