From 66c1b0e68b6528353df97e6f7ebdf9b730faeb21 Mon Sep 17 00:00:00 2001 From: rishabhkemni Date: Tue, 8 Oct 2024 00:09:28 +0530 Subject: [PATCH 1/5] Added new algo for RSA * Used in cryptography, the RSA algorithm is known for its complexity in terms of factoring large prime numbers --- other/RSA_Algo/rsa_algo.py | 120 +++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 other/RSA_Algo/rsa_algo.py diff --git a/other/RSA_Algo/rsa_algo.py b/other/RSA_Algo/rsa_algo.py new file mode 100644 index 000000000000..f2e0fb4e7c5d --- /dev/null +++ b/other/RSA_Algo/rsa_algo.py @@ -0,0 +1,120 @@ +import random +from sympy import isprime, mod_inverse +import sys + +def generate_prime_candidate(length): + """ + Generate a large prime number candidate. + + >>> p = generate_prime_candidate(16) + >>> isprime(p) + True + """ + p = random.getrandbits(length) + while not isprime(p): + p = random.getrandbits(length) + return p + +def generate_keys(keysize): + """ + Generate RSA keys. + + >>> public, private = generate_keys(16) + >>> len(bin(public)) - 2 # Check bit length of n + 32 + >>> len(bin(private)) - 2 # Check bit length of n + 32 + """ + try: + e = d = n = 0 + + p = generate_prime_candidate(keysize) + q = generate_prime_candidate(keysize) + + n = p * q + phi = (p - 1) * (q - 1) + + e = random.randrange(1, phi) + g = gcd(e, phi) + while g != 1: + e = random.randrange(1, phi) + g = gcd(e, phi) + + d = mod_inverse(e, phi) + + return ((e, n), (d, n)) + except Exception as ex: + print(f"Error generating keys: {ex}", file=sys.stderr) + sys.exit(1) + +def gcd(a, b): + """ + Compute the greatest common divisor of a and b. + + >>> gcd(48, 18) + 6 + """ + while b != 0: + a, b = b, a % b + return a + +def encrypt(pk, plaintext): + """ + Encrypt a message with a public key. + + >>> public, private = generate_keys(16) + >>> encrypted = encrypt(public, "test") + >>> isinstance(encrypted, list) + True + """ + try: + key, n = pk + cipher = [(ord(char) ** key) % n for char in plaintext] + return cipher + except Exception as ex: + print(f"Error during encryption: {ex}", file=sys.stderr) + return None + +def decrypt(pk, ciphertext): + """ + Decrypt a message with a private key. + + >>> public, private = generate_keys(16) + >>> encrypted = encrypt(public, "test") + >>> decrypted = decrypt(private, encrypted) + >>> decrypted == "test" + True + """ + try: + key, n = pk + plain = [chr((char ** key) % n) for char in ciphertext] + return ''.join(plain) + except Exception as ex: + print(f"Error during decryption: {ex}", file=sys.stderr) + return None + +if __name__ == '__main__': + import doctest + doctest.testmod() + + try: + keysize = 1024 + public, private = generate_keys(keysize) + + message = "Hello, RSA!" + print("Original message:", message) + + encrypted_msg = encrypt(public, message) + if encrypted_msg: + print("Encrypted message:", encrypted_msg) + + decrypted_msg = decrypt(private, encrypted_msg) + if decrypted_msg: + print("Decrypted message:", decrypted_msg) + else: + print("Decryption failed.", file=sys.stderr) + else: + print("Encryption failed.", file=sys.stderr) + except Exception as ex: + print(f"An error occurred: {ex}", file=sys.stderr) + sys.exit(1) From 2f166eb418a030a90878f3faa145a212bb844066 Mon Sep 17 00:00:00 2001 From: rishabhkemni Date: Tue, 8 Oct 2024 00:38:39 +0530 Subject: [PATCH 2/5] Updated file, added execption handling and doctest --- other/RSA_Algo/__init__.py | 0 other/RSA_Algo/rsa_algo.py | 28 +++++++++++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 other/RSA_Algo/__init__.py diff --git a/other/RSA_Algo/__init__.py b/other/RSA_Algo/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/other/RSA_Algo/rsa_algo.py b/other/RSA_Algo/rsa_algo.py index f2e0fb4e7c5d..b7e5c7cb32f2 100644 --- a/other/RSA_Algo/rsa_algo.py +++ b/other/RSA_Algo/rsa_algo.py @@ -1,6 +1,6 @@ import random -from sympy import isprime, mod_inverse import sys +from sympy import isprime, mod_inverse def generate_prime_candidate(length): """ @@ -43,8 +43,14 @@ def generate_keys(keysize): d = mod_inverse(e, phi) return ((e, n), (d, n)) + except ValueError as ex: + print(f"Value error generating keys: {ex}", file=sys.stderr) + sys.exit(1) + except TypeError as ex: + print(f"Type error generating keys: {ex}", file=sys.stderr) + sys.exit(1) except Exception as ex: - print(f"Error generating keys: {ex}", file=sys.stderr) + print(f"Unexpected error generating keys: {ex}", file=sys.stderr) sys.exit(1) def gcd(a, b): @@ -71,8 +77,11 @@ def encrypt(pk, plaintext): key, n = pk cipher = [(ord(char) ** key) % n for char in plaintext] return cipher + except TypeError as ex: + print(f"Type error during encryption: {ex}", file=sys.stderr) + return None except Exception as ex: - print(f"Error during encryption: {ex}", file=sys.stderr) + print(f"Unexpected error during encryption: {ex}", file=sys.stderr) return None def decrypt(pk, ciphertext): @@ -89,8 +98,11 @@ def decrypt(pk, ciphertext): key, n = pk plain = [chr((char ** key) % n) for char in ciphertext] return ''.join(plain) + except TypeError as ex: + print(f"Type error during decryption: {ex}", file=sys.stderr) + return None except Exception as ex: - print(f"Error during decryption: {ex}", file=sys.stderr) + print(f"Unexpected error during decryption: {ex}", file=sys.stderr) return None if __name__ == '__main__': @@ -115,6 +127,12 @@ def decrypt(pk, ciphertext): print("Decryption failed.", file=sys.stderr) else: print("Encryption failed.", file=sys.stderr) + except ValueError as ex: + print(f"Value error: {ex}", file=sys.stderr) + sys.exit(1) + except TypeError as ex: + print(f"Type error: {ex}", file=sys.stderr) + sys.exit(1) except Exception as ex: - print(f"An error occurred: {ex}", file=sys.stderr) + print(f"Unexpected error: {ex}", file=sys.stderr) sys.exit(1) From 6b3f93067c2ce632b46816be2f44c7327dd33ff1 Mon Sep 17 00:00:00 2001 From: rishabhkemni Date: Tue, 8 Oct 2024 00:45:15 +0530 Subject: [PATCH 3/5] Updated functions with return type and hints --- other/RSA_Algo/rsa_algo.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/other/RSA_Algo/rsa_algo.py b/other/RSA_Algo/rsa_algo.py index b7e5c7cb32f2..d50cf226225a 100644 --- a/other/RSA_Algo/rsa_algo.py +++ b/other/RSA_Algo/rsa_algo.py @@ -1,8 +1,9 @@ import random import sys from sympy import isprime, mod_inverse +from typing import Tuple, List -def generate_prime_candidate(length): +def generate_prime_candidate(length: int) -> int: """ Generate a large prime number candidate. @@ -15,7 +16,7 @@ def generate_prime_candidate(length): p = random.getrandbits(length) return p -def generate_keys(keysize): +def generate_keys(keysize: int) -> Tuple[Tuple[int, int], Tuple[int, int]]: """ Generate RSA keys. @@ -53,7 +54,7 @@ def generate_keys(keysize): print(f"Unexpected error generating keys: {ex}", file=sys.stderr) sys.exit(1) -def gcd(a, b): +def gcd(a: int, b: int) -> int: """ Compute the greatest common divisor of a and b. @@ -64,7 +65,7 @@ def gcd(a, b): a, b = b, a % b return a -def encrypt(pk, plaintext): +def encrypt(pk: Tuple[int, int], plaintext: str) -> List[int]: """ Encrypt a message with a public key. @@ -84,7 +85,7 @@ def encrypt(pk, plaintext): print(f"Unexpected error during encryption: {ex}", file=sys.stderr) return None -def decrypt(pk, ciphertext): +def decrypt(pk: Tuple[int, int], ciphertext: List[int]) -> str: """ Decrypt a message with a private key. From 452470a2d3925f9fa19009f41f7d4fcdb86cb6cf Mon Sep 17 00:00:00 2001 From: rishabhkemni Date: Tue, 8 Oct 2024 00:57:28 +0530 Subject: [PATCH 4/5] Removed uppercase and unwanted exceptions --- other/RSA_Algo/rsa_algo.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/other/RSA_Algo/rsa_algo.py b/other/RSA_Algo/rsa_algo.py index d50cf226225a..f220cf85c2c7 100644 --- a/other/RSA_Algo/rsa_algo.py +++ b/other/RSA_Algo/rsa_algo.py @@ -1,7 +1,8 @@ import random import sys from sympy import isprime, mod_inverse -from typing import Tuple, List +from typing import List, Tuple + def generate_prime_candidate(length: int) -> int: """ @@ -50,8 +51,8 @@ def generate_keys(keysize: int) -> Tuple[Tuple[int, int], Tuple[int, int]]: except TypeError as ex: print(f"Type error generating keys: {ex}", file=sys.stderr) sys.exit(1) - except Exception as ex: - print(f"Unexpected error generating keys: {ex}", file=sys.stderr) + except ArithmeticError as ex: + print(f"Arithmetic error generating keys: {ex}", file=sys.stderr) sys.exit(1) def gcd(a: int, b: int) -> int: @@ -81,8 +82,11 @@ def encrypt(pk: Tuple[int, int], plaintext: str) -> List[int]: except TypeError as ex: print(f"Type error during encryption: {ex}", file=sys.stderr) return None - except Exception as ex: - print(f"Unexpected error during encryption: {ex}", file=sys.stderr) + except ValueError as ex: + print(f"Value error during encryption: {ex}", file=sys.stderr) + return None + except OverflowError as ex: + print(f"Overflow error during encryption: {ex}", file=sys.stderr) return None def decrypt(pk: Tuple[int, int], ciphertext: List[int]) -> str: @@ -102,8 +106,11 @@ def decrypt(pk: Tuple[int, int], ciphertext: List[int]) -> str: except TypeError as ex: print(f"Type error during decryption: {ex}", file=sys.stderr) return None - except Exception as ex: - print(f"Unexpected error during decryption: {ex}", file=sys.stderr) + except ValueError as ex: + print(f"Value error during decryption: {ex}", file=sys.stderr) + return None + except OverflowError as ex: + print(f"Overflow error during decryption: {ex}", file=sys.stderr) return None if __name__ == '__main__': @@ -134,6 +141,6 @@ def decrypt(pk: Tuple[int, int], ciphertext: List[int]) -> str: except TypeError as ex: print(f"Type error: {ex}", file=sys.stderr) sys.exit(1) - except Exception as ex: - print(f"Unexpected error: {ex}", file=sys.stderr) + except ArithmeticError as ex: + print(f"Arithmetic error: {ex}", file=sys.stderr) sys.exit(1) From 2a1c36727ec0bf71de4cba4ad05cf1b4edff76e4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:28:11 +0000 Subject: [PATCH 5/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- other/RSA_Algo/rsa_algo.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/other/RSA_Algo/rsa_algo.py b/other/RSA_Algo/rsa_algo.py index f220cf85c2c7..c2bcb803cdc8 100644 --- a/other/RSA_Algo/rsa_algo.py +++ b/other/RSA_Algo/rsa_algo.py @@ -7,7 +7,7 @@ def generate_prime_candidate(length: int) -> int: """ Generate a large prime number candidate. - + >>> p = generate_prime_candidate(16) >>> isprime(p) True @@ -17,10 +17,11 @@ def generate_prime_candidate(length: int) -> int: p = random.getrandbits(length) return p + def generate_keys(keysize: int) -> Tuple[Tuple[int, int], Tuple[int, int]]: """ Generate RSA keys. - + >>> public, private = generate_keys(16) >>> len(bin(public)) - 2 # Check bit length of n 32 @@ -32,7 +33,7 @@ def generate_keys(keysize: int) -> Tuple[Tuple[int, int], Tuple[int, int]]: p = generate_prime_candidate(keysize) q = generate_prime_candidate(keysize) - + n = p * q phi = (p - 1) * (q - 1) @@ -55,10 +56,11 @@ def generate_keys(keysize: int) -> Tuple[Tuple[int, int], Tuple[int, int]]: print(f"Arithmetic error generating keys: {ex}", file=sys.stderr) sys.exit(1) + def gcd(a: int, b: int) -> int: """ Compute the greatest common divisor of a and b. - + >>> gcd(48, 18) 6 """ @@ -66,10 +68,11 @@ def gcd(a: int, b: int) -> int: a, b = b, a % b return a + def encrypt(pk: Tuple[int, int], plaintext: str) -> List[int]: """ Encrypt a message with a public key. - + >>> public, private = generate_keys(16) >>> encrypted = encrypt(public, "test") >>> isinstance(encrypted, list) @@ -89,10 +92,11 @@ def encrypt(pk: Tuple[int, int], plaintext: str) -> List[int]: print(f"Overflow error during encryption: {ex}", file=sys.stderr) return None + def decrypt(pk: Tuple[int, int], ciphertext: List[int]) -> str: """ Decrypt a message with a private key. - + >>> public, private = generate_keys(16) >>> encrypted = encrypt(public, "test") >>> decrypted = decrypt(private, encrypted) @@ -101,8 +105,8 @@ def decrypt(pk: Tuple[int, int], ciphertext: List[int]) -> str: """ try: key, n = pk - plain = [chr((char ** key) % n) for char in ciphertext] - return ''.join(plain) + plain = [chr((char**key) % n) for char in ciphertext] + return "".join(plain) except TypeError as ex: print(f"Type error during decryption: {ex}", file=sys.stderr) return None @@ -113,8 +117,10 @@ def decrypt(pk: Tuple[int, int], ciphertext: List[int]) -> str: print(f"Overflow error during decryption: {ex}", file=sys.stderr) return None -if __name__ == '__main__': + +if __name__ == "__main__": import doctest + doctest.testmod() try: