def vigenere(text, key, encOrDec): """ Description: A cipher that uses a tabula recta to encode text. Encoding equation: (letter + key_letter) % 26 Decoding equation: (letter - key_letter) % 26 """ text = ltn(text) key = ltnKey(key) result = [] counter = 0 enOrDec = -1 if encOrDec else 1 #True for decode, False for encode for x in text: if counter == len(key): counter = 0 if type(x) == int: result.append((x + (key[counter] * enOrDec)) % 26) counter += 1 else: result.append(x) return ntl(result)
def beaufort(text, key): """ Description: A cipher that uses a tabula recta to encode/decode text. It's quite similar to Vignere, but its table starts from "Z" rather than "A". Equation: (key letter - letter) % 26 Doctests: >>> beaufort("this is a test with a weak key.", "key") 'rxqs wg k lusl cclr k iuku ogg.' >>> beaufort("rxqs wg k lusl cclr k iuku ogg.", "key") 'this is a test with a weak key.' >>> beaufort("abc", "defghijklmnop") 'ddd' """ text = ltn(text) key = ltnKey(key) result = [] counter = 0 for x in text: if counter == len(key): counter = 0 if type(x) == int: result.append((key[counter] - x) % 26) counter += 1 else: result.append(x) return ntl(result)
def affine(text, multiplier, shift, encOrDec): """ Description: A cipher similar to Caesar Shift, but uses a multiplier to further alter the text. Note that the multiplier MUST be coprime to the alphabet size, as using an improper multiplier will result in problems when decoding. Program Notes: For the boolean variable encOrDec, False will encode text and True will decode text. The multiplier inverse is derived by finding a number between 1 and 25 that satisfies this equation: number * multiplier % 26 == 1 Encoding equation: (multiplier * [individual letter] + shift) % [alphabet size] Decoding equation: (multiplier inverse * ([individual letter] - shift) % [alphabet size] Doctests: >>> affine("this is a test!", 3, 15, False) 'uknr nr p ubru!' >>> affine("uknr nr p ubru!", 3, 15, True) 'this is a test! >>> affine("", 1, 3, False) '' >>> affine("lorem ipsum dolor sit amet", 41, 9, False) 'slerh zatxh clsle tzi jhri' >>> affine("slerh zatxh clsle tzi jhri", 41, 9, True) """ assert any([1 if multiplier % x == 0 else 0 for x in [2, 13, 26] ]) != True, "Multiplier must be coprime to 26!" assert 0 < shift < 26, "Shift must be between 1 and 25!" result = [] if encOrDec: for n in range(1, 26): if n * multiplier % 26 == 1: multiplierInverse = n break formula = (lambda x: (multiplierInverse * (x - shift)) % 26) else: formula = (lambda x: (multiplier * x + shift) % 26) for x in ltn(text): if type(x) == int: result.append(formula(x)) else: result.append(x) return ntl(result)
def atbash(text): """ Description: A cipher that replaces each letter in text with its "opposite" letter. Equation: (abs(letter_position - 25)) Doctests: >>> atbash("abcdefghijklmnopqrstuvwxyz") 'zyxwvutsrqponmlkjihgfedcba' """ nums = [] for x in ltn(text): if type(x) == int: nums.append(abs(x - 25)) else: nums.append(x) return ntl(nums)
def caesar(text, shift): """ Description: A cipher that shifts each letter by n positions. Equation: (letter + shift) % 26 Test Cases: >>> caesar("abcdefghijklmnopqrstuvwxyz", 1) 'bcdefghijklmnopqrstuvwxyza' >>> caesar("abcdefghijklmnopqrstuvwxyz", 25) 'zabcdefghijklmnopqrstuvwxy' >>> caesar("abcdefghijklmnopqrstuvwxyz", 13) 'nopqrstuvwxyzabcdefghijklm' """ assert 0 < shift < 26, "Shift must be between 1 and 25!" nums = [] for x in ltn(text): if type(x) == int: nums.append((x + shift) % 26) else: nums.append(x) return ntl(nums)