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.11k stars 761 forks source link

Ctxt::bringToSet called with capacity=-14.9074, likely decryption error #285

Open hdln opened 5 years ago

hdln commented 5 years ago

Hi,when I set a very big value to param p (like 999999999999659),the decrypted result is not correct ,it seams like a random num. My params: const long p = 999999999999659; const long r = 1; const long L = 4; const long c = 2; const long k = 80; const long s = 0; const long d = 1; const long w = 64;

Got result:
encrypt 100 decrypt the ciphertexts of 100 :122 sum 100+50 decrypt the ciphertexts of 100+50 :171 sub 150-20 decrypt the ciphertexts of 150 -20 :120 Ctxt::bringToSet called with capacity=-11.671, likely decryption error Ctxt::bringToSet called with capacity=-10.5724, likely decryption error Ctxt::bringToSet called with capacity=-56.354, likely decryption error mul 1302 decrypt the ciphertexts of 1302 :33557767100928

When the param p is small ,it's OK!

shaih commented 5 years ago

HElib cannot work with very large p values. In principle you may be able to use p values upto 60 bits (about 1e20), but you will need huge values of L to make it work. (And also we never tested such large values, so perhaps things break with p values above 30 bits.) This is unlikely to ever change, as the technology inherently has poor behavior for very large p values. Some ways to get around this limitation are:

(a) work with p=2 and encode all your values in binary (HElib has some support for binary arithmetic and comparisons). (b) Work with multiple instances, each with a small p value (all co-prime), and use Chinese-remaindering to reconstruct the values that you are interested in. (c) Use the CKKS back end of HElib (still in draft status) to handle "analog computations" where you only care about the high-order bits of the results.

peiworld commented 5 years ago

I am having similar problem with smaller p values.

{ "PlaintextModule": 73, "Lifting": 1, "ModuleChainLevel": 30, "KeySwitchingMatricesColumns": 2, "SecKeyHammingWeight": 64, "FieldExtensionDegree": 1, "SecurityParameter": 80, "Slot": 0, "nSlot": 174 }

Ctxt::bringToSet called with empty set and capacity=11.3256, this is likely a bug Ctxt::bringToSet called with empty set and capacity=12.8503, this is likely a bug Ctxt::bringToSet called with empty set and capacity=11.3256, this is likely a bug Ctxt::bringToSet called with empty set and capacity=27.2386, this is likely a bug getSet4Size: no matching IndexSet found, likely decryption error Ctxt::bringToSet called with capacity=-13.8163, likely decryption error Ctxt::bringToSet called with capacity=-13.1942, likely decryption error Ctxt::bringToSet called with capacity=-51.7861, likely decryption error getSet4Size: no matching IndexSet found, likely decryption error

shaih commented 5 years ago

Most likely you specified a value of L which is too low to buildModChain. We re-purposed the argument L, now it means the number of bits that you need rather than the number of levels. (For most settings you can use #-of-bits = 25x or 30x the #-of-levels.)

hdln commented 5 years ago

(a) work with p=2 and encode all your values in binary (HElib has some support for binary arithmetic and comparisons).

`long r = 1; long p = 2; long d = 1; long c = 2; long k = 80; long L = 500; long s = 0; long chosen_m = 0; long seed = 0; SetSeed(ZZ(seed)); long w = 64; long m = FindM(k, L, c, p, d, s, chosen_m, 0); vector gens, ords;

FHEcontext context(m, p, r, gens, ords);
buildModChain(context, L, c);
ZZX G = makeIrredPoly(p, d);
FHESecKey secretKey(context);
const FHEPubKey &publicKey = secretKey;
secretKey.GenSecKey();
addSome1DMatrices(secretKey);
EncryptedArray ea(context, G);
PlaintextArray p0(ea);
PlaintextArray p1(ea);
random(ea, p0);
random(ea, p1);
Ctxt c0(publicKey), c1(publicKey);
ea.encrypt(c0, publicKey, p0);
ea.encrypt(c1, publicKey, p1);
                        //if p0=110  p1=010
mul(ea, p1, p0);     // p1*=p0  ,I think p1 should be 1100,but the result is 010
c1.multiplyBy(c0);  // c1.multiplyBy(c0)
c0.cleanUp();
c1.cleanUp();
PlaintextArray pp1(ea);
ea.decrypt(c1, secretKey, pp1);
if (equals(ea, pp1, p1))
    std::cout << "GOOD\n";
else std::cout << "BAD\n";`

If p0=110 p1=010, p1*=p0 , I think p1 should be 1100,but the result is 010.

hdln commented 5 years ago

` long m = FindM(k, L, c, p, d, s, 0);

FHEcontext context(m, p, r);
buildModChain(context, L, c);

stringstream secKeyStream;
stringstream pubKeyStream;

writeContextBase(secKeyStream, context);
writeContextBase(pubKeyStream, context);

secKeyStream << context << endl;
pubKeyStream << context << endl;

FHESecKey secretKey(context);
const FHEPubKey &publicKey = secretKey;
secretKey.GenSecKey(w);
// addSome1DMatrices(secretKey);

// Output keys to files
secKeyStream << secretKey << endl;
pubKeyStream << publicKey << endl;

cout<<secKeyStream.str()<<endl;
cout<<pubKeyStream.str()<<endl;

`

The publicKey string is the same with secretKey string,is that right?

ama9000 commented 5 years ago

Most likely you specified a value of L which is too low to buildModChain. We re-purposed the argument L, now it means the number of bits that you need rather than the number of levels. (For most settings you can use #-of-bits = 25x or 30x the #-of-levels.)

Thanks for the suggestion. I was facing a similar issue with my code for the same reason. Does this also affect the hard-coded L value in the AES test example below? https://github.com/shaih/HElib/blob/7091789b0e00010399dafaf0291a6be59fb3104e/src/aes/Test_AES.cpp#L69-L78

Thanks.

radhumal commented 4 years ago

I am getting this error when I am trying to update value at specific location in deque. eg: a[i]=s; where a is deque and i am assigning s to a[i]

The error is given below:

Ctxt::bringToSet called with empty set and capacity=13.0338, this is likely a bug getSet4Size: no matching IndexSet found, likely decryption error Ctxt::bringToSet called with capacity=-11.2463, likely decryption error Ctxt::bringToSet called with capacity=-11.2463, likely decryption error

shaih commented 4 years ago

This error means that you are using parameters that are too small, and ran out of capacity (note the negative capacity).

radhumal commented 4 years ago

Thank you for your response.

On Mon, May 11, 2020 at 10:07 AM Shai Halevi notifications@github.com wrote:

This error means that you are using parameters that are too small, and ran out of capacity (note the negative capacity).

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/homenc/HElib/issues/285#issuecomment-626464547, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKMYTL2M3GEJ77OLLNEG6X3RQ56G3ANCNFSM4GZXRI7Q .

DHCtaichi commented 3 years ago

Hey guys, I have the same problem. I try to multiply a single variable many times using HElib, like A = Enc(a), B = Enc(b), A = A*B. When I use normal encryption and multiply, I got the same problem like Ctxt::bringToSet called with capacity=-11.671, likely decryption error., but when I use binary multiply like examples/BGV_binary_arithmetic in HElib showed, I've never faced the same problem even 1000 times multiplication. Could someone tell me the reason?