Partial Homomorphic Encryption with Haskell

145 views Asked by At

I am working with a fairly simple Paillier partial homomorphic encryption library in Haskell. The API for the library is here - https://hackage.haskell.org/package/Paillier-0.1.0.3/docs/Crypto-Paillier.html

This library unfortunately does not handle negative numbers or floating point numbers. It only operates on positive integers. So, an operation like

decrypt prvKey pubKey (encrypt pubKey (-10))  =/=  -10

My naive approach to handling negative numbers and floating points was to multiply the Integers with my desired precision (say 10^6) and then convert it back. But internally, some modular arithmetic does not work for homomorphic multiplication (exponentiation).

The problem could somewhat be boiled down to finding a good encoding of negative numbers as well as floating point numbers into an Integer type (the arbitrary precision integer type in Haskell). Is there any good strategy to do the encoding?

Another strategy could be modifying the modular exponentiation function in the cryptonite package to handle modular arithmetic for negative numbers (https://hackage.haskell.org/package/cryptonite-0.30/docs/Crypto-Number-ModArithmetic.html#v:expSafe).

Can anyone suggest to me the best strategy or something that I am missing out here?

1

There are 1 answers

0
sefiks On

All partially homomorphic encryption algorithms including Paillier are working on modular arithmetic. Even if you fancy about negative numbers, then they are still positive numbers on the defined modulo.

Let's explain this with an example with LightPHE for Paillier. The cryptosystem is defined on modulo n for plaintexts and n^2 for ciphertext. So, a negative number is equivalent to negative number itself modulo n.

# !pip install lightphe
from lightphe import LightPHE

# build a cryptosystem with random keys
cs = LightPHE(algorithm_name="Paillier")

# modulo of the cryptosystem
modulo = cs.cs.plaintext_modulo

# define a plaintext
m = -10

# calculate ciphertext
c = cs.encrypt(plaintext=m)

# proof of work
assert cs.decrypt(c) == m % modulo