Пример #1
0
// break *this into n digits,according to the primeSets in context.digits
void DoubleCRT::breakIntoDigits(vector<DoubleCRT>& digits, long n) const
{
  FHE_TIMER_START;
  IndexSet allPrimes = getIndexSet() | context.specialPrimes;
  assert(n <= (long)context.digits.size());

  digits.resize(n, DoubleCRT(context, IndexSet::emptySet()));
  if (dryRun) return;

  for (long i=0; i<(long)digits.size(); i++) {
    digits[i]=*this;
    IndexSet notInDigit = digits[i].getIndexSet()/context.digits[i];
    digits[i].removePrimes(notInDigit); // reduce modulo the digit primes
  }
  
  for (long i=0; i<(long)digits.size(); i++) {
    IndexSet notInDigit = allPrimes / digits[i].getIndexSet();
    digits[i].addPrimes(notInDigit); // add back all the primes

    // subtract this digits from all the others, then divide by pi
    ZZ pi = context.productOfPrimes(context.digits[i]);
    for (long j=i+1; j<(long)digits.size(); j++) {
      digits[j].Sub(digits[i], /*matchIndexSets=*/false);
      digits[j] /= pi;
    }
  }
#if 0
  dgts.resize(n, DoubleCRT(context, IndexSet::emptySet()));
  for (long i=0; i<n; i++) // copy only the primes for this digit
    dgts[i].partialCopy(*this, context.digits[i]);

  IndexSet allPrimes = getIndexSet() | context.specialPrimes;
  for (long i=0; i<n; i++) {
    IndexSet notInDigit = allPrimes / dgts[i].getIndexSet();
    dgts[i].addPrimes(notInDigit); // add back all the primes

    // subtract this digits from all the others, then divide by pi
    ZZ pi = context.productOfPrimes(context.digits[i]);
    for (long j=i+1; j<n; j++) {
      dgts[j].Sub(dgts[i], /*matchIndexSets=*/false);
      dgts[j] /= pi;
    }
  }
#endif
  FHE_TIMER_STOP;
}
Пример #2
0
// Used in lieu of istream& operator>>(istream& str, KeySwitch& matrix)
void KeySwitch::readMatrix(istream& str, const FHEcontext& context)
{
  //  cerr << "KeySwitch[";
  seekPastChar(str,'['); // defined in NumbTh.cpp
  str >> fromKey;
  str >> toKeyID;
  str >> ptxtSpace;

  long nDigits;
  str >> nDigits;
  b.resize(nDigits, DoubleCRT(context, IndexSet::emptySet()));
  for (long i=0; i<nDigits; i++)
    str >> b[i];
  str >> prgSeed;
  seekPastChar(str,']');
  //  cerr << "]";
}
Пример #3
0
void KeySwitch::verify(FHESecKey& sk) 
{
  long fromSPower = fromKey.getPowerOfS();
  long fromXPower = fromKey.getPowerOfX();
  long fromIdx = fromKey.getSecretKeyID(); 
  long toIdx = toKeyID;
  long p = ptxtSpace;
  long n = b.size();

  cout << "KeySwitch::verify\n";
  cout << "fromS = " << fromSPower 
       << " fromX = " << fromXPower 
       << " fromIdx = " << fromIdx 
       << " toIdx = " << toIdx 
       << " p = " << p 
       << " n = " << n 
       << "\n";


  if (fromSPower != 1 || fromXPower != 1 || (fromIdx == toIdx) || n == 0) {
    cout << "KeySwitch::verify: these parameters not checkable\n";
    return;
  }

  const FHEcontext& context = b[0].getContext();

  // we don't store the context in the ks matrix, so let's
  // check that they are consistent

  for (long i = 0; i < n; i++) {
    if (&context != &(b[i].getContext()))
      cout << "KeySwitch::verify: bad context " << i << "\n";
  }

  cout << "context.ctxtPrimes = " << context.ctxtPrimes << "\n";
  cout << "context.specialPrimes = " << context.specialPrimes << "\n";

  IndexSet allPrimes = context.ctxtPrimes | context.specialPrimes;

  cout << "digits: ";
  for (long i = 0; i < n; i++) 
    cout << context.digits[i] << " ";
  cout << "\n";

  cout << "IndexSets of b: ";
  for (long i = 0; i < n; i++) 
    cout << b[i].getMap().getIndexSet() << " ";
  cout << "\n";

  // VJS: suspicious shadowing of fromKey, toKey
  const DoubleCRT& _fromKey = sk.sKeys.at(fromIdx);
  const DoubleCRT& _toKey = sk.sKeys.at(toIdx);

  cout << "IndexSet of fromKey: " << _fromKey.getMap().getIndexSet() << "\n";
  cout << "IndexSet of toKey: " << _toKey.getMap().getIndexSet() << "\n";

  vector<DoubleCRT> a;
  a.resize(n, DoubleCRT(context, allPrimes)); // defined modulo all primes

  { RandomState state;

    SetSeed(prgSeed);
    for (long i = 0; i < n; i++)
      a[i].randomize();

  } // the RandomState destructor "restores the state" (see NumbTh.h)

  vector<ZZX> A, B;

  A.resize(n);
  B.resize(n);

  for (long i = 0; i < n; i++) {
    a[i].toPoly(A[i]);
    b[i].toPoly(B[i]);
  }

  ZZX FromKey, ToKey;
  _fromKey.toPoly(FromKey, allPrimes);
  _toKey.toPoly(ToKey, allPrimes);

  ZZ Q = context.productOfPrimes(allPrimes);
  ZZ prod = context.productOfPrimes(context.specialPrimes);
  ZZX C, D;
  ZZX PhimX = context.zMStar.getPhimX();

  long nb = 0;
  for (long i = 0; i < n; i++) {
    C = (B[i] - FromKey*prod + ToKey*A[i]) % PhimX;
    PolyRed(C, Q);
    if (!divide(D, C, p)) {
      cout << "*** not divisible by p at " << i << "\n";
    }
    else {
      for (long j = 0; j <= deg(D); j++)
         if (NumBits(coeff(D, j)) > nb) nb = NumBits(coeff(D, j));
    }
    prod *= context.productOfPrimes(context.digits[i]);
  }

  cout << "error ratio: " << ((double) nb)/((double) NumBits(Q)) << "\n";
}