diff --git a/.github/workflows/cs102.yml b/.github/workflows/cs102.yml index 4509ac4..44469e8 100644 --- a/.github/workflows/cs102.yml +++ b/.github/workflows/cs102.yml @@ -7,10 +7,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Set up Python 3.8.6 + - name: Set up Python 3.10 uses: actions/setup-python@v2 with: - python-version: '3.8.6' + python-version: '3.10' - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/homework01/caesar.py b/homework01/caesar.py index 09c3681..e9bd6b6 100644 --- a/homework01/caesar.py +++ b/homework01/caesar.py @@ -15,7 +15,14 @@ def encrypt_caesar(plaintext: str, shift: int = 3) -> str: '' """ ciphertext = "" - # PUT YOUR CODE HERE + for i in plaintext: + if i.isalpha(): + if i.isupper(): + ciphertext += chr((ord(i) - 65 + shift) % 26 + 65) + else: + ciphertext += chr((ord(i) - 97 + shift) % 26 + 97) + else: + ciphertext += i return ciphertext @@ -33,7 +40,14 @@ def decrypt_caesar(ciphertext: str, shift: int = 3) -> str: '' """ plaintext = "" - # PUT YOUR CODE HERE + for i in ciphertext: + if i.isalpha(): + if i.isupper(): + plaintext += chr((ord(i) - 65 - shift) % 26 + 65) + else: + plaintext += chr((ord(i) - 97 - shift) % 26 + 97) + else: + plaintext += i return plaintext diff --git a/homework01/rsa.py b/homework01/rsa.py index b777be5..c00ea06 100644 --- a/homework01/rsa.py +++ b/homework01/rsa.py @@ -13,8 +13,13 @@ def is_prime(n: int) -> bool: >>> is_prime(8) False """ - # PUT YOUR CODE HERE - pass + if n <= 1: + return False + else: + for i in range(2, int(n**0.5) + 1): + if n % i == 0: + return False + return True def gcd(a: int, b: int) -> int: @@ -26,8 +31,12 @@ def gcd(a: int, b: int) -> int: >>> gcd(3, 7) 1 """ - # PUT YOUR CODE HERE - pass + while a > 0 and b > 0: + if a > b: + a %= b + else: + b %= a + return a + b def multiplicative_inverse(e: int, phi: int) -> int: @@ -38,8 +47,16 @@ def multiplicative_inverse(e: int, phi: int) -> int: >>> multiplicative_inverse(7, 40) 23 """ - # PUT YOUR CODE HERE - pass + + def gcd_extended(e, phi): + if e != 0: + div, x, y = gcd_extended(phi % e, e) + else: + return phi, 0, 1 + return div, y - (phi // e) * x, x + + a = gcd_extended(e, phi) + return a[1] % phi def generate_keypair(p: int, q: int) -> tp.Tuple[tp.Tuple[int, int], tp.Tuple[int, int]]: @@ -49,10 +66,10 @@ def generate_keypair(p: int, q: int) -> tp.Tuple[tp.Tuple[int, int], tp.Tuple[in raise ValueError("p and q cannot be equal") # n = pq - # PUT YOUR CODE HERE + n = p * q # phi = (p-1)(q-1) - # PUT YOUR CODE HERE + phi = (p - 1) * (q - 1) # Choose an integer e such that e and phi(n) are coprime e = random.randrange(1, phi) @@ -85,7 +102,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..e6c1584 100644 --- a/homework01/vigenere.py +++ b/homework01/vigenere.py @@ -10,7 +10,15 @@ def encrypt_vigenere(plaintext: str, keyword: str) -> str: 'LXFOPVEFRNHR' """ ciphertext = "" - # PUT YOUR CODE HERE + for j in range(len(plaintext)): + i = plaintext[j] + if i.isalpha(): + if i.isupper(): + ciphertext += chr((ord(i) + ord(keyword[j % len(keyword)]) - 130) % 26 + 65) + else: + ciphertext += chr((ord(i) + ord(keyword[j % len(keyword)]) - 194) % 26 + 97) + else: + ciphertext += i return ciphertext @@ -26,5 +34,13 @@ def decrypt_vigenere(ciphertext: str, keyword: str) -> str: 'ATTACKATDAWN' """ plaintext = "" - # PUT YOUR CODE HERE + for j in range(len(ciphertext)): + i = ciphertext[j] + if i.isalpha(): + if i.isupper(): + plaintext += chr((ord(i) - ord(keyword[j % len(keyword)])) % 26 + 65) + else: + plaintext += chr((ord(i) - ord(keyword[j % len(keyword)])) % 26 + 97) + else: + plaintext += i return plaintext