from math import ceil, floor, log e = 17 d = 413 n = 3233 m = 65; def crypt(m): return pow(m, e, n) def clear(c): return pow(c, d, n) def oracle(c): return clear(c) % 2 == 0 def double(c): return (c * crypt(2)) % n def solve(c, lower, upper): div = 1 for i in range(int(log(n, 2)) + 1): print(f"{i=} {lower=} {upper=} {div=}") div = div * 2 lower = lower * 2 upper = upper * 2 new = (lower + upper) >> 1 c = double(c) if oracle(c): upper = new else: lower = new return upper * n // div for m in range(2, n - 1): c = crypt(m) r = solve(c, 0, 1) print(f"{m=} {c=} {r=}") assert(r == m)