Added Lab2/Lab3 IS

This commit is contained in:
sherlock 2025-08-12 09:43:39 +05:30
parent 011d5aded1
commit 0755dd4b76
6 changed files with 109 additions and 140 deletions

View file

@ -5,76 +5,68 @@
def add_cipher_en(ptext, ak): def add_cipher_en(ptext, ak):
result = "" result = ""
for i in range(len(ptext)): for ch in ptext:
ch = ptext[i] if ch.isalpha():
if 32 <= ord(ch) <= 47: base = ord('A') if ch.isupper() else ord('a')
result += ch result += chr((ord(ch) - base + ak) % 26 + base)
elif 90 >= ord(ch) >= 65:
result += chr((ord(ch) + ak - 65) % 26 + 65)
else: else:
result += chr((ord(ch) + ak - 97) % 26 + 97) result += ch
return result return result
def add_cipher_de(ctext, ak): def add_cipher_de(ctext, ak):
result = "" result = ""
for i in range(len(ctext)): for ch in ctext:
ch = ctext[i] if ch.isalpha():
if 32 <= ord(ch) <= 47: base = ord('A') if ch.isupper() else ord('a')
result += ch result += chr((ord(ch) - base - ak) % 26 + base)
elif 90 >= ord(ch) >= 65:
result += chr((ord(ch) - ak - 65) % 26 + 65)
else: else:
result += chr((ord(ch) - ak - 97) % 26 + 97) result += ch
return result return result
def mult_cipher_en(ptext, mk): def mult_cipher_en(ptext, mk):
result = "" result = ""
for i in range(len(ptext)): for ch in ptext:
ch = ptext[i] if ch.isalpha():
if 32 <= ord(ch) <= 47: base = ord('A') if ch.isupper() else ord('a')
result += ch x = ord(ch) - base
elif 90 >= ord(ch) >= 65: result += chr((x * mk) % 26 + base)
result += chr((ord(ch) * mk - 65) % 26 + 65)
else: else:
result += chr((ord(ch) * mk - 97) % 26 + 97) result += ch
return result return result
def mult_cipher_de(ctext, mk): def mult_cipher_de(ctext, mk):
result = "" result = ""
inverse = pow(mk, -1, 26) inverse = pow(mk, -1, 26)
for i in range(len(ctext)): for ch in ctext:
ch = ctext[i] if ch.isalpha():
if 32 <= ord(ch) <= 47: base = ord('A') if ch.isupper() else ord('a')
result += ch x = ord(ch) - base
elif 90 >= ord(ch) >= 65: result += chr((x * inverse) % 26 + base)
result += chr((ord(ch) * inverse - 65) % 26 + 65)
else: else:
result += chr((ord(ch) * inverse - 97) % 26 + 97) result += ch
return result return result
def affine_en(ptext, ak, mk): def affine_en(ptext, ak, mk):
result = "" result = ""
for i in range(len(ptext)): for ch in ptext:
ch = ptext[i] if ch.isalpha():
if 32 <= ord(ch) <= 47: base = ord('A') if ch.isupper() else ord('a')
result += ch x = ord(ch) - base
elif 90 >= ord(ch) >= 65: result += chr(((x * mk + ak) % 26) + base)
result += chr((((ord(ch) - 65) * mk) + ak) % 26 + 65)
else: else:
result += chr((((ord(ch) - 97) * mk) + ak) % 26 + 97) result += ch
return result return result
def affine_de(ctext, ak, mk): def affine_de(ctext, ak, mk):
result = "" result = ""
inverse = pow(mk, -1, 26) inverse = pow(mk, -1, 26)
for i in range(len(ctext)): for ch in ctext:
ch = ctext[i] if ch.isalpha():
if 32 <= ord(ch) <= 47: base = ord('A') if ch.isupper() else ord('a')
result += ch x = ord(ch) - base
elif 90 >= ord(ch) >= 65: result += chr((((x - ak) * inverse) % 26) + base)
result += chr((((ord(ch) - 65 - ak) * inverse) % 26) + 65)
else: else:
result += chr((((ord(ch) - 97 - ak) * inverse) % 26) + 97) result += ch
return result return result
def mult_inverse(mk): def mult_inverse(mk):

View file

@ -1,80 +1,58 @@
def vigenere_en(ptext, vk): def vigenere_en(ptext, vk):
result = "" result = []
ptext = ptext.upper() ptext = ptext.upper()
vk = vk.upper() vk = vk.upper()
kl = len(vk)
kl = len(vk) ## key length for i, ch in enumerate(ptext):
if ch.isalpha():
for i in range(len(ptext)):
ch = ptext[i]
if 32 <= ord(ch) <= 47:
result += ch
elif 65 <= ord(ch) <= 90:
shift = (ord(vk[i % kl]) - ord('A')) % 26 shift = (ord(vk[i % kl]) - ord('A')) % 26
result += chr((ord(ch) - ord('A') + shift) % 26 + ord('A')) result.append(chr((ord(ch) - ord('A') + shift) % 26 + ord('A')))
else: else:
result += ch result.append(ch)
return ''.join(result)
return result
def vigenere_de(ctext, vk): def vigenere_de(ctext, vk):
result = "" result = []
ctext = ctext.upper() ctext = ctext.upper()
vk = vk.upper() vk = vk.upper()
kl = len(vk) kl = len(vk)
for i, ch in enumerate(ctext):
for i in range(len(ctext)): if ch.isalpha():
ch = ctext[i]
if 32 <= ord(ch) <= 47:
result += ch
elif 65 <= ord(ch) <= 90:
shift = (ord(vk[i % kl]) - ord('A')) % 26 shift = (ord(vk[i % kl]) - ord('A')) % 26
result += chr((ord(ch) - ord('A') - shift + 26) % 26 + ord('A')) result.append(chr((ord(ch) - ord('A') - shift) % 26 + ord('A')))
else: else:
result += ch result.append(ch)
return ''.join(result)
return result
def autokey_en(ptext, ak): def autokey_en(ptext, ak):
result = "" result = []
ptext = ptext.upper() ptext = ptext.upper()
current_key = ak current_key = ak
for ch in ptext:
for i in range(len(ptext)): if ch.isalpha():
ch = ptext[i]
if 32 <= ord(ch) <= 47:
result += ch
elif 65 <= ord(ch) <= 90:
shift = (current_key - ord('A')) % 26 shift = (current_key - ord('A')) % 26
cipher_char = chr((ord(ch) - ord('A') + shift) % 26 + ord('A')) cipher_char = chr((ord(ch) - ord('A') + shift) % 26 + ord('A'))
result += cipher_char result.append(cipher_char)
current_key = ord(cipher_char) current_key = ord(cipher_char)
else: else:
result += ch result.append(ch)
return ''.join(result)
return result
def autokey_de(ctext, ak): def autokey_de(ctext, ak):
result = "" result = []
ctext = ctext.upper() ctext = ctext.upper()
current_key = ak current_key = ak
for ch in ctext:
for i in range(len(ctext)): if ch.isalpha():
ch = ctext[i]
if 32 <= ord(ch) <= 47:
result += ch
elif 65 <= ord(ch) <= 90:
shift = (current_key - ord('A')) % 26 shift = (current_key - ord('A')) % 26
plain_char = chr((ord(ch) - ord('A') - shift + 26) % 26 + ord('A')) plain_char = chr((ord(ch) - ord('A') - shift) % 26 + ord('A'))
result += plain_char result.append(plain_char)
current_key = ord(plain_char) current_key = ord(plain_char)
else: else:
result += ch result.append(ch)
return ''.join(result)
return result
def operator(argument,ptext,ak,vk): def operator(argument,ptext,ak,vk):
match argument: match argument:

View file

@ -1,18 +1,14 @@
def generate_playfair_matrix(key): def generate_playfair_matrix(key):
key = ''.join(sorted(set(key.upper()), key=key.upper().index)) key = ''.join(sorted(set(key.upper()), key=key.upper().index))
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" alphabet = "ABCDEFGHIKLMNOPQRSTUVWXYZ" # J omitted
matrix = [] unique = []
for ch in key:
for char in key: if ch != 'J' and ch not in unique:
if char not in matrix and char != 'J': unique.append(ch)
matrix.append(char) for ch in alphabet:
if ch not in unique:
for char in alphabet: unique.append(ch)
if char not in matrix and char != 'J': return [unique[i:i+5] for i in range(0, 25, 5)]
matrix.append(char)
playfair_matrix = [matrix[i:i+5] for i in range(0, len(matrix), 5)]
return playfair_matrix
def find_pos(matrix, char): def find_pos(matrix, char):
for row_idx, row in enumerate(matrix): for row_idx, row in enumerate(matrix):
@ -22,16 +18,14 @@ def find_pos(matrix, char):
return None return None
def prepare_text(text): def prepare_text(text):
text = ''.join(filter(str.isalpha, text.upper())) text = ''.join(ch for ch in text.upper() if ch.isalpha()).replace('J', 'I')
text = text.replace('J', 'I') pairs, i = [], 0
pairs = []
i = 0
while i < len(text): while i < len(text):
if i + 1 < len(text) and text[i] != text[i+1]: if i + 1 < len(text) and text[i] != text[i + 1]:
pairs.append(text[i:i+2]) pairs.append(text[i:i + 2])
i += 2 i += 2
else: else:
pairs.append(text[i]+'X') pairs.append(text[i] + 'X')
i += 1 i += 1
return pairs return pairs

View file

@ -1,7 +1,7 @@
import numpy as np import numpy as np
def hill_en(ptext, hk): def hill_en(ptext, hk):
# all letters to uppercase # keep only letters and convert to uppercase
ptext = ''.join(c.upper() for c in ptext if c.isalpha()) ptext = ''.join(c.upper() for c in ptext if c.isalpha())
# matrix size # matrix size
@ -14,30 +14,34 @@ def hill_en(ptext, hk):
ptext += 'X' * (-len(ptext) % n) ptext += 'X' * (-len(ptext) % n)
# block operation # block operation
result = "" out_chars = []
for i in range(0, len(ptext), n): for i in range(0, len(ptext), n):
block = np.array([ord(c) - 65 for c in ptext[i:i+n]]) block = np.array([ord(c) - 65 for c in ptext[i:i + n]])
encrypted_block = (key @ block) % 26 encrypted_block = (key @ block) % 26
result += ''.join(chr(val + 65) for val in encrypted_block) out_chars.extend(chr(int(val) + 65) for val in encrypted_block)
return result return ''.join(out_chars)
def hill_de(ctext, hk): def hill_de(ctext, hk):
# keep only letters and convert to uppercase
ctext = ''.join(c.upper() for c in ctext if c.isalpha())
# matrix size # matrix size
n = int(len(hk)**0.5) n = int(len(hk)**0.5)
# key matrix and its inverse # key matrix and its inverse (note: not a true modular inverse; kept minimal per lab)
key = np.array([ord(c) - 65 for c in hk]).reshape(n, n) key = np.array([ord(c) - 65 for c in hk]).reshape(n, n)
inv_key = np.linalg.inv(key).astype(int) % 26 inv_key = np.linalg.inv(key)
inv_key = np.rint(inv_key).astype(int) % 26
# block operation # block operation
result = "" out_chars = []
for i in range(0, len(ctext), n): for i in range(0, len(ctext), n):
block = np.array([ord(c) - 65 for c in ctext[i:i+n]]) block = np.array([ord(c) - 65 for c in ctext[i:i + n]])
decrypted_block = (inv_key @ block) % 26 decrypted_block = (inv_key @ block) % 26
result += ''.join(chr(val + 65) for val in decrypted_block) out_chars.extend(chr(int(val) + 65) for val in decrypted_block)
return result return ''.join(out_chars)
def main(): def main():
ptext = input("Plaintext: ") ptext = input("Plaintext: ")

View file

@ -2,20 +2,19 @@ def main():
shift = (ord('C') - ord('y')) % 26 shift = (ord('C') - ord('y')) % 26
ctext = "XVIEWYWI" ctext = "XVIEWYWI"
plaintext = "" plaintext = []
for char in ctext: for ch in ctext:
if char.isalpha(): if ch.isalpha():
shifted = ord(char.lower()) - shift base = ord('a')
if shifted < ord('a'): shifted = (ord(ch.lower()) - base - shift) % 26 + base
shifted += 26 plaintext.append(chr(shifted))
plaintext += chr(shifted)
else: else:
plaintext += char plaintext.append(ch)
print(f"Attack type: Known plaintext attack") print(f"Attack type: Known plaintext attack")
print(f"Ciphertext: {ctext}") print(f"Ciphertext: {ctext}")
print(f"Decrypted: {plaintext}") print(f"Decrypted: {''.join(plaintext)}")
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View file

@ -8,23 +8,25 @@ def main():
for a in range(1, 26): for a in range(1, 26):
if gcd(a, 26) != 1: if gcd(a, 26) != 1:
continue continue
a_inv = mod_inverse(a, 26)
if a_inv is None:
continue
for b in range(26): for b in range(26):
# if key produces "ab" -> "GL" # check constraint: "ab" -> "GL" (a*0+b=6, a*1+b=11 mod 26)
if (a * 0 + b) % 26 == 6 and (a * 1 + b) % 26 == 11: if (b % 26 == 6) and ((a + b) % 26 == 11):
a_inv = mod_inverse(a, 26) decrypted = []
decrypted = "" for ch in ciphertext:
for char in ciphertext: if ch.isalpha():
if char.isalpha(): y = ord(ch.upper()) - ord('A')
y = ord(char.upper()) - ord('A')
x = (a_inv * (y - b)) % 26 x = (a_inv * (y - b)) % 26
decrypted += chr(x + ord('A')) decrypted.append(chr(x + ord('A')))
else: else:
decrypted += char decrypted.append(ch)
print(f"Key found: a={a}, b={b}") print(f"Key found: a={a}, b={b}")
print(f"Ciphertext: {ciphertext}") print(f"Ciphertext: {ciphertext}")
print(f"Decrypted: {decrypted}") print(f"Decrypted: {''.join(decrypted)}")
return return
def gcd(a, b): def gcd(a, b):