Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paillier not working with scalar non-integer float #21

Closed
kostrom opened this issue Apr 16, 2024 · 16 comments
Closed

Paillier not working with scalar non-integer float #21

kostrom opened this issue Apr 16, 2024 · 16 comments
Labels
bug Something isn't working dependency

Comments

@kostrom
Copy link

kostrom commented Apr 16, 2024

If someone tries to work with float values in paillier, it doesn't work, but it works for integers. If it only supports integers, you may want to raise an exception, in keeping with how you handle some other illegal operations.

see https://stackoverflow.com/questions/78335087/the-sum-does-not-get-decrypted

@serengil serengil added the question Further information is requested label Apr 16, 2024
@serengil
Copy link
Owner

Float numbers are not invalid actually. They are converted to integers for that module.

cs = LightPHE(algorithm_name = "Paillier")

m1 = 17
c1 = cs.encrypt(m1)

# increasing something 5%
k = 1.05

# scalar multiplication - private key is not required!
c4 = k * c1

# proof of work
assert cs.decrypt(c4) == k * m1

Besides, if you set your plaintext as tensor, then you are able to restore that float number.

cs = LightPHE(algorithm_name = "Paillier")

m = [1.5]
c = cs.encrypt(m)
p = cs.decrypt(c)
assert p[0] == 1.5

@serengil serengil closed this as not planned Won't fix, can't repro, duplicate, stale Apr 16, 2024
@kostrom
Copy link
Author

kostrom commented Apr 17, 2024

`from lightphe import LightPHE
cs = LightPHE(algorithm_name="Paillier")
def validate(m): return m == cs.decrypt(cs.encrypt(m))

assert validate(1)
assert validate([1.5])
assert validate(1.0)
assert validate(1.5) # does not work for scalar float (with a non-integer value)
`
Thanks for the workaround. I notice that the working vector of float creates a Fraction object, but the scalar float goes into parse_int and breaks it down to a fraction form, but returns a Ciphertext object of a very large integer, which it doesn't know how to reverse.

I guess the title of the bug report is completely wrong, though -- sorry about that. If I'd thought about it, I'd have realized something that works with integers can work with fractions of integers.

@serengil
Copy link
Owner

They are all working for me. Are you using latest version?

@kostrom
Copy link
Author

kostrom commented Apr 17, 2024

pip says this is version 0.0.6

@serengil
Copy link
Owner

would you please share all exception message?

@serengil
Copy link
Owner

btw python version may be the root cause of your problem.

i am using Python 3.9.16

@kostrom
Copy link
Author

kostrom commented Apr 17, 2024

Python 3.10.4 (tags/v3.10.4:9d38120, Mar 23 2022, 23:13:41) [MSC v.1929 64 bit (AMD64)] on win32
There are no exceptions (unless you count the assert).
It just returns a very large integer instead of the original float.
I updated the issue summary.

from lightphe import LightPHE  
cs = LightPHE(algorithm_name="Paillier")  

m = 0.5  
c = cs.encrypt(m)  
print (c)  
print (c.value)  
print (cs.decrypt(c))  

The result is a different large integer each time. One example:
Ciphertext(4922236528608796958846746588856423007916048798962477533781817619365633697325781550310212188324426679830638156638168677716104162861723368950471576089968798265186067536585262890999551828526603098457138708105316241290356667810727996717063041280990292421509852573848746382971495371575884363892331801459088266056263296822284217735228810846513811562773585729263266463491832609884275528416373445393310448315775555480589931990786433374114491875143152201524542983831458022888057533769829260893420154296328186405682975065490419261182064893854706074644935068680571429787260863682691199488370523205802299040717157400554985373)
4922236528608796958846746588856423007916048798962477533781817619365633697325781550310212188324426679830638156638168677716104162861723368950471576089968798265186067536585262890999551828526603098457138708105316241290356667810727996717063041280990292421509852573848746382971495371575884363892331801459088266056263296822284217735228810846513811562773585729263266463491832609884275528416373445393310448315775555480589931990786433374114491875143152201524542983831458022888057533769829260893420154296328186405682975065490419261182064893854706074644935068680571429787260863682691199488370523205802299040717157400554985373
3160776990604745647081572122326825228093787522500982730374347988572421971214894550600891079327673062817591884978456486978621806738130920750356955734498673096320017239353437210121462431193272851721939264910466572918152023133068103002383357016447565929890091709586032192185552280463164426557306804290606846899

@kostrom kostrom changed the title Paillier should enforce integers Paillier not working with scalar non-integer float Apr 17, 2024
@kostrom
Copy link
Author

kostrom commented Apr 17, 2024

Actually, looking at the source, I might be able to submit an MR, but if you're not reproducing the issue ... that might be counterproductive.

@serengil
Copy link
Owner

Yes please

@serengil serengil reopened this Apr 17, 2024
@kostrom
Copy link
Author

kostrom commented Apr 18, 2024

My quick fix of handling float like [float] broke a few other things. Fraction doesn't have value, and why can't we multiply a Fraction by a constant?

Is there a quick way to convert between Ciphertext and Fraction?

@serengil
Copy link
Owner

serengil commented Apr 18, 2024

It does!

https://github.com/serengil/LightPHE/blob/master/tests/test_tensors.py#L64

As seen this is checked in unit tests and run successfully in github actions. I think your problem is because of your python version.

@serengil serengil added bug Something isn't working and removed question Further information is requested labels Apr 18, 2024
@serengil
Copy link
Owner

you cannot convert ciphertext to fraction. you can only convert a float value to fraction. then, you can encrypt its dividend and divisor separately as shown here: https://github.com/serengil/LightPHE/blob/master/lightphe/__init__.py#L178

@kostrom
Copy link
Author

kostrom commented Apr 18, 2024

Sorry, I misspoke. Multiply Ciphertext (of a constant) and Fraction.
Ciphertext and Tensor each have dunder mul, but they don't like each other.

@kostrom
Copy link
Author

kostrom commented Apr 19, 2024

I'll have to deal with another fire, then get a better understanding of the class structure before I give this another go.

@serengil
Copy link
Owner

@kostrom you may consider to make your python version same with me

@serengil
Copy link
Owner

Closed due to inactivity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working dependency
Projects
None yet
Development

No branches or pull requests

2 participants