Ejemplo n.º 1
0
// Adds several primes to the chain. If byNumber=true then totalSize specifies
// the number of primes to add. If byNumber=false then totalSize specifies the
// target total bitsize of all the added primes.
// The function returns the total bitsize of all the added primes.
double AddManyPrimes(FHEcontext& context, double totalSize,
                     bool byNumber, bool special)
{
    double nBits = 0.0;     // How many bits added so far
    double sizeSoFar = 0.0;
    if (!context.zMStar.getM() || context.zMStar.getM()>(1<<20))// sanity checks
        Error("AddManyPrimes: m undefined or larger than 2^20");

    if (ALT_CRT) {
        while (sizeSoFar < totalSize) {
            long p = context.AddFFTPrime(special);
            nBits += log((double)p);
            sizeSoFar = byNumber? (sizeSoFar+1.0) : nBits;
        }
    }
    else {
#ifdef NO_HALF_SIZE_PRIME
        long sizeBits = context.bitsPerLevel;
#else
        long sizeBits = 2*context.bitsPerLevel;
#endif
        if (special) {
            long numPrimes = ceil(totalSize/NTL_SP_NBITS);// how many special primes
            sizeBits = ceil(totalSize/numPrimes);         // what's the size of each
        }
        long twoM = 2 * context.zMStar.getM();

        if (sizeBits>NTL_SP_NBITS) sizeBits = NTL_SP_NBITS;
        long sizeBound = 1L << sizeBits;
        if (sizeBound < twoM*log2(twoM)*8) {
            sizeBits = ceil(log2(twoM*log2(twoM)))+3;
            sizeBound = 1L << sizeBits;
        }

        // make p-1 divisible by m*2^k for as large k as possible
        while (twoM < sizeBound/(sizeBits*2)) twoM *= 2;

        long bigP = sizeBound - (sizeBound%twoM) +1; // 1 mod 2m
        long p = bigP+twoM; // The twoM is subtracted in the AddPrime function

        // FIXME: The last prime could be smaller
        while (sizeSoFar < totalSize) {
            if ((p = context.AddPrime(p,-twoM,special))) { // found a prime
                nBits += log((double)p);
                sizeSoFar = byNumber? (sizeSoFar+1.0) : nBits;
            }
            else { // we ran out of primes, try a lower power of two
                twoM /= 2;
                assert(twoM > (long)context.zMStar.getM()); // can we go lower?
                p = bigP;
            }
        }
    }
    return nBits;
}
Ejemplo n.º 2
0
// Adds several primes to the chain. If byNumber=true then totalSize specifies
// the number of primes to add. If byNumber=false then totalSize specifies the
// target natural log all the added primes.
// Returns natural log of the product of all added primes.
double AddManyPrimes(FHEcontext& context, double totalSize, 
		     bool byNumber, bool special)
{
  if (!context.zMStar.getM() || context.zMStar.getM()>(1<<20))// sanity checks
    Error("AddManyPrimes: m undefined or larger than 2^20");
  // NOTE: Below we are ensured that 16m*log(m) << NTL_SP_BOUND

  double sizeLogSoFar = 0.0; // log of added primes so far
  double addedSoFar = 0.0;   // Either size or number, depending on 'byNumber'

#ifdef NO_HALF_SIZE_PRIME
  long sizeBits = context.bitsPerLevel;
#else
  long sizeBits = 2*context.bitsPerLevel;
#endif
  if (special) { // try to use similar size for all the special primes
    double totalBits = totalSize/log(2.0);
    long numPrimes = ceil(totalBits/NTL_SP_NBITS);// how many special primes
    sizeBits = 1+ceil(totalBits/numPrimes);       // what's the size of each
    // Added one so we don't undershoot our target
  }
  if (sizeBits>NTL_SP_NBITS) sizeBits = NTL_SP_NBITS;
  long sizeBound = 1L << sizeBits;

  // Make sure that you have enough primes such that p-1 is divisible by 2m
  long twoM = 2 * context.zMStar.getM();
  if (sizeBound < twoM*log2(twoM)*8) { // bound too small to have such primes
    sizeBits = ceil(log2(twoM*log2(twoM)))+3; // increase prime size-bound
    sizeBound = 1L << sizeBits;
  }

  // make p-1 divisible by m*2^k for as large k as possible
  // (not needed when m itself a power of two)

  if (context.zMStar.getM() & 1) // m is odd, so not power of two
    while (twoM < sizeBound/(sizeBits*2)) twoM *= 2;

  long bigP = sizeBound - (sizeBound%twoM) +1; // 1 mod 2m
  long p = bigP+twoM; // twoM is subtracted in the AddPrime function

  // FIXME: The last prime could sometimes be slightly smaller
  while (addedSoFar < totalSize) {
    if ((p = context.AddPrime(p,-twoM,special))) { // found a prime
      sizeLogSoFar += log((double)p);
      addedSoFar = byNumber? (addedSoFar+1.0) : sizeLogSoFar;
    }
    else { // we ran out of primes, try a lower power of two
      twoM /= 2;
      assert(twoM > (long)context.zMStar.getM()); // can we go lower?
      p = bigP;
    }
  }
  return sizeLogSoFar;
}
Ejemplo n.º 3
0
void buildModChain(FHEcontext &context, long nLevels, long nDgts)
{
#ifdef NO_HALF_SIZE_PRIME
    long nPrimes = nLevels;
#else
    long nPrimes = (nLevels+1)/2;
    // The first prime should be of half the size. The code below tries to find
    // a prime q0 of this size where q0-1 is divisible by 2^k * m for some k>1.
    // Then if the plaintext space is a power of two it tries to choose the
    // second prime q1 so that q0*q1 = 1 mod ptxtSpace. All the other primes are
    // chosen so that qi-1 is divisible by 2^k * m for as large k as possible.
    long twoM;
    if (ALT_CRT)
        twoM = 2;
    else
        twoM = 2 * context.zMStar.getM();

    long bound = (1L << (context.bitsPerLevel-1));
    while (twoM < bound/(2*context.bitsPerLevel))
        twoM *= 2; // divisible by 2^k * m  for a larger k

    bound = bound - (bound % twoM) +1; // = 1 mod 2m
    long q0 = context.AddPrime(bound, twoM, false, !ALT_CRT);
    // add next prime to chain

    assert(q0 != 0);
    nPrimes--;
#endif

    // Choose the next primes as large as possible
    if (nPrimes>0) AddPrimesByNumber(context, nPrimes);

    // calculate the size of the digits

    if (nDgts > nPrimes) nDgts = nPrimes; // sanity checks
    if (nDgts <= 0) nDgts = 1;
    context.digits.resize(nDgts); // allocate space

    IndexSet s1;
    double sizeSoFar = 0.0;
    double maxDigitSize = 0.0;
    if (nDgts>1) { // we break ciphetext into a few digits when key-switching
        double dsize = context.logOfProduct(context.ctxtPrimes)/nDgts; // estimate
        double target = dsize-(context.bitsPerLevel/3.0);
        long idx = context.ctxtPrimes.first();
        for (long i=0; i<nDgts-1; i++) { // compute next digit
            IndexSet s;
            while (idx <= context.ctxtPrimes.last() && (empty(s)||sizeSoFar<target)) {
                s.insert(idx);
                sizeSoFar += log((double)context.ithPrime(idx));
                idx = context.ctxtPrimes.next(idx);
            }
            assert (!empty(s));
            context.digits[i] = s;
            s1.insert(s);
            double thisDigitSize = context.logOfProduct(s);
            if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
            target += dsize;
        }
        IndexSet s = context.ctxtPrimes / s1; // all the remaining primes
        if (!empty(s)) {
            context.digits[nDgts-1] = s;
            double thisDigitSize = context.logOfProduct(s);
            if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
        }
        else { // If last digit is empty, remove it
            nDgts--;
            context.digits.resize(nDgts);
        }
    }
    else {
        maxDigitSize = context.logOfProduct(context.ctxtPrimes);
        context.digits[0] = context.ctxtPrimes;
    }

    // Add primes to the chain for the P factor of key-switching
    long p2r = (context.rcData.alMod)? context.rcData.alMod->getPPowR()
               : context.alMod.getPPowR();
    double sizeOfSpecialPrimes
        = maxDigitSize + log(nDgts/32.0)/2 + log(context.stdev *2)
          + log((double)p2r);

    AddPrimesBySize(context, sizeOfSpecialPrimes, true);
}
Ejemplo n.º 4
0
void buildModChain(FHEcontext &context, long nLevels, long nDgts,long extraBits)
{
#ifdef NO_HALF_SIZE_PRIME
  long nPrimes = nLevels;
#else
  long nPrimes = (nLevels+1)/2;
  // The first prime should be of half the size. The code below tries to find
  // a prime q0 of this size where q0-1 is divisible by 2^k * m for some k>1.

  long twoM = 2 * context.zMStar.getM();
  long bound = (1L << (context.bitsPerLevel-1));
  while (twoM < bound/(2*context.bitsPerLevel))
    twoM *= 2; // divisible by 2^k * m  for a larger k

  bound = bound - (bound % twoM) +1; // = 1 mod 2m
  long q0 = context.AddPrime(bound, twoM, false); 
  // add next prime to chain
  
  assert(q0 != 0);
  nPrimes--;
#endif

  // Choose the next primes as large as possible
  if (nPrimes>0) AddPrimesByNumber(context, nPrimes);

  // calculate the size of the digits

  if (nDgts > nPrimes) nDgts = nPrimes; // sanity checks
  if (nDgts <= 0) nDgts = 1;
  context.digits.resize(nDgts); // allocate space

  IndexSet s1;
  double sizeSoFar = 0.0;
  double maxDigitSize = 0.0;
  if (nDgts>1) { // we break ciphetext into a few digits when key-switching
    double dsize = context.logOfProduct(context.ctxtPrimes)/nDgts; // estimate

    // A hack: we break the current digit after the total size of all digits
    // so far "almost reaches" the next multiple of dsize, upto 1/3 of a level
    double target = dsize-(context.bitsPerLevel/3.0);
    long idx = context.ctxtPrimes.first();
    for (long i=0; i<nDgts-1; i++) { // set all digits but the last
      IndexSet s;
      while (idx <= context.ctxtPrimes.last() && (empty(s)||sizeSoFar<target)) {
        s.insert(idx);
	sizeSoFar += log((double)context.ithPrime(idx));
	idx = context.ctxtPrimes.next(idx);
      }
      assert (!empty(s));
      context.digits[i] = s;
      s1.insert(s);
      double thisDigitSize = context.logOfProduct(s);
      if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
      target += dsize;
    }
    // The ctxt primes that are left (if any) form the last digit
    IndexSet s = context.ctxtPrimes / s1;
    if (!empty(s)) {
      context.digits[nDgts-1] = s;
      double thisDigitSize = context.logOfProduct(s);
      if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
    }
    else { // If last digit is empty, remove it
      nDgts--;
      context.digits.resize(nDgts);
    }
  }
  else { // only one digit
    maxDigitSize = context.logOfProduct(context.ctxtPrimes);
    context.digits[0] = context.ctxtPrimes;
  }

  // Add special primes to the chain for the P factor of key-switching
  long p2r = context.alMod.getPPowR();
  double sizeOfSpecialPrimes
    = maxDigitSize + log(nDgts) + log(context.stdev *2)
      + log((double)p2r) + (extraBits*log(2.0));

  AddPrimesBySize(context, sizeOfSpecialPrimes, true);
}