예제 #1
0
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")
예제 #2
0
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))
예제 #3
0
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))
예제 #4
0
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))
예제 #5
0
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))
        
예제 #6
0
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))
예제 #7
0
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))
예제 #8
0
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))
예제 #9
0
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))
예제 #10
0
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))
예제 #11
0
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))