Open neuroretransmit opened 7 months ago
After seeing many examples and explanations on the internet, here are some implementation ideas for some of these missing encryption types:
affine
def affine(text, a, b, decrypt=False):
if not (a and b):
raise ValueError("Values for 'a' and 'b' must be provided for affine cipher.")
if decrypt:
a_inv = 0
for i in range(26):
if (a * i) % 26 == 1:
a_inv = i
break
if not a_inv:
raise ValueError("Invalid 'a' value for decryption in affine cipher.")
b = -a_inv * b
result = []
for char in text:
if char.isalpha():
if char.islower():
result.append(chr(((a_inv * (ord(char) - ord('a') - b)) % 26) + ord('a')))
else:
result.append(chr(((a_inv * (ord(char) - ord('A') - b)) % 26) + ord('A')))
else:
result.append(char)
return ''.join(result)
autokey
def autokey(text, key, decrypt=False):
result = []
key_index = 0
for char in text:
if char.isalpha():
if decrypt:
key_char = key[key_index]
else:
key_char = char
key_index += 1
if key_index == len(key):
key_index = 0
shift = ord(key_char.lower()) - ord('a')
if char.islower():
result.append(chr(((ord(char) - ord('a') - shift) % 26) + ord('a')))
else:
result.append(chr(((ord(char) - ord('A') - shift) % 26) + ord('A')))
else:
result.append(char)
return ''.join(result)
beaufort
def beaufort(text, key, decrypt=False):
if not key:
raise ValueError("Key must be provided for Beaufort cipher.")
result = []
for char, key_char in zip(text, key):
if char.isalpha():
shift = ord(key_char.lower()) - ord('a')
if decrypt:
shift *= -1
if char.islower():
result.append(chr(((ord(char) - ord('a') - shift) % 26) + ord('a')))
else:
result.append(chr(((ord(char) - ord('A') - shift) % 26) + ord('A')))
else:
result.append(char)
return ''.join(result)
caesar
def caesar(text, shift, decrypt=False):
if decrypt:
shift = -shift
result = []
for char in text:
if char.isalpha():
if char.islower():
result.append(chr(((ord(char) - ord('a') + shift) % 26) + ord('a')))
else:
result.append(chr(((ord(char) - ord('A') + shift) % 26) + ord('A')))
else:
result.append(char)
return ''.join(result)
chaocipher
def chaocipher(text, key1, key2):
if not (key1 and key2):
raise ValueError("Key1 and Key2 must be provided for Chaocipher.")
result = []
for char in text:
if char.isalpha():
if char.islower():
index = ord(char) - ord('a')
result.append(key2[index])
else:
index = ord(char) - ord('A')
result.append(key1[index])
else:
result.append(char)
return ''.join(result)
hill
def hill(text, key, decrypt=False):
n = len(key)
if not (n > 1 and n % 2 == 0):
raise ValueError("Key must be a 2x2 matrix for Hill cipher.")
det = key[0][0] * key[1][1] - key[0][1] * key[1][0]
det_inv = None
for i in range(26):
if (det * i) % 26 == 1:
det_inv = i
break
if not det_inv:
raise ValueError("Invalid key for Hill cipher.")
if decrypt:
key = [[key[1][1], -key[0][1]], [-key[1][0], key[0][0]]]
key = [[(det_inv * x) % 26 for x in row] for row in key]
result = []
for i in range(0, len(text), 2):
a = ord(text[i]) - ord('A')
b = ord(text[i + 1]) - ord('A')
if decrypt:
result.append(chr(((key[0][0] * a + key[0][1] * b) % 26) + ord('A')))
result.append(chr(((key[1][0] * a + key[1][1] * b) % 26) + ord('A')))
else:
result.append(chr(((key[0][0] * a + key[0][1] * b) % 26) + ord('A')))
result.append(chr(((key[1][0] * a + key[1][1] * b) % 26) + ord('A')))
return ''.join(result)
trimethius
def trimethius(text, key, decrypt=False):
def generate_key_stream(key, length):
key_stream = ''
while len(key_stream) < length:
key_stream += key
return key_stream[:length]
def shift(char, shift_amount, decrypt=False):
if decrypt:
shift_amount = -shift_amount
return chr(((ord(char) - ord('A') + shift_amount) % 26) + ord('A'))
if not key:
raise ValueError("Key must be provided for Trimethius cipher.")
key_stream = generate_key_stream(key.upper(), len(text))
result = ''
for i in range(len(text)):
if text[i].isalpha():
shift_amount = ord(key_stream[i]) - ord('A')
result += shift(text[i].upper(), shift_amount, decrypt)
else:
result += text[i]
return result
After seeing many examples and explanations on the internet, here are some implementation ideas for some of these missing encryption types:
affine
def affine(text, a, b, decrypt=False): if not (a and b): raise ValueError("Values for 'a' and 'b' must be provided for affine cipher.") if decrypt: a_inv = 0 for i in range(26): if (a * i) % 26 == 1: a_inv = i break if not a_inv: raise ValueError("Invalid 'a' value for decryption in affine cipher.") b = -a_inv * b result = [] for char in text: if char.isalpha(): if char.islower(): result.append(chr(((a_inv * (ord(char) - ord('a') - b)) % 26) + ord('a'))) else: result.append(chr(((a_inv * (ord(char) - ord('A') - b)) % 26) + ord('A'))) else: result.append(char) return ''.join(result)
autokey
def autokey(text, key, decrypt=False): result = [] key_index = 0 for char in text: if char.isalpha(): if decrypt: key_char = key[key_index] else: key_char = char key_index += 1 if key_index == len(key): key_index = 0 shift = ord(key_char.lower()) - ord('a') if char.islower(): result.append(chr(((ord(char) - ord('a') - shift) % 26) + ord('a'))) else: result.append(chr(((ord(char) - ord('A') - shift) % 26) + ord('A'))) else: result.append(char) return ''.join(result)
beaufort
def beaufort(text, key, decrypt=False): if not key: raise ValueError("Key must be provided for Beaufort cipher.") result = [] for char, key_char in zip(text, key): if char.isalpha(): shift = ord(key_char.lower()) - ord('a') if decrypt: shift *= -1 if char.islower(): result.append(chr(((ord(char) - ord('a') - shift) % 26) + ord('a'))) else: result.append(chr(((ord(char) - ord('A') - shift) % 26) + ord('A'))) else: result.append(char) return ''.join(result)
caesar
def caesar(text, shift, decrypt=False): if decrypt: shift = -shift result = [] for char in text: if char.isalpha(): if char.islower(): result.append(chr(((ord(char) - ord('a') + shift) % 26) + ord('a'))) else: result.append(chr(((ord(char) - ord('A') + shift) % 26) + ord('A'))) else: result.append(char) return ''.join(result)
chaocipher
def chaocipher(text, key1, key2): if not (key1 and key2): raise ValueError("Key1 and Key2 must be provided for Chaocipher.") result = [] for char in text: if char.isalpha(): if char.islower(): index = ord(char) - ord('a') result.append(key2[index]) else: index = ord(char) - ord('A') result.append(key1[index]) else: result.append(char) return ''.join(result)
hill
def hill(text, key, decrypt=False): n = len(key) if not (n > 1 and n % 2 == 0): raise ValueError("Key must be a 2x2 matrix for Hill cipher.") det = key[0][0] * key[1][1] - key[0][1] * key[1][0] det_inv = None for i in range(26): if (det * i) % 26 == 1: det_inv = i break if not det_inv: raise ValueError("Invalid key for Hill cipher.") if decrypt: key = [[key[1][1], -key[0][1]], [-key[1][0], key[0][0]]] key = [[(det_inv * x) % 26 for x in row] for row in key] result = [] for i in range(0, len(text), 2): a = ord(text[i]) - ord('A') b = ord(text[i + 1]) - ord('A') if decrypt: result.append(chr(((key[0][0] * a + key[0][1] * b) % 26) + ord('A'))) result.append(chr(((key[1][0] * a + key[1][1] * b) % 26) + ord('A'))) else: result.append(chr(((key[0][0] * a + key[0][1] * b) % 26) + ord('A'))) result.append(chr(((key[1][0] * a + key[1][1] * b) % 26) + ord('A'))) return ''.join(result)
trimethius
def trimethius(text, key, decrypt=False): def generate_key_stream(key, length): key_stream = '' while len(key_stream) < length: key_stream += key return key_stream[:length] def shift(char, shift_amount, decrypt=False): if decrypt: shift_amount = -shift_amount return chr(((ord(char) - ord('A') + shift_amount) % 26) + ord('A')) if not key: raise ValueError("Key must be provided for Trimethius cipher.") key_stream = generate_key_stream(key.upper(), len(text)) result = '' for i in range(len(text)): if text[i].isalpha(): shift_amount = ord(key_stream[i]) - ord('A') result += shift(text[i].upper(), shift_amount, decrypt) else: result += text[i] return result
This is great work. As we only need decryptions, I'd recommend stripping out the encryption side and aligning method signatures to how we are calling other crypto functions. Thanks @d4v1-sudo
Removing the encryption part - leaving only the decryption part, trying to aligning method signatures to how we are calling other crypto functions and adding more types of decryption :
affine
def affine(text, a, b):
if not (a and b):
raise ValueError("Values for 'a' and 'b' must be provided for affine cipher decryption.")
a_inv = 0
for i in range(26):
if (a * i) % 26 == 1:
a_inv = i
break
if not a_inv:
raise ValueError("Invalid 'a' value for decryption in affine cipher.")
b = -a_inv * b
result = []
for char in text:
if char.isalpha():
if char.islower():
result.append(chr(((a_inv * (ord(char) - ord('a') - b)) % 26) + ord('a')))
else:
result.append(chr(((a_inv * (ord(char) - ord('A') - b)) % 26) + ord('A')))
else:
result.append(char)
return ''.join(result)
autokey
def autokey(text, key):
result = []
key_index = 0
for char in text:
if char.isalpha():
key_char = key[key_index]
key_index += 1
if key_index == len(key):
key_index = 0
shift = ord(key_char.lower()) - ord('a')
if char.islower():
result.append(chr(((ord(char) - ord('a') - shift) % 26) + ord('a')))
else:
result.append(chr(((ord(char) - ord('A') - shift) % 26) + ord('A')))
else:
result.append(char)
return ''.join(result)
beaufort
def beaufort(text, key):
if not key:
raise ValueError("Key must be provided for Beaufort cipher decryption.")
result = []
for char, key_char in zip(text, key):
if char.isalpha():
shift = ord(key_char.lower()) - ord('a')
if char.islower():
result.append(chr(((ord(char) - ord('a') - shift) % 26) + ord('a')))
else:
result.append(chr(((ord(char) - ord('A') - shift) % 26) + ord('A')))
else:
result.append(char)
return ''.join(result)
chaocipher
def chaocipher(text, key1, key2):
if not (key1 and key2):
raise ValueError("Key1 and Key2 must be provided for Chaocipher decryption.")
result = []
for char in text:
if char.isalpha():
if char.islower():
index = ord(char) - ord('a')
result.append(key2[index])
else:
index = ord(char) - ord('A')
result.append(key1[index])
else:
result.append(char)
return ''.join(result)
hill
def hill(text, key):
n = len(key)
if not (n > 1 and n % 2 == 0):
raise ValueError("Key must be a 2x2 matrix for Hill cipher decryption.")
det = key[0][0] * key[1][1] - key[0][1] * key[1][0]
det_inv = None
for i in range(26):
if (det * i) % 26 == 1:
det_inv = i
break
if not det_inv:
raise ValueError("Invalid key for Hill cipher decryption.")
key = [[key[1][1], -key[0][1]], [-key[1][0], key[0][0]]]
key = [[(det_inv * x) % 26 for x in row] for row in key]
result = []
for i in range(0, len(text), 2):
a = ord(text[i]) - ord('A')
b = ord(text[i + 1]) - ord('A')
result.append(chr(((key[0][0] * a + key[0][1] * b) % 26) + ord('A')))
result.append(chr(((key[1][0] * a + key[1][1] * b) % 26) + ord('A')))
return ''.join(result)
trimethius
def trimethius(text, key):
def generate_key_stream(key, length):
key_stream = ''
while len(key_stream) < length:
key_stream += key
return key_stream[:length]
def shift(char, shift_amount):
return chr(((ord(char) - ord('A') + shift_amount) % 26) + ord('A'))
if not key:
raise ValueError("Key must be provided for Trimethius cipher decryption.")
key_stream = generate_key_stream(key.upper(), len(text))
result = ''
for i in range(len(text)):
if text[i].isalpha():
shift_amount = ord(key_stream[i]) - ord('A')
result += shift(text[i].upper(), shift_amount)
else:
result += text[i]
return result
caesar_box
def caesar_box(text, key):
rows = key
cols = len(text) // key
result = [''] * len(text)
for r in range(rows):
for c in range(cols):
result[c * rows + r] = text[r * cols + c]
return ''.join(result)
columnar_transposition
def columnar_transposition(text, key):
key_order = sorted(range(len(key)), key=lambda k: key[k])
num_cols = len(key)
num_rows = -(-len(text) // num_cols)
grid = [[''] * num_cols for _ in range(num_rows)]
for i, char in enumerate(text):
grid[i // num_cols][key_order[i % num_cols]] = char
result = ''
for col in range(num_cols):
for row in range(num_rows):
result += grid[row][col]
return result
double
def double(text, key1, key2):
return caesar_box(columnar_transposition(text, key2), key1)
myszkowski
def myszkowski(text, key):
sorted_key = sorted(key)
num_cols = len(key)
num_rows = -(-len(text) // num_cols)
sorted_key_index = {k: i for i, k in enumerate(sorted_key)}
last_row_fill = len(text) % num_cols
grid = [[''] * num_cols for _ in range(num_rows)]
index = 0
for col in range(num_cols):
for row in range(num_rows):
if row == num_rows - 1 and col >= last_row_fill:
continue
grid[row][sorted_key_index[key[col]]] = text[index]
index += 1
result = ''
for row in range(num_rows):
for col in range(num_cols):
result += grid[row][col]
return result
railfence
def railfence(text, key):
fence = [['' for _ in range(len(text))] for _ in range(key)]
rail = 0
direction = 1
for char in text:
fence[rail][direction] = char
rail += direction
if rail == key - 1 or rail == 0:
direction = -direction
result = ''
for i in range(key):
for j in range(len(text)):
if fence[i][j]:
result += fence[i][j]
return result
route
def route(text, key):
num_rows = len(text) // key
remainder = len(text) % key
rows = [num_rows] * key
for i in range(remainder):
rows[i] += 1
index = 0
grid = [[''] * len(text) for _ in range(key)]
for r in range(key):
for c in range(rows[r]):
grid[r][c] = text[index]
index += 1
result = ''
for c in range(len(text)):
for r in range(key):
if grid[r][c]:
result += grid[r][c]
return result
concealment
def concealment(text, key):
chunks = [text[i:i + key] for i in range(0, len(text), key)]
max_len = max(map(len, chunks))
padded_chunks = [chunk.ljust(max_len, ' ') for chunk in chunks]
result = ''
for i in range(max_len):
for chunk in padded_chunks:
if chunk[i] != ' ':
result += chunk[i]
return result
Self explanatory, use the generic cradle of the spec to align their method signatures to the
SolutionSpec
run() function to be run in the genetic algorithm's evolve loop when offspring.rate() is called.