def sum_ec_points(p1, p2, curve): # None acts like a neutral element if p1 is None: return p2 if p2 is None: return p1 A, B, p = curve x1, y1 = p1 x2, y2 = p2 if x1 == x2 and y1 == (p - y2): # neutral element return None elif p1 == p2: l = ((3 * bin_pow(x1, 2, p) + A) * reverse(2 * y1, p)) % p x3 = (bin_pow(l, 2, p) - 2 * x1) % p y3 = (l * (x1 - x3) - y1) % p else: l = ((y2 - y1) * reverse(x2 - x1, p)) % p x3 = (bin_pow(l, 2, p) - x1 - x2) % p y3 = (l * (x1 - x3) - y1) % p return (x3, y3)
def factorize_n(pub_k, priv_k): n, d = priv_k _, e = pub_k tmp = e * d - 1 s = 0 t = None while True: if tmp % 2 == 0: tmp = tmp // 2 s += 1 else: t = tmp break a = random(2, n) if gcd(a, n) > 1: return a v = bin_pow(a, t, n) if v == 1: return None while v % n != 1: v0 = v % n v = bin_pow(v, 2, n) if v0 % n == -1: return None else: return gcd(v0 + 1, n)
def encrypt(pub_key, M): p, g, y = pub_key z = random(1, p - 1) c1 = bin_pow(g, z, p) c2 = M * bin_pow(y, z, p) C = [c1, c2] return C
def sqrt(a, p): if p % 4 != 3: raise Exception("p must be a valid prime that equals 3 (mod 4)") b = bin_pow(a, ((p + 1) // 4), p) return p - b
def decrypt(priv_key, C): x, p = priv_key c1, c2 = C c1_rev = reverse(c1, p) c1_rev_x = bin_pow(c1_rev, x, p) return c2 * c1_rev_x % p
def generate_keys(): p = None q = None g = None while True: num = randkbits(1024) if is_prime(num) and is_prime(2 * num + 1): q = num p = 2 * num + 1 print(q, p) while True: g = random(1, p - 1) x = bin_pow(g, q, p) if x != 1: y = bin_pow(g, x, p) return {"public": (p, g, y), "private": (x, p)}
def is_prime(x): if x == 1: return False if x == 2 or x == 3: return True for _ in range(0, 32): # The a values 1 and n-1 are not used as the equality holds for # all n and all odd n respectively, hence testing them # adds no value. if x > 4: a = random(2, x - 2) else: a = random(2, x) if bin_pow(a, x - 1, x) != 1: return False return True
def legendre(a, p): symbol = bin_pow(a, ((p - 1) // 2), p) return symbol if symbol == 1 or symbol == 0 else -1
def ec_delta(A, B, p): return (4 * bin_pow(A, 3, p) + 27 * bin_pow(B, 2, p)) % p
def decrypt(priv_k, C): n, d = priv_k return bin_pow(C, d, n)
def encrypt(pub_k, M): n, e = pub_k if 0 > M or M > n: raise Exception("Invalid message. Message must be 0 <= M < n") return bin_pow(M, e, n)