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

Bitwise operations involving negative secret ints #1556

Open
sebw42 opened this issue Dec 16, 2024 · 5 comments
Open

Bitwise operations involving negative secret ints #1556

sebw42 opened this issue Dec 16, 2024 · 5 comments

Comments

@sebw42
Copy link

sebw42 commented Dec 16, 2024

Hi, I tried bitwise operations on secret integers (or mixed secret and clear ones) like you described in this issue: #264.
However, when negative numbers are involved, this method does not work as expected.
The reason seems to be that the bit_compose functions of cint and sint expect the input to represent an unsigned integer instead of a signed one.
Here is an example:

b = sint(-1)
bits = sint.bit_decompose(b, 8)
b_composed = sint.bit_compose(bits)

print_ln("bits: %s", [v.reveal() for v in bits])
print_ln("b_composed: %s", b_composed.reveal())

11111111 is the correct two's complement representation of -1, but bit_compose interprets it as an unsigned int, and therefore 255.

Is there a way to obtain a signed int from a list of bits? Or is there another way of performing bitwise operations on secrets that do not involve decomposing them?

Thank you!

@mkskeller
Copy link
Member

You can easily achieve this by subtracting bits[-1] * 2 ** (len(bits)).

@sebw42
Copy link
Author

sebw42 commented Dec 17, 2024

Thank you for the quick response, this works.
I have another related question. I tried using bitshifts and noticed the following (compiled using -R 64):

a = sint(-1) >> sint(0)
print_ln('a: %s', a.reveal()) # prints 9223372036854775807

The printed number would be the result of a logical right shift by 1.
It prints -1 when we use 0 instead of sint(0) in the shift operation.
Is this expected? Thank you!

@mkskeller
Copy link
Member

Shifting negative numbers by a secret number isn't implemented because it's not as straightforward as correcting a public shift.

@sebw42
Copy link
Author

sebw42 commented Dec 18, 2024

Does this also apply to other runtime values?
I've tried different combinations of types for shifting -7 by 1 to the right (which should result in -4) and got the following results:

c_c = cint(-7) >> cint(1)
print_ln('c_c: %s', c_c) # prints 9223372036854775804
c_p = cint(-7) >> 1
print_ln('c_p: %s\n', c_p) # prints 9223372036854775804

s_c = sint(-7) >> cint(1)
print_ln('s_c: %s', s_c.reveal()) # prints 4611686018427387900
s_p = sint(-7) >> 1
print_ln('s_p: %s\n', s_p.reveal()) # prints -4

p_c = -7 >> cint(1)
print_ln('p_c: %s', p_c) # prints 9223372036854775804
p_p = -7 >> 1
print_ln('p_p: %s\n', p_p) # prints -4

Shifting a sint by a cint returns the same value as when we shift a sint by another sint.
The other cases involving cints seem to perform a logical shift instead of an arithmetic one, even if the right operand is a python integer.

@mkskeller
Copy link
Member

Two things are going on here:

  • Operations involving negative sint aren't implemented for the same reason as above. Nevertheless, there cannot be an error because that would violate the secrecy. The fact that sint(-7) >> 1 results in -4 is more coincidental.
  • cint is generally assumed to be unsigned, hence the result for all operations involving cint but not sint.

Taking one step back, I would be interested to hear how this affects your application, so I can think of potential improvements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants