This repository was archived by the owner on Jun 30, 2025. It is now read-only.
  
  
  
  
  
Description
When using encrypt inside a omp parallel for loop, the error ippMontExp: set Mont input error. is very likely to occur, especially when the plaintext is large, e.g., close to N.
Here is the simplest code to reproduce the problem.
int main()
{
	ipcl::KeyPair keyPair = ipcl::generateKeypair(2048);
	std::cout << "N=" << *keyPair.pub_key.getN() << std::endl;
	std::cout << "N^2=" << *keyPair.pub_key.getNSQ() << std::endl;
	std::vector<BigNumber> bignums;
	for (size_t i = 0; i < 100; i++)
	{
		bignums.push_back(BigNumber(uint32_t(i + 1)));
	}
	for (size_t t = 0; t < 100; t++)
	{
		std::cout << "Start to encrypt 100 BigNumbers ==== time " << t << std::endl;
		BigNumber N = *keyPair.pub_key.getN();
		BigNumber moded = N - bignums[t];
#pragma omp parallel for
		for (size_t i = 0; i < 100; i++)
		{
			keyPair.pub_key.encrypt(ipcl::PlainText(moded));
		}
		std::cout << "Encrypted 100 BigNumbers" << std::endl;
	}
} 
The error seems to be caused by the ippsMod_BN function, which somehow modifies the data of modulus (the m_nquare field) during its computation. Hence it is not thread-safe.
However, I notice that copying m_square in raw_encrypt probably fixes the problem.
std::vector<BigNumber> PublicKey::raw_encrypt(const std::vector<BigNumber>& pt,
                                              bool make_secure) const {
  std::size_t pt_size = pt.size();
  BigNumber nsq = *m_nsquare; // This code copies the data of m_nsquare
  std::vector<BigNumber> ct(pt_size);
  for (std::size_t i = 0; i < pt_size; i++)
    // ct[i] = (*m_n * pt[i] + 1) % (*m_nsquare);
    ct[i] = (*m_n * pt[i] + 1) % nsq;
  if (make_secure) applyObfuscator(ct);
  return ct;
}