commit 43a72c3fb71c70bbe157ae520f29f25b7a08803e Author: Lukian Date: Thu Jan 23 17:57:15 2025 +0100 First commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9b65602 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +cr/ +.venv/ diff --git a/lib/__pycache__/arithmetics.cpython-313.pyc b/lib/__pycache__/arithmetics.cpython-313.pyc new file mode 100644 index 0000000..006ef0f Binary files /dev/null and b/lib/__pycache__/arithmetics.cpython-313.pyc differ diff --git a/lib/__pycache__/diffie_hellman.cpython-313.pyc b/lib/__pycache__/diffie_hellman.cpython-313.pyc new file mode 100644 index 0000000..3b3fc15 Binary files /dev/null and b/lib/__pycache__/diffie_hellman.cpython-313.pyc differ diff --git a/lib/__pycache__/miller_rabin.cpython-313.pyc b/lib/__pycache__/miller_rabin.cpython-313.pyc new file mode 100644 index 0000000..ec71d81 Binary files /dev/null and b/lib/__pycache__/miller_rabin.cpython-313.pyc differ diff --git a/lib/__pycache__/rsa.cpython-313.pyc b/lib/__pycache__/rsa.cpython-313.pyc new file mode 100644 index 0000000..3ecd8ed Binary files /dev/null and b/lib/__pycache__/rsa.cpython-313.pyc differ diff --git a/lib/arithmetics.py b/lib/arithmetics.py new file mode 100644 index 0000000..0ac78de --- /dev/null +++ b/lib/arithmetics.py @@ -0,0 +1,39 @@ +# Arithmetics functions implementaton + +def modpow(a: int, b: int, m: int) -> int: + result = 1 + while b > 0: + if (b & 1) > 0: + result = (result * a) % m + b = b >> 1 + a = (a * a) % m + return result + +def gcd(a: int, b: int) -> int: + if b == 0: + return a + return gcd(b, a % b) + +def mod_inverse(A: int, M: int) -> int: + m0 = M + y = 0 + x = 1 + if (M == 1): + return 0 + while (A > 1): + # q is quotient + q = A // M + t = M + # m is remainder now, process + # same as Euclid's algo + M = A % M + A = t + t = y + # Update x and y + y = x - q * y + x = t + # Make x positive + if (x < 0): + x = x + m0 + return x + diff --git a/lib/diffie_hellman.py b/lib/diffie_hellman.py new file mode 100644 index 0000000..2117e87 --- /dev/null +++ b/lib/diffie_hellman.py @@ -0,0 +1,21 @@ +# Python Diffie-Hillman implémentation + +import random + +import lib.miller_rabin as miller +import lib.arithmetics as arithm + +def get_p_and_g(n: int) -> (int, int): + p = miller.get_random_prime(n) + g = random.randint(2**(n-1), p) + return (p, g) + +def get_x(n: int) -> int: + return random.randint(2**(n-1), 2**n - 1) + +def get_X(x: int, p: int, g: int) -> int: + return arithm.modpow(g, x, p) + +def get_K(X: int, y: int, p: int): + return arithm.modpow(X, y, p) + diff --git a/lib/miller_rabin.py b/lib/miller_rabin.py new file mode 100644 index 0000000..5d4c10a --- /dev/null +++ b/lib/miller_rabin.py @@ -0,0 +1,40 @@ +# Python Miller-Rabin implementation + +import random +import lib.arithmetics as arithm + +def get_d_and_s(n: int) -> (int, int): + d = n - 1 + s = 0 + while d % 2 == 0: + d //= 2 + s += 1 + return (d, s) + +def rabin_witness(n: int, a: int) -> bool: + d, s = get_d_and_s(n) + x = arithm.modpow(a, d, n) + if x == 1 or x == n - 1: + return False + for _ in range(s - 1): + x = arithm.modpow(x, 2, n) + if x == n - 1: + return False + return True + +def miller_rabin(n: int, k: int) -> bool: + if n < 3: return False + for _ in range(k): + a = random.randint(2, n - 1) + if rabin_witness(n, a): return False + return True + +def is_prime(n: int) -> bool: + return miller_rabin(n, 25) + +def get_random_prime(n: int) -> int: + a = random.randint(2**(n-1), 2**(n) - 1) + while not is_prime(a): + a = random.randint(2**(n-1), 2**(n) - 1) + return a + diff --git a/lib/rsa.py b/lib/rsa.py new file mode 100644 index 0000000..0ae2a7c --- /dev/null +++ b/lib/rsa.py @@ -0,0 +1,35 @@ +# Python RSA implementation + +import random +import sys + +import lib.arithmetics as arithm +import lib.miller_rabin as miller + +def get_p_and_q(n: int) -> (int, int): + # Get two random prime numbers + p = miller.get_random_prime(n) + q = miller.get_random_prime(n) + # Ensure the two numbers are differents + while p == q: + q = get_random_prime(n) + return (p, q) + +def get_keys(l: int) -> int: + p, q = get_p_and_q(l // 2) + n = p * q + phy_n = (p - 1) * (q - 1) + e = 65537 + while arithm.gcd(e, phy_n) != 1: + p, q = get_p_and_q(l // 2) + n = p * q + phy_n = (p - 1) * (q - 1) + d = arithm.mod_inverse(e, phy_n) + return (e, d, n) + +def encrypt(m: int, e: int, n: int) -> int: + return arithm.modpow(m, e, n) + +def decrypt(c: int, d: int, n: int) -> int: + return arithm.modpow(c, d, n) + diff --git a/main.py b/main.py new file mode 100644 index 0000000..4b8be63 --- /dev/null +++ b/main.py @@ -0,0 +1,59 @@ +import lib.rsa as rsa +import lib.diffie_hellman as diffie +from hashlib import sha256 + +BITS = 32 +ALPH = {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5, 'g': 6, 'h': 7, 'i': 8, 'j': 9, 'k': 10, 'l': 11, 'm': 12, 'n': 13, 'o': 14, 'p': 15, 'q': 16, 'r': 17, 's': 18, 't': 19, 'u': 20, 'v': 21, 'w': 22, 'x': 23, 'y': 24, 'z': 25, ' ': 26} +LEN = BITS // 5 + +def encode(text): + sum = 0 + for i in range(len(text)): + sum += ALPH[text[i]] * 27 ** i + return sum + +def decode(num): + text = "" + while num > 0: + text += list(ALPH.keys())[num % 27] + num //= 27 + return text + +def encrypt(text, e, n): + crypt = [] + while len(text) > 0: + if len(text) >= LEN: + crypt.append(rsa.encrypt(encode(text[:LEN]), e, n)) + text = text[LEN:] + else: + crypt.append(rsa.encrypt(encode(text), e, n)) + text = "" + return crypt + +def decrypt(crypt, d, n): + text = "" + for i in range(len(crypt)): + text += decode(rsa.decrypt(crypt[i], d, n)) + return text + +if __name__ == "__main__": + p, g = diffie.get_p_and_g(BITS) + + a = diffie.get_x(BITS) + b = diffie.get_x(BITS) + + A = diffie.get_X(a, p, g) + B = diffie.get_X(b, p, g) + + K_a = diffie.get_K(B, a, p) + K_b = diffie.get_K(A, b, p) + + e, d, n = rsa.get_keys(BITS) + + c_d = d ^ K_a + h_d = sha256(str(c_d).encode()) + + m = "hello world" + crypt = encrypt(m, e, n) + print(crypt) + print(decrypt(crypt, d, n)) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ + diff --git a/tests.py b/tests.py new file mode 100644 index 0000000..1f6516f --- /dev/null +++ b/tests.py @@ -0,0 +1,16 @@ +import lib.rsa as rsa +import lib.arithmetics as arithm +import lib.miller_rabin as miller + +for i in range(100): + for j in range(100): + assert arithm.modpow(i, j, 20) == pow(i, j, 20) + +for i in range(3, 100): + if miller.is_prime(i): print(i) + +e, d, n = rsa.get_keys(2048) +c = rsa.encrypt(22, e, n) +m = rsa.decrypt(c, d, n) +print(m) +