Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
5149846c61
6 changed files with 109 additions and 140 deletions
|
@ -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):
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,10 +18,8 @@ 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])
|
||||||
|
|
|
@ -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: ")
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue