import random from functools import reduce from math import floor, log2 from params import a, b, c, d, e, f, g, h, i, j, k, m, n, o, p, q, r, u, v, w # a < b => b # (a // b) * c + (a % b) def wut(a, b, c): def wuuuuut(z): if z <= b: return z x, y = divmod(z, b) return wuuuuut(x * c + y) return wuuuuut(a) def wutwut(a, b, c, d): return reduce( lambda x, y: ( wut(x * x, c, d) if not (b >> y) & 1 else wut(wut(x * x, c, d) * a, c, d) ), reversed(range(floor(log2(b)))), wut(a, c, d), ) def rsa_decrypt(ciphertext): s = wutwut(wut(ciphertext, o, p), a * b + c * d, o, p) t = wutwut(wut(ciphertext, q, r), f * g + h * i, q, r) x = s - t y = (x * j + x * k) * u x = y * r y = t + v + y * m return (y - x - w) % n # check if the code works correctly :) for _ in range(1000): # encrypt 100 random plaintexts with public key random_plaintext = random.randint(0, n - 1) print(random_plaintext) # verify that the decryption works correctly assert rsa_decrypt(pow(random_plaintext, e, n)) == random_plaintext