lschoe / mpyc

MPyC: Multiparty Computation in Python
MIT License
367 stars 76 forks source link

How to conduct bitwise or efficiently? #56

Closed winnnnnny closed 1 year ago

winnnnnny commented 1 year ago

Hello, sorry for disturbing you. I want to conduct a bitwise on two secure integers. I observed that the mpc._or is limited to 1-bit only, so I try to use 1-bit secure integer but the result was still unexpected. I also tried the methods mentioned in #36, it works but may be a bit complex. The coding is shown below.

from mpyc.runtime import mpc
async def main():
    secint = mpc.SecInt(1)
    a = secint(1)
    b = secint(1)
    x = mpc.to_bits(a)
    y = mpc.to_bits(b)
    z1 = mpc.schur_prod(x, y)   # bitwise and
    z2 = mpc.vector_sub(mpc.vector_add(x, y), z1)
    c1 = mpc.from_bits(z1)
    c2 = mpc.from_bits(z2)
    print("c2", await mpc.output(c2))
    bitor = mpc.or_(a, b)
    print("bitor", await mpc.output(bitor))

mpc.run(main())

The result is shown below.

2023-05-30 16:47:52,031 Install package numpy for more functionality.
2023-05-30 16:47:52,031 Install package gmpy2 for better performance.
c2 1
bitor 3

a and b are two 1-bit secure integers, but the result is still unexpected. Does it mean I have to implement the or like #36?

lschoe commented 1 year ago

You get the or of a and b by using | as mentioned in #36. If you replace the line where you assign bitor by:

     bitor = a | b

you get the expected result because '|` is overloaded for secure integers.

Here, a and b are not required to be of the secure integer type mpc.SecInt(1) with bit length exactly 1, but can be of type mpc.SecInt(16) for instance as long as the values of a and b are 0 or 1 (bit values). Such a and b may arise from secure comparisons between secure integers, e.g., a = r < s and b = r < t, or from secure bit decompositions.

winnnnnny commented 1 year ago

Thank you for your suggestion! Now I can use a | b to implement bitwise or successfully.

winnnnnny commented 1 year ago

Sorry for disturbing you again. I cannot implement bitwise not successfully. From the document, I should use mpc.convert, but the result is unexpected. Here is the code.

from mpyc.runtime import mpc
async def main():
    secint = mpc.SecInt(1)
    a = secint(1)
    b = secint(0)
    result = mpc.invert(a & b)
    print("result:", await mpc.output(result))

mpc.run(main())

The result is shown below.

2023-05-30 19:52:39,052 Install package numpy for more functionality.
2023-05-30 19:52:39,052 Install package gmpy2 for better performance.
result: -1

I expect the result to be 1 from not(0), but the result is -1. How should I implement not?

lschoe commented 1 year ago

Use ~ which is also overloaded for secure integers:

   result = ~(a & b)
winnnnnny commented 1 year ago

Thank you for your suggestion!