homenc / HElib

HElib is an open-source software library that implements homomorphic encryption. It supports the BGV scheme with bootstrapping and the Approximate Number CKKS scheme. HElib also includes optimizations for efficient homomorphic evaluation, focusing on effective use of ciphertext packing techniques and on the Gentry-Halevi-Smart optimizations.
https://homenc.github.io/HElib
Other
3.14k stars 765 forks source link

Wrong decryption with multiple ciphertext file I/O's #172

Open radwasherif opened 7 years ago

radwasherif commented 7 years ago

I have the following code to initialize multiple schemes in HElib, encrypt some values using each scheme, then write the scheme, public key and Ctxt's out to a file:

for(int I = 0; I < 3; I++) {
        long m=0, p=5, r=1; // Native plaintext space
        // Computations will be 'modulo p'
        long L=16;          // Levels
        long c=3;           // Columns in key switching matrix
        long w=64;          // Hamming weight of secret key
        long d=0;
        long security = 0;
        ZZX G;
        m = FindM(security,L,c,p, d, 0, 0);

        fstream out("keyFile" + to_string(I) + std::string(".txt") , fstream::out); 

        FHEcontext context(m, p, r);
        // initialize context
        buildModChain(context, L, c);
        // modify the context, adding primes to the modulus chain
        FHESecKey secretKey(context);
        // construct a secret key structure
        const FHEPubKey& publicKey = secretKey;
        // an "upcast": FHESecKey is a subclass of FHEPubKey
        //if(0 == d)
        G = context.alMod.getFactorsOverZZ()[0];

       secretKey.GenSecKey(w);
       // actually generate a secret key with Hamming weight w

       addSome1DMatrices(secretKey);
       cout << "Generated key" << endl;

       EncryptedArray ea(context, G);
       // constuct an Encrypted array object ea that is
       // associated with the given context and the polynomial G

    //writing context and public key out to file 
       writeContextBase(out, context);
       out << context << endl; 
       out << publicKey << endl; 

       long nslots = ea.size();

        for(int k = 0; k < 10; k++) {
            vector<long> pt; 

            for(int i = 0; i < nslots; i++) {
                pt.push_back(i%5); 
            }

            Ctxt ct(publicKey); 
            ea.encrypt(ct, publicKey, pt); 
            vector <long> res; 
            ea.decrypt(ct, secretKey, res); 
            cout << res << endl; 
            out << ct << endl; 

        }
       out.close(); 

    }

Then I have the following code to read each scheme and it's public key, then initiate a secret key. Then it reads the Ctxt's from their respective files and decrypts them:

for(int I = 0; I < 3; I++) {
        fstream keyFile("keyFile" + to_string(I) + std::string(".txt") , fstream::in); 
        unsigned long m1, p1, r1;
        vector<long> gens, ords;
        readContextBase(keyFile, m1, p1, r1, gens, ords);
        FHEcontext context(m1, p1, r1, gens, ords);
        keyFile >> context;

        FHESecKey secretKey(context);
        // construct a secret key structure
        FHEPubKey publicKey(context); 
        // an "upcast": FHESecKey is a subclass of FHEPubKey
        keyFile >> publicKey; 
        ZZX G; 
        //if(0 == d)
        G = context.alMod.getFactorsOverZZ()[0];

       secretKey.GenSecKey(64);
       // actually generate a secret key with Hamming weight w

       addSome1DMatrices(secretKey);
       cout << "Generated key" << endl;

       EncryptedArray ea(context, G);
       // constuct an Encrypted array object ea that is
       // associated with the given context and the polynomial G
        Ctxt ct(publicKey); 
        cout << I << endl; 
        for(int k = 0; k < 10; k++) {
            keyFile >> ct; 
            vector <long> res; 
            ea.decrypt(ct, secretKey, res);
            cout << res << endl; 
        } 

    }

But only the first scheme decrypts correctly. For the other two, I am getting random values modulo p. I cannot detect a pattern in them. What could be the problem?

shaih commented 6 years ago

You seem to be encrypting relative to one key, but then generating a totally new key (cf. the secretKey.GenSecKey(64) in the second part). Trying to decrypt with this new key, you should not expect to get the right answer. Are you sure the first scheme decrypts correctly? It really should not, as far as I can tell.