diff --git a/algorithms/cryptography/shor_algorithm.py b/algorithms/cryptography/shor_algorithm.py new file mode 100644 index 000000000000..1cdefaa3c0fb --- /dev/null +++ b/algorithms/cryptography/shor_algorithm.py @@ -0,0 +1,61 @@ +import math +import random + + +def gcd(a, b): + """Computes the greatest common divisor using Euclidean algorithm.""" + while b: + a, b = b, a % b + return a + + +def modular_exponentiation(base, exp, mod): + """Computes (base^exp) % mod using fast modular exponentiation.""" + result = 1 + while exp > 0: + if exp % 2 == 1: + result = (result * base) % mod + base = (base * base) % mod + exp //= 2 + return result + + +def find_order(a, N): + """Finds the smallest r such that a^r ≡ 1 (mod N)""" + r = 1 + while modular_exponentiation(a, r, N) != 1: + r += 1 + if r > N: # Prevent infinite loops + return None + return r + + +def shor_algorithm(N): + """Simulates Shor’s Algorithm classically to factorize N.""" + if N % 2 == 0: + return 2, N // 2 # Trivial case if N is even + + while True: + a = random.randint(2, N - 1) + factor = gcd(a, N) + if factor > 1: + return factor, N // factor # Lucky case: a and N are not coprime + + r = find_order(a, N) + if r is None or r % 2 == 1: + continue # Retry if order is not even + + factor1 = gcd(modular_exponentiation(a, r // 2, N) - 1, N) + factor2 = gcd(modular_exponentiation(a, r // 2, N) + 1, N) + + if 1 < factor1 < N: + return factor1, N // factor1 + if 1 < factor2 < N: + return factor2, N // factor2 + + +# Example usage +if __name__ == "__main__": + N = 15 # You can test with 21, 35, 55, etc. + factors = shor_algorithm(N) + print(f"Factors of {N}: {factors}")