Example #1
0
ostream& operator<<(ostream& str, const FHEPubKey& pk)
{
  str << "[";
  writeContextBase(str, pk.getContext());

  // output the public encryption key itself
  str << pk.pubEncrKey << endl;

  // output skHwts in the same format as vec_long
  str << "[";
  for (long i=0; i<(long)pk.skHwts.size(); i++)
    str << pk.skHwts[i]<<" ";
  str << "]\n";

  // output the key-switching matrices
  str << pk.keySwitching.size() << endl;
  for (long i=0; i<(long)pk.keySwitching.size(); i++)
    str << pk.keySwitching[i] << endl;

  // output keySwitchMap in the same format as vec_vec_long
  str << "[";
  for (long i=0; i<(long)pk.keySwitchMap.size(); i++) {
    str << "[";
    for (long j=0; j<(long)pk.keySwitchMap[i].size(); j++)
      str << pk.keySwitchMap[i][j] << " ";
    str << "]\n ";
  }
  str << "]\n";

  str << pk.KS_strategy << "\n";

  // output the bootstrapping key, if any
  str << pk.recryptKeyID << " ";
  if (pk.recryptKeyID>=0) str << pk.recryptEkey << endl;
  return str << "]";
}
Example #2
0
int main(int argc, char *argv[]) 
{
  ArgMapping amap;

  long m=17;
  amap.arg("m", m, "cyclotomic index");
  amap.note("e.g., m=2047");

  long p=2;
  amap.arg("p", p, "plaintext base");

  long r=1;
  amap.arg("r", r,  "lifting");

  Vec<long> gens0;
  amap.arg("gens", gens0, "use specified vector of generators", NULL);
  amap.note("e.g., gens='[562 1871 751]'");

  Vec<long> ords0;
  amap.arg("ords", ords0, "use specified vector of orders", NULL);
  amap.note("e.g., ords='[4 2 -4]', negative means 'bad'");

  amap.parse(argc, argv);

  cout << "m = " << m << ", p = " << p <<  ", r = " << r << endl;

  vector<long> f;
  factorize(f,m);
  cout << "factoring "<<m<<" gives [";
  for (unsigned long i=0; i<f.size(); i++)
    cout << f[i] << " ";
  cout << "]\n";

  vector<long> gens1, ords1;
  convert(gens1, gens0);
  convert(ords1, ords0);

  PAlgebra al(m, p, gens1, ords1);
  al.printout();
  cout << "\n";

  PAlgebraMod almod(al, r);

  FHEcontext context(m, p, r);
  buildModChain(context, 5, 2);

  stringstream s1;
  writeContextBase(s1, context);
  s1 << context;

  string s2 = s1.str();

  cout << s2 << endl;

  stringstream s3(s2);

  unsigned long m1, p1, r1;
  vector<long> gens, ords;
  readContextBase(s3, m1, p1, r1, gens, ords);

  FHEcontext c1(m1, p1, r1, gens, ords);
  s3 >> c1;

  if (context == c1)
    cout << "equal\n";
  else
    cout << "not equal\n";

  return 0;
}
Example #3
0
// Testing the I/O of the important classes of the library
// (context, keys, ciphertexts).
int main(int argc, char *argv[])
{
  ArgMapping amap;

  long r=1;
  long p=2;
  long c = 2;
  long w = 64;
  long L = 5;
  long mm=0;
  amap.arg("p", p, "plaintext base");
  amap.arg("r", r,  "lifting");
  amap.arg("c", c, "number of columns in the key-switching matrices");
  amap.arg("m", mm, "cyclotomic index","{31,127,1023}");
  amap.parse(argc, argv);

  bool useTable = (mm==0 && p==2);
  long ptxtSpace = power_long(p,r);
  long numTests = useTable? N_TESTS : 1;

  std::unique_ptr<FHEcontext> contexts[numTests];
  std::unique_ptr<FHESecKey> sKeys[numTests];
  std::unique_ptr<Ctxt> ctxts[numTests];
  std::unique_ptr<EncryptedArray> eas[numTests];
  vector<ZZX> ptxts[numTests];

  // first loop: generate stuff and write it to cout

  // open file for writing
  {fstream keyFile("iotest.txt", fstream::out|fstream::trunc);
   assert(keyFile.is_open());
  for (long i=0; i<numTests; i++) {
    long m = (mm==0)? ms[i][1] : mm;

    cout << "Testing IO: m="<<m<<", p^r="<<p<<"^"<<r<<endl;

    Vec<long> mvec(INIT_SIZE,2);
    mvec[0] = ms[i][4];  mvec[1] = ms[i][5];
    vector<long> gens(2);
    gens[0] = ms[i][6];  gens[1] = ms[i][7];
    vector<long> ords(2);
    ords[0] = ms[i][8];  ords[1] = ms[i][9];

    if (useTable && gens[0]>0)
      contexts[i].reset(new FHEcontext(m, p, r, gens, ords));
    else
      contexts[i].reset(new FHEcontext(m, p, r));
    contexts[i]->zMStar.printout();

    buildModChain(*contexts[i], L, c);  // Set the modulus chain
    if (mm==0 && m==1023) contexts[i]->makeBootstrappable(mvec);

    // Output the FHEcontext to file
    writeContextBase(keyFile, *contexts[i]);
    writeContextBase(cout, *contexts[i]);
    keyFile << *contexts[i] << endl;

    sKeys[i].reset(new FHESecKey(*contexts[i]));
    const FHEPubKey& publicKey = *sKeys[i];
    sKeys[i]->GenSecKey(w,ptxtSpace); // A Hamming-weight-w secret key
    addSome1DMatrices(*sKeys[i]);// compute key-switching matrices that we need
    eas[i].reset(new EncryptedArray(*contexts[i]));

    long nslots = eas[i]->size();

    // Output the secret key to file, twice. Below we will have two copies
    // of most things.
    keyFile << *sKeys[i] << endl;;
    keyFile << *sKeys[i] << endl;;

    vector<ZZX> b;
    long p2r = eas[i]->getContext().alMod.getPPowR();
    ZZX poly = RandPoly(0,to_ZZ(p2r)); // choose a random constant polynomial
    eas[i]->decode(ptxts[i], poly);

    ctxts[i].reset(new Ctxt(publicKey));
    eas[i]->encrypt(*ctxts[i], publicKey, ptxts[i]);
    eas[i]->decrypt(*ctxts[i], *sKeys[i], b);
    assert(ptxts[i].size() == b.size());
    for (long j = 0; j < nslots; j++) assert (ptxts[i][j] == b[j]);

    // output the plaintext
    keyFile << "[ ";
    for (long j = 0; j < nslots; j++) keyFile << ptxts[i][j] << " ";
    keyFile << "]\n";

    eas[i]->encode(poly,ptxts[i]);
    keyFile << poly << endl;

    // Output the ciphertext to file
    keyFile << *ctxts[i] << endl;
    keyFile << *ctxts[i] << endl;
    cerr << "okay " << i << endl<< endl;
  }
  keyFile.close();}
  cerr << "so far, so good\n\n";

  // second loop: read from input and repeat the computation

  // open file for read
  {fstream keyFile("iotest.txt", fstream::in);
  for (long i=0; i<numTests; i++) {

    // Read context from file
    unsigned long m1, p1, r1;
    vector<long> gens, ords;
    readContextBase(keyFile, m1, p1, r1, gens, ords);
    FHEcontext tmpContext(m1, p1, r1, gens, ords);
    keyFile >> tmpContext;
    assert (*contexts[i] == tmpContext);
    cerr << i << ": context matches input\n";

    // We define some things below wrt *contexts[i], not tmpContext.
    // This is because the various operator== methods check equality of
    // references, not equality of the referenced FHEcontext objects.
    FHEcontext& context = *contexts[i];
    FHESecKey secretKey(context);
    FHESecKey secretKey2(tmpContext);
    const FHEPubKey& publicKey = secretKey;
    const FHEPubKey& publicKey2 = secretKey2;

    keyFile >> secretKey;
    keyFile >> secretKey2;
    assert(secretKey == *sKeys[i]);
    cerr << "   secret key matches input\n";

    EncryptedArray ea(context);
    EncryptedArray ea2(tmpContext);

    long nslots = ea.size();

    // Read the plaintext from file
    vector<ZZX> a;
    a.resize(nslots);
    assert(nslots == (long)ptxts[i].size());
    seekPastChar(keyFile, '['); // defined in NumbTh.cpp
    for (long j = 0; j < nslots; j++) {
      keyFile >> a[j];
      assert(a[j] == ptxts[i][j]);
    }
    seekPastChar(keyFile, ']');
    cerr << "   ptxt matches input\n";

    // Read the encoded plaintext from file
    ZZX poly1, poly2;
    keyFile >> poly1;
    eas[i]->encode(poly2,a);
    assert(poly1 == poly2);
    cerr << "   eas[i].encode(a)==poly1 okay\n";

    ea.encode(poly2,a);
    assert(poly1 == poly2);
    cerr << "   ea.encode(a)==poly1 okay\n";

    ea2.encode(poly2,a);
    assert(poly1 == poly2);
    cerr << "   ea2.encode(a)==poly1 okay\n";

    eas[i]->decode(a,poly1);
    assert(nslots == (long)a.size());
    for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]);
    cerr << "   eas[i].decode(poly1)==ptxts[i] okay\n";

    ea.decode(a,poly1);
    assert(nslots == (long)a.size());
    for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]);
    cerr << "   ea.decode(poly1)==ptxts[i] okay\n";

    ea2.decode(a,poly1);
    assert(nslots == (long)a.size());
    for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]);
    cerr << "   ea2.decode(poly1)==ptxts[i] okay\n";

    // Read ciperhtext from file
    Ctxt ctxt(publicKey);
    Ctxt ctxt2(publicKey2);
    keyFile >> ctxt;
    keyFile >> ctxt2;
    assert(ctxts[i]->equalsTo(ctxt,/*comparePkeys=*/false));
    cerr << "   ctxt matches input\n";

    sKeys[i]->Decrypt(poly2,*ctxts[i]);
    assert(poly1 == poly2);
    cerr << "   sKeys[i]->decrypt(*ctxts[i]) == poly1 okay\n";

    secretKey.Decrypt(poly2,*ctxts[i]);
    assert(poly1 == poly2);
    cerr << "   secretKey.decrypt(*ctxts[i]) == poly1 okay\n";

    secretKey.Decrypt(poly2,ctxt);
    assert(poly1 == poly2);
    cerr << "   secretKey.decrypt(ctxt) == poly1 okay\n";

    secretKey2.Decrypt(poly2,ctxt2);
    assert(poly1 == poly2);
    cerr << "   secretKey2.decrypt(ctxt2) == poly1 okay\n";

    eas[i]->decrypt(ctxt, *sKeys[i], a);
    assert(nslots == (long)a.size());
    for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]);
    cerr << "   eas[i].decrypt(ctxt, *sKeys[i])==ptxts[i] okay\n";

    ea.decrypt(ctxt, secretKey, a);
    assert(nslots == (long)a.size());
    for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]);
    cerr << "   ea.decrypt(ctxt, secretKey)==ptxts[i] okay\n";

    ea2.decrypt(ctxt2, secretKey2, a);
    assert(nslots == (long)a.size());
    for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]);
    cerr << "   ea2.decrypt(ctxt2, secretKey2)==ptxts[i] okay\n";

    cerr << "test "<<i<<" okay\n\n";
  }}
  unlink("iotest.txt"); // clean up before exiting
}
Example #4
0
int main(int argc, char *argv[]) 
{

  argmap_t argmap;
  argmap["m"] = "0"; 
  argmap["p"] = "2";
  argmap["r"] = "1";

  if (!parseArgs(argc, argv, argmap)) usage();

  unsigned long m = atoi(argmap["m"]);

  if (!m) usage();

  unsigned long p = atoi(argmap["p"]);

  unsigned long r = atoi(argmap["r"]);

  cout << "m = " << m << ", p = " << p <<  ", r = " << r << endl;

  vector<long> f;
  factorize(f,m);
  cout << "factoring "<<m<<" gives [";
  for (unsigned long i=0; i<f.size(); i++)
    cout << f[i] << " ";
  cout << "]\n";

  PAlgebra al(m, p);
  al.printout();
  cout << "\n";

  PAlgebraMod almod(al, r);
  almod.genMaskTable();

  FHEcontext context(m, p, r);
  buildModChain(context, 5, 2);

  stringstream s1;
  writeContextBase(s1, context);
  s1 << context;

  string s2 = s1.str();

  cout << s2 << endl;

  stringstream s3(s2);

  unsigned long m1, p1, r1;
  readContextBase(s3, m1, p1, r1);

  FHEcontext c1(m1, p1, r1);
  s3 >> c1;

  if (context == c1)
    cout << "equal\n";
  else
    cout << "not equal\n";

  return 0;

#if 0


  PAlgebraModTwo al2(al);
  PAlgebraMod2r al2r(r,al2);

  if (false) {
    long nslots = al.NSlots();
    long ngens = al.numOfGens();

    for (long i = 0; i < nslots; i++) {
      const int* v = al.dLog(al.ith_rep(i));
      cout << i << " ";
      for (long j = 0; j < ngens; j++)
         cout << v[j] << " ";
      cout << "\n";
      
    }

    return 0;
  }

  //  GF2X::HexOutput = 1; // compact hexadecimal printout
  //  cout << "Phi_m(X) = " << al.PhimX()  << endl;
  //  vec_GF2X Fs = al2.Factors();
  //  cout << "Factors = " << Fs << endl;

  //  GF2X Q = Fs[0];
  //  for (long i=1; i<Fs.length(); i++) Q *= Fs[i];
  //  cout << "mult of factors = " << Q << endl;

  GF2X G;          // G is the AES polynomial, G(X)= X^8 +X^4 +X^3 +X +1
  SetCoeff(G,8); SetCoeff(G,4); SetCoeff(G,3); SetCoeff(G,1); SetCoeff(G,0);
  //  GF2X G; SetCoeff(G,4); SetCoeff(G,1); SetCoeff(G,0); // X^4 +X +1
  //  cout << "G = " << G << ", deg(G)=" << deg(G) << endl;

  vector<GF2X> maps;
  al2.mapToSlots(maps, G);
  //  cout << "maps = [";
  //  for (unsigned long i=0; i<maps.size(); i++)
  //    cout << maps[i] << " ";
  //  cout << "]\n";


  GF2X X; SetX(X); // The polynomial X
  GF2X ptxt;       // plaintext has X in all the slots
  cout << "embedding X in plaintext slots... ";
  al2.embedInAllSlots(ptxt, X, maps);
  cout << "done\n";
  //  cout << "ptxt = " << ptxt << endl;

  // Debugging printout: p modulo all the factors
  //  vector<GF2X> crt;
  //  al2.CRT_decompose(crt,ptxt);
  //  cout << "ptxt mod factors = [";
  //  for (unsigned long i=0; i<crt.size(); i++) cout << crt[i] << " ";
  //  cout << "]\n";

  // Decode the plaintext back to a vector of elements,
  // and check that they are all equal to X
  vector<GF2X> alphas;
  cout << "decoding plaintext slots... ";
  al2.decodePlaintext(alphas, ptxt, G, maps);
  cout << "done\n";
  //  cout << "alphas = [";
  //  for (unsigned long i=0; i<alphas.size(); i++)
  //    cout << alphas[i] << " ";
  //  cout << "]\n";

  cout << "comparing " << alphas.size() << " plaintext slots to X... ";
  for (unsigned long i=0; i<alphas.size(); i++) if (alphas[i] != X) {
      cout << "\n  alphas["<<i<<"] = "<<alphas[i]<<" != X\n\n";
      exit(0);
  }
  cout << "all tests completed successfully\n\n";

  // encode and decode random polynomials
  for (unsigned long i=0; i<alphas.size(); i++) 
    random(alphas[i], 8); // random degree-7 polynomial mod 2

  cout << "embedding random GF(2^8) elements in plaintext slots... ";
  al2.embedInSlots(ptxt, alphas, maps);
  cout << "done\n";

  // Compute p^2 mod Phi_m(X) and also p(X^2) mod Phi_m(X) and
  // verify that they both decode to a vector of X^2 in all the slots

  cout << "squaring and decoding plaintext slots... ";

  X *= X;                            // X^2
  //  GF2X ptxt2;
  //  SqrMod(ptxt2,ptxt,al2.PhimXMod());      // ptxt2 = ptxt^2 mod Phi_m(X)
  CompMod(ptxt, ptxt, X, al2.PhimXMod()); // ptxt = ptxt(X^2) mod Phi_m(X)

  //  // sanity chack: these should be the same mod 2 (but not mod 2^r)
  //  if (ptxt != ptxt2) cout << "ptxt^2 != ptxt(X^2) mod Phi_m(X)\n";

  vector<GF2X> betas;
  al2.decodePlaintext(betas, ptxt, G, maps);
  cout << "done\n";

  if (alphas.size() != betas.size()) Error("wrong number of slots decoded");

  cout << "comparing decoded plaintext slots... ";
  for (unsigned long i=0; i<alphas.size(); i++) {
    SqrMod(alphas[i],alphas[i],G); // should get alpha[i]^2 mod G
    if (alphas[i] != betas[i]) {
      cout << "\n  alphas["<<i<<"] = "<<alphas[i]
           <<" != " << "betas["<<i<<"] = " << betas[i] << "\n\n";
      exit(0);
    }
  }
  cout << "all tests completed successfully\n\n";
  // return 0;

  al2r.restoreContext();

  vector<zz_pX> maps1;
  zz_pX X1; SetX(X1);

  cerr << "HERE1\n";
  al2r.mapToSlots(maps1, X1);
  cerr << "HERE1a\n";

  vector<zz_pX> alphas1;
  alphas1.resize(maps.size());

  for (long i = 0; i < lsize(alphas1); i++)
    random(alphas1[i], 1);

  zz_pX ptxt1;

  cerr << "HERE2\n";
  al2r.embedInSlots(ptxt1, alphas1, maps1);

  cerr << "HERE3\n";
  vector<zz_pX> betas1;
  al2r.decodePlaintext(betas1, ptxt1, X1, maps1);

  assert(alphas1 == betas1);
  

  return 0;
#endif
}
Example #5
0
int main()
{
  string * tmp_ptr;

  long LLL, DDD, KKK ;

  long m; 
  long ccc;
  FHEcontext * context_ptr;
  FHESecKey  * fhekey_ptr;
  EncryptedArray * ea_ptr;
  
  LLL = 682; DDD=12; KKK=80;

  /*
      pair<long, long> m_c  = get_m_c(LLL, DDD, KKK);
      m = m_c.first;
      ccc = m_c.second;
  */
  m = 15709;
  ccc = 3;

  context_ptr = new FHEcontext(m, 2, 1);
  buildModChain(*context_ptr, DDD, ccc);
  fhekey_ptr = new FHESecKey(*context_ptr);
  fhekey_ptr->clear();
  fhekey_ptr->GenSecKey(64,2);
  addSome1DMatrices(*fhekey_ptr);
  const  FHEPubKey & pub_key =  *fhekey_ptr;

  ZZX G;
  G = ZZX(1,1);
  ea_ptr = new EncryptedArray(*context_ptr, G);

  // Test I/O, write context and public key, then try to read them back
  cout << "KEY\n";
  cout <<"L= " <<LLL<< " D= " << DDD<< " K= " << KKK << endl<< flush;

  {
  stringstream s1;
  writeContextBase(s1, *context_ptr);
  s1 << *context_ptr;

  string s2 = s1.str();
  cout << s2 << endl;  // output context also to external cout

  // Read back context from input stream (s3)
  unsigned long m1, p1, r1;
  stringstream s3(s2);
  readContextBase(s3, m1, p1, r1);
  FHEcontext c1(m1, p1, r1);
  s3 >> c1;
  assert(c1 == *context_ptr);
  }
  {
  stringstream s1;
  s1 << pub_key;

  string s2 = s1.str();
  cout << s2 <<"\nENDKEY" << endl; // output public key also to external cout

  // Read back cpublic key from input stream (s3)
  stringstream s3(s2);
  FHEPubKey pk1(*context_ptr);
  s3 >> pk1;
  assert(pk1 == pub_key);
  }
}