diff --git a/homework01/caesar.py b/homework01/caesar.py index 09c3681..f110e69 100644 --- a/homework01/caesar.py +++ b/homework01/caesar.py @@ -2,39 +2,39 @@ def encrypt_caesar(plaintext: str, shift: int = 3) -> str: - """ - Encrypts plaintext using a Caesar cipher. - - >>> encrypt_caesar("PYTHON") - 'SBWKRQ' - >>> encrypt_caesar("python") - 'sbwkrq' - >>> encrypt_caesar("Python3.6") - 'Sbwkrq3.6' - >>> encrypt_caesar("") - '' - """ ciphertext = "" - # PUT YOUR CODE HERE + if shift < 0: + shift = 26 + shift + a = [] + for i in range(len(plaintext)): + if plaintext[i].isalpha(): + a.append(ord(plaintext[i])) + else: + a.append(ord(plaintext[i]) - shift) + for i in range(len(a)): + temp = a[i] + shift + if plaintext[i].isalpha(): + if a[i] >= ord("a") and a[i] <= ord("z"): + # Маленькие буквы + if temp > ord("z"): + a[i] = shift - (ord("z") - a[i]) + ord("a") - 1 + else: + a[i] = a[i] + shift + else: + # Большие буквы + if temp > ord("Z"): + a[i] = shift - (ord("Z") - a[i]) + ord("A") - 1 + else: + a[i] = a[i] + shift + else: + a[i] = a[i] + shift + for i in range(len(a)): + ciphertext += chr(a[i]) return ciphertext def decrypt_caesar(ciphertext: str, shift: int = 3) -> str: - """ - Decrypts a ciphertext using a Caesar cipher. - - >>> decrypt_caesar("SBWKRQ") - 'PYTHON' - >>> decrypt_caesar("sbwkrq") - 'python' - >>> decrypt_caesar("Sbwkrq3.6") - 'Python3.6' - >>> decrypt_caesar("") - '' - """ - plaintext = "" - # PUT YOUR CODE HERE - return plaintext + return encrypt_caesar(ciphertext, -shift) def caesar_breaker_brute_force(ciphertext: str, dictionary: tp.Set[str]) -> int: diff --git a/homework01/rsa.py b/homework01/rsa.py index b777be5..e87f80f 100644 --- a/homework01/rsa.py +++ b/homework01/rsa.py @@ -3,43 +3,37 @@ def is_prime(n: int) -> bool: - """ - Tests to see if a number is prime. - - >>> is_prime(2) - True - >>> is_prime(11) - True - >>> is_prime(8) - False - """ - # PUT YOUR CODE HERE - pass + if n == 1: + return False + for i in range(2, n - 1): + if n % i == 0: + return False + return True def gcd(a: int, b: int) -> int: - """ - Euclid's algorithm for determining the greatest common divisor. + if a == 0 or b == 0: + return max(a, b) + max_del = 1 + for i in range(1, min(a, b)): + if a % i == 0 and b % i == 0 and i > max_del: + max_del = i + return max_del - >>> gcd(12, 15) - 3 - >>> gcd(3, 7) - 1 - """ - # PUT YOUR CODE HERE - pass +def extended_gcd(a: int, b: int): + if a == 0: + return (b, 0, 1) + temp = extended_gcd(b % a, a) + return (temp[0], temp[2] - (b // a) * temp[1], temp[1]) -def multiplicative_inverse(e: int, phi: int) -> int: - """ - Euclid's extended algorithm for finding the multiplicative - inverse of two numbers. - >>> multiplicative_inverse(7, 40) - 23 - """ - # PUT YOUR CODE HERE - pass +def multiplicative_inverse(e: int, phi: int) -> int: + gcd_res = extended_gcd(e, phi) + if gcd_res[1] >= 0: + return gcd_res[1] + else: + return gcd_res[1] + max(e, phi) def generate_keypair(p: int, q: int) -> tp.Tuple[tp.Tuple[int, int], tp.Tuple[int, int]]: @@ -47,25 +41,17 @@ def generate_keypair(p: int, q: int) -> tp.Tuple[tp.Tuple[int, int], tp.Tuple[in raise ValueError("Both numbers must be prime.") elif p == q: raise ValueError("p and q cannot be equal") - - # n = pq - # PUT YOUR CODE HERE - - # phi = (p-1)(q-1) - # PUT YOUR CODE HERE - + n = p * q + phi = (p - 1) * (q - 1) # Choose an integer e such that e and phi(n) are coprime e = random.randrange(1, phi) - # Use Euclid's Algorithm to verify that e and phi(n) are coprime g = gcd(e, phi) while g != 1: e = random.randrange(1, phi) g = gcd(e, phi) - # Use Extended Euclid's Algorithm to generate the private key d = multiplicative_inverse(e, phi) - # Return public and private keypair # Public key is (e, n) and private key is (d, n) return ((e, n), (d, n)) @@ -85,7 +71,7 @@ def decrypt(pk: tp.Tuple[int, int], ciphertext: tp.List[int]) -> str: # Unpack the key into its components key, n = pk # Generate the plaintext based on the ciphertext and key using a^b mod m - plain = [chr((char ** key) % n) for char in ciphertext] + plain = [chr((char**key) % n) for char in ciphertext] # Return the array of bytes as a string return "".join(plain) diff --git a/homework01/vigenere.py b/homework01/vigenere.py index e51742e..dd2f653 100644 --- a/homework01/vigenere.py +++ b/homework01/vigenere.py @@ -1,30 +1,64 @@ def encrypt_vigenere(plaintext: str, keyword: str) -> str: - """ - Encrypts plaintext using a Vigenere cipher. - - >>> encrypt_vigenere("PYTHON", "A") - 'PYTHON' - >>> encrypt_vigenere("python", "a") - 'python' - >>> encrypt_vigenere("ATTACKATDAWN", "LEMON") - 'LXFOPVEFRNHR' - """ ciphertext = "" - # PUT YOUR CODE HERE + + for i in range(len(plaintext)): + l = ord(plaintext[i]) + shift = ord(keyword[i % len(keyword)]) # смещене + + k = ord(keyword[i % len(keyword)]) # порядковый номер, A-Z, a-z + if k >= ord("a") and k <= ord("z"): + shift -= ord("a") + else: + shift -= ord("A") + + if plaintext[i].isalpha(): + if l >= ord("a") and l <= ord("z"): + temp = l + shift + if temp > ord("z"): + ciphertext += chr(shift - (ord("z") - l) + ord("a") - 1) + else: + ciphertext += chr(temp) + else: + temp = l + shift + if temp > ord("Z"): + ciphertext += chr(shift - (ord("Z") - l) + ord("A") - 1) + else: + ciphertext += chr(temp) + else: + ciphertext += plaintext[i] + return ciphertext def decrypt_vigenere(ciphertext: str, keyword: str) -> str: - """ - Decrypts a ciphertext using a Vigenere cipher. - - >>> decrypt_vigenere("PYTHON", "A") - 'PYTHON' - >>> decrypt_vigenere("python", "a") - 'python' - >>> decrypt_vigenere("LXFOPVEFRNHR", "LEMON") - 'ATTACKATDAWN' - """ - plaintext = "" - # PUT YOUR CODE HERE - return plaintext + ciphertexttext = "" + + for i in range(len(ciphertext)): + l = ord(ciphertext[i]) + shift = ord(keyword[i % len(keyword)]) + + k = ord(keyword[i % len(keyword)]) + if k >= ord("a") and k <= ord("z"): + shift -= ord("a") + else: + shift -= ord("A") + + shift = 26 - shift + + if ciphertext[i].isalpha(): + if l >= ord("a") and l <= ord("z"): + temp = l + shift + if temp > ord("z"): + ciphertexttext += chr(shift - (ord("z") - l) + ord("a") - 1) + else: + ciphertexttext += chr(temp) + else: + temp = l + shift + if temp > ord("Z"): + ciphertexttext += chr(shift - (ord("Z") - l) + ord("A") - 1) + else: + ciphertexttext += chr(temp) + else: + ciphertexttext += ciphertext[i] + + return ciphertexttext