def TruncPrRing(a, k, m, signed=True): if m == 0: return a n_ring = int(program.Program.prog.options.ring) assert n_ring >= k, '%d too large' % k if k == n_ring: for i in range(m): a += types.sint.get_random_bit() << i return comparison.TruncLeakyInRing(a, k, m, signed=signed) else: from types import sint if signed: a += (1 << (k - 1)) if program.Program.prog.use_trunc_pr: res = sint() trunc_pr(res, a, k, m) else: # extra bit to mask overflow r_bits = [sint.get_random_bit() for i in range(k + 1)] n_shift = n_ring - len(r_bits) tmp = a + sint.bit_compose(r_bits) masked = (tmp << n_shift).reveal() shifted = (masked << 1 >> (n_shift + m + 1)) overflow = r_bits[-1].bit_xor(masked >> (n_ring - 1)) res = shifted - sint.bit_compose(r_bits[m:k]) + \ (overflow << (k - m)) if signed: res -= (1 << (k - m - 1)) return res
def TruncZeroesInRing(a, k, m, signed): """ Returns a >> m. Requires 2^m | a and a < 2^k. """ from types import sint, intbitint, cint, cgf2n n_bits = k - m n_shift = int(program.options.ring) - n_bits r_bits = [sint.get_random_bit() for i in range(n_bits)] r = sint.bit_compose(r_bits) shifted = ((a << (n_shift - m)) - (r << n_shift)).reveal() masked = shifted >> n_shift res_bits = intbitint.bit_adder(r_bits, masked.bit_decompose(n_bits)) res = sint.bit_compose(res_bits) if signed: res = sint.conv(res_bits[-1].if_else(res - (sint(1) << n_bits), res)) return res
def TruncPrRing(a, k, m): if m == 0: return a n_ring = int(program.Program.prog.options.ring) if k == n_ring: for i in range(m): a += types.sint.get_random_bit() << i return comparison.TruncLeakyInRing(a, k, m, True) else: from types import sint # extra bit to mask overflow r_bits = [sint.get_random_bit() for i in range(k + 1)] n_shift = n_ring - len(r_bits) tmp = a + sint.bit_compose(r_bits) masked = (tmp << n_shift).reveal() shifted = (masked << 1 >> (n_shift + m + 1)) overflow = r_bits[-1].bit_xor(masked >> (n_ring - 1)) res = shifted - sint.bit_compose(r_bits[m:k]) + (overflow << (k - m)) return res
def Mod2mRing(a_prime, a, k, m, signed): assert(int(program.options.ring) >= k) from Compiler.types import sint, intbitint, cint shift = int(program.options.ring) - m r = [sint.get_random_bit() for i in range(m)] r_prime = sint.bit_compose(r) tmp = a + r_prime c_prime = (tmp << shift).reveal() >> shift u = sint() BitLTL(u, c_prime, r, 0) res = (u << m) + c_prime - r_prime if a_prime is not None: movs(a_prime, res) return res
def TruncLeakyInRing(a, k, m, signed): """ Returns a >> m. Requires a < 2^k and leaks a % 2^m (needs to be constant or random). """ assert k > m assert int(program.options.ring) >= k from types import sint, intbitint, cint, cgf2n n_bits = k - m n_shift = int(program.options.ring) - n_bits r_bits = [sint.get_random_bit() for i in range(n_bits)] r = sint.bit_compose(r_bits) if signed: a += (1 << (k - 1)) shifted = ((a << (n_shift - m)) + (r << n_shift)).reveal() masked = shifted >> n_shift u = sint() BitLTL(u, masked, r_bits, 0) res = (u << n_bits) + masked - r if signed: res -= (1 << (n_bits - 1)) return res