def recursiveKeyExample(): print("Example of the Recursive Key Cipher") print("The recursive key cipher lengthens a short key by combining it with strentched out versions of itself.") print("Here the key is TABLE\n") k1 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAATTTTT" k2 = "AAAAATTTTTAAAAABBBBBLLLLLEEEEETTTTT" k3 = "TABLETABLETABLETABLETABLETABLETABLE" n1 = alphaToNumber(k1) n2 = alphaToNumber(k2) n3 = alphaToNumber(k3) nT = [(a+b+c) % 26 for a,b,c in zip(n1,n2,n3)] kT = "".join(numberToAlpha(nT)) k1 = " TTTTT" k2 = " TTTTTAAAAABBBBBLLLLLEEEEETTTTT" k3 = "TABLETABLETABLETABLETABLETABLETABLE" print("{}\n{}\n{}\nWhich results in\n{}\n".format(k3,k2,k1,kT)) ptext = "THEQUICKBROWNFOXJUMPSOVERTHELAZYDOG" ctext, dtext = example(recursiveKey,ptext,"ZEBRAS") print(ptext) print(ctext) if dtext != ptext: print("Error")
def progressiveKey(text, key, decode=False, alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ"): # Validate the inputs validptext(text, alphabet) validkeys(key, [str, int]) if len(set(alphabet)) != len(alphabet): raise Exception("Alphabet cannot repeat any symbols") K = alphaToNumber(key[0], alphabet) pr = key[1] P = 0 T = alphaToNumber(text, alphabet) M = len(alphabet) out = [] for keynum, textnum in zip(cycle(K), T): if decode == False: out.append((textnum + keynum + P) % M) else: out.append((textnum - keynum - P) % M) if len(out) % len(K) == 0: P += pr return "".join(numberToAlpha(out, alphabet))
def autokey(text, key, decode=False, alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ", mode="vigenere"): """ :param text: The text to be encrypyed or decrypted. Must be uppercase. :param key: A keyword that is used to encrypt the first few letters. :param decode: Boolean. If false encrypt plaintext. If true decode ciphertext. :param mode: String to select between vigenere and beaufort modes. """ M = len(alphabet) validptext(text, alphabet) validkeys(key, str) if mode in ["v", "vig", "vigenere"]: mode = "vigenere" elif mode in ["b", "beau", "beaufort"]: mode = "beaufort" else: raise Exception("{} is not a valid mode".format(mode)) # Convert the text to numbers T = alphaToNumber(text, alphabet) # Conver the key to numbers K = alphaToNumber(key, alphabet) # When encoding append the text to the key, we use a different method when # decoding if decode == False: K += T out = [] if mode == "vigenere": for keynum, textnum in zip(K, T): if decode == False: out.append((textnum + keynum) % M) else: # Decode a letter then add it to the keystrean out.append((textnum - keynum) % M) K.append(out[-1]) if mode == "beaufort": for keynum, textnum in zip(K, T): if decode == False: out.append((keynum - textnum) % M) else: # Decode a letter then add it to the keystrean out.append((keynum - textnum) % M) K.append(out[-1]) return "".join(numberToAlpha(out, alphabet))
def trithemius(text, key="", decode=False): # The key is the same every time. The key argument is kept for compatibility. K = [i for i in range(26)] # Convert the text into numbers N = alphaToNumber(text) out = [] for keynum, textnum in zip(cycle(K), N): if decode == False: out.append((textnum + keynum) % 26) else: out.append((textnum - keynum) % 26) return "".join(numberToAlpha(out))
def recursiveKey(text,key,decode=False,alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ"): # Validate the inputs validptext(text,alphabet) validkeys(key,str) if len(set(alphabet)) != len(alphabet): raise Exception("Alphabet cannot repeat any symbols") nextkey = len(key) K = alphaToNumber(key,alphabet) P = [cycle(K)] T = alphaToNumber(text,alphabet) M = len(alphabet) out = [] for pos,textnum in enumerate(T): if pos == nextkey: P.append(cycle(stretch(K,nextkey))) nextkey = nextkey*2 s = 0 #for i in P: # n = next(i) # print(n,end="") # s += n #print() for i in P: s += next(i) if decode == False: out.append( (textnum+s) % M) else: out.append( (textnum-s) % M) return "".join(numberToAlpha(out,alphabet))
def affine(text, key=[0, 1], decode=False, alphabet=""): """ :param text: The text to be encrypyed. Must be alphanumeric and uppercase. The letter J will be replaced with I. :param key: A list of two integers. The first is used for multiplication. The second for addition. :param decode: Boolean. If false encrypt plaintext. If true decode ciphertext """ if alphabet == "": alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" # validptext(text, alphabet) validkeys(key, [int, int]) # The length of the alphabet and its factors M = len(alphabet) F = factors(M) # A common error for an affine cipher is using a multiplicative constant # that has no inverse modulo the length of the alphabet. That constant must # be coprime to the factors of the modulus. # For the usual 26 letter alphabet this means 13 and all even numbers are # forbidden. for fac in F: if key[0] % fac == 0: raise Exception('multiplicative part has no inverse') # Convert the text to numbers T = alphaToNumber(text, alphabet) # Get the inverse of the multiplicative constant inv = modinv(key[0], M) out = [] for textnum in T: if decode == False: out.append((textnum * key[0] + key[1]) % M) else: out.append(((textnum - key[1]) * inv) % M) return "".join(numberToAlpha(out, alphabet))
def M209(text, key, decode=False): # We need the wheels to check for possible errors Wheels = [ "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "ABCDEFGHIJKLMNOPQRSTUVXYZ", "ABCDEFGHIJKLMNOPQRSTUVX", "ABCDEFGHIJKLMNOPQRSTU", "ABCDEFGHIJKLMNOPQRS", "ABCDEFGHIJKLMNOPQ" ] # Wrong number of letters if len(key[0]) != 6: raise Exception("Key must have exactly six letters") # Check if valid letters were used in the key for i in range(6): if key[0][i] not in Wheels[i]: raise Exception("Wheel {} can only have letters in {}".format( i + 1, Wheels[i])) text = alphaToNumber(text) pins = transPins(key[1]) Lugs = lugPos(key[2]) sh = [15, 14, 13, 12, 11, 10] # For each wheel add up the shift of the wheel and the position of the key # letter that is on it. activePins = [0, 0, 0, 0, 0, 0] for wheel in range(len(Wheels)): activePins[wheel] = sh[wheel] + Wheels[wheel].index(key[0][wheel]) K = keystream(len(text), Lugs, Wheels, pins, activePins) L = [] for ltr, k in zip(text, K): s = ((25 + k) - ltr) % 26 L.append(s) return "".join(numberToAlpha(L))
def beaufort(text, key, decode=False, alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ"): """The Beaufort cipher subtracts the text from key. This makes it a reciprocal cipher that works the same when encrypting and decrypting.""" M = len(alphabet) # Validate input and convert as necessary validptext(text, alphabet) validkeys(key, str) # Convert both the text and key to a list of numbers K = cycle(alphaToNumber(key, alphabet)) T = alphaToNumber(text, alphabet) out = [] for keynum, textnum in zip(K, T): # The beaufort cipher is involutive so the decode argument is ignored # but still exist for compatibility. N = (keynum - textnum) % M out.append(N) return "".join(numberToAlpha(out, alphabet))
def caesar(text, key, decode=False, alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ"): validalpha(alphabet) validptext(text, alphabet) validkeys(key, int) M = len(alphabet) T = alphaToNumber(text, alphabet) # Allow key to be specified by letter if type(key) == str: if key in alphabet: key = alphabet.index(key) if decode == True: key = M - key out = [] for i in T: # Shift the number by the key value out.append((i + key) % M) return "".join(numberToAlpha(out, alphabet))
def vigenere(text, key, decode=False, alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ"): # Validate the inputs validptext(text, alphabet) validkeys(key, str) if len(set(alphabet)) != len(alphabet): raise Exception("Alphabet cannot repeat any symbols") K = alphaToNumber(key, alphabet) T = alphaToNumber(text, alphabet) M = len(alphabet) out = [] for keynum, textnum in zip(cycle(K), T): if decode == False: out.append((textnum + keynum) % M) else: out.append((textnum - keynum) % M) return "".join(numberToAlpha(out, alphabet))
def affineVigenere(text, key=["A", "A"], decode=False): """ :param text: The text to be encrypyed. Must be alphanumeric and uppercase. The letter J will be replaced with I. :param key: A list of two integers. The first is used for mutiplication. The second for addition. :param decode: Boolean. If false encrypt plaintext. If true decode ciphertext """ # Error if an invalid key value is used if "#" in key[0]: raise Exception('cannot use # symbol in multiplicative key') # The 37 symbol alphabet being used alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#" # Convert the plaintext and keys to lists of numbers T = alphaToNumber(text, alphabet) K1, K2, = alphaToNumber(key[0], alphabet), alphaToNumber(key[0], alphabet) out = [] # Cycle through the two keys as much as needed as we go through the key for keynum1, keynum2, textnum in zip(cycle(K1), cycle(K2), T): N = textnum # When encoding multiply and then add # When decoding multiply by the inverse then subtract if decode == False: N = (N * (keynum1 + 1)) % 37 N = (N + keynum2) % 37 else: inv = modinv(keynum1 + 1, 37) N = (N - keynum2) % 37 N = (N * inv) % 37 out.append(N) return "".join(numberToAlpha(out, alphabet))