diff --git a/elgamal.py b/elgamal.py index b51abfb52c901003aca0360436458f347bd91c26..dbd4d83e1f0f00e3b06a9cd00fe55219586051ef 100644 --- a/elgamal.py +++ b/elgamal.py @@ -3,10 +3,11 @@ from random import randint from sys import argv from math import sqrt, gcd -INPUT_NAME="fichier.txt" -SIGNATURE_NAME="fichier.signed.txt" -PUBKEY_FILE="pubkey.txt" -PRIVKEY_FILE="privkey.txt" +INPUT_NAME = "fichier.txt" +SIGNATURE_NAME = "fichier.signed.txt" +PUBKEY_FILE = "pubkey.txt" +PRIVKEY_FILE = "privkey.txt" + class Pubkey: p: int @@ -17,7 +18,7 @@ class Pubkey: self.p = p self.g = g self.A = A - + def write(self, filename: str) -> None: with open(filename, "w") as f: f.write(f"{self.p} {self.g} {self.A}") @@ -27,6 +28,7 @@ class Pubkey: p, g, A = map(int, f.read().split()) return Pubkey(p, g, A) + class Privkey: p: int g: int @@ -46,6 +48,7 @@ class Privkey: p, g, a = map(int, f.read().split()) return Privkey(p, g, a) + class Signature: Y: int S: int @@ -53,7 +56,7 @@ class Signature: def __init__(self, Y: int, S: int) -> None: self.Y = Y self.S = S - + def write(self, filename: str, data: str) -> None: with open(filename, "w") as f: f.write(f"{self.Y} {self.S}\n{data}") @@ -64,18 +67,25 @@ class Signature: data = f.read() return Signature(Y, S), data + def hash(m: str) -> int: return sum(ord(c) for c in m) + def sign(m: int, k: int, privkey: Privkey) -> Signature: p = privkey.p g = privkey.g a = privkey.a Y = pow(g, k, p) - S = pow((m - a * Y) * k, -1, p - 1) + inverse = xgcd(k, p)[1] % (p - 1) + S = ((m - a * Y) * inverse) % (p - 1) + print( + f"Y = {Y}, S = {S}, p = {p}, g = {g} a = {a}, k = {k}, m = {m}, A = {pow(g,a,p)}" + ) return Signature(Y, S) + def verify(m: int, sig: Signature, pubkey: Pubkey) -> bool: Y = sig.Y S = sig.S @@ -86,16 +96,18 @@ def verify(m: int, sig: Signature, pubkey: Pubkey) -> bool: return (pow(A, Y, p) * pow(Y, S, p)) % p == pow(g, m, p) + def is_prime(n: int) -> bool: if n <= 1: return False - + for i in range(3, int(sqrt(n)) + 1, 2): if n % i == 0: return False return True + def get_random_prime(min: int, max: int) -> int: # trouver un nombre premier aléatoire entre min et max while True: @@ -104,40 +116,47 @@ def get_random_prime(min: int, max: int) -> int: print(f"Found prime: {n}") return n + def get_all_generators(p: int) -> int: return [g for g in range(2, p) if all(pow(g, i, p) != 1 for i in range(1, p - 1))] + def get_random_generator(p: int) -> int: generators = get_all_generators(p) rand = randint(0, len(generators) - 1) - return generators[1] + return generators[rand] + def generate_key_pair() -> Tuple[Privkey, Pubkey]: - # p = get_random_prime(1000, 10_000) - # g = get_random_generator(p) - # a = randint(0, p - 1) - p = 7297 - g = 14 - a = 7057 + p = get_random_prime(1000, 10_000) + g = get_random_generator(p) + a = randint(0, p - 1) + # p = 7297 + # g = 852 + # a = 12 A = pow(g, a, p) + print(f"Found generator : {g}") return Privkey(p, g, a), Pubkey(p, g, A) -def xgcd(a,b): - prevx , x = 1 , 0 - prevy , y = 0 , 1 + +def xgcd(a, b): + prevx, x = 1, 0 + prevy, y = 0, 1 while b: - q = a//b - x, prevx = prevx - q*x, x - y, prevy = prevy - q*y, y - a, b = b, a % b + q = a // b + x, prevx = prevx - q * x, x + y, prevy = prevy - q * y, y + a, b = b, a - q * b return a, prevx, prevy + def generate_k(p: int) -> int: k = randint(1, p - 2) while gcd(k, p - 1) != 1: k = randint(1, p - 2) return k + def main(mode): if mode == 0: # open the fichier.txt file and read its content into a string @@ -164,4 +183,5 @@ def main(mode): print("mode: 0 for signing, 1 for verifying") exit(1) -main(int(argv[1]) if len(argv) == 2 else -1) \ No newline at end of file + +main(int(argv[1]) if len(argv) == 2 else -1)