예제 #1
0
def quagmire4(text, keys, decode=False, alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ"):

    key1 = alphabetPermutation(keys[0], alphabet)
    key2 = alphabetPermutation(keys[1], alphabet)
    M = len(alphabet)
    indicator = keys[2]

    table = []

    for lt in indicator:
        sh = key2.index(lt) % M
        table.append(key2[sh:] + key2[:sh])

    out = []
    if decode == False:
        for ctr, ltr in enumerate(text):
            t = table[ctr % len(indicator)]
            out.append(t[key1.index(ltr)])

    if decode == True:
        for ctr, ltr in enumerate(text):
            t = table[ctr % len(indicator)]
            out.append(key1[t.index(ltr)])

    return "".join(out)
예제 #2
0
def chaocipher(text, keys=["", ""], decode=False):

    if keys[0] == "":
        L = "ABCDEFGHIJKLMONPQRSTUVWXYZ"
    else:
        L = alphabetPermutation(keys[0])

    if keys[1] == "":
        R = "ABCDEFGHIJKLMONPQRSTUVWXYZ"
    else:
        R = alphabetPermutation(keys[1])

    validptext(text, "ABCDEFGHIJKLMONPQRSTUVWXYZ")
    validkeys(keys, [str, str])

    if decode == False:
        out = ""
        for letter in text:
            pos = R.index(letter)
            out += L[pos]
            L = permuteL(L, L[pos])
            R = permuteR(R, letter)
        return out

    if decode == True:
        out = ""
        for letter in text:
            pos = L.index(letter)
            out += R[pos]
            L = permuteL(L, letter)
            R = permuteR(R, R[pos])

        return out
예제 #3
0
def straddlingCheckerboard(text,keys=["A",[0,1]],decode=False,alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ"):

    if len(keys) != 2:
        raise Exception('must provide both keys')
    if len(keys[1]) != 2:
        raise Exception('must provide two numbers for checkboard')
    
    # Derive the internally used key from the input
    KEY = alphabetPermutation(keys[0],alphabet)
    # Divide they KEY into a mutable list so we can pop from it
    KEY = list(KEY)
    D = {}
    
    if decode == False:

        # First row of the checkerboard
        for i in range(10):
            if i not in keys[1]:
                D[KEY.pop(0)] = str(i)
        
        # Second row
        for i in range(10):
            codegroup = str(keys[1][0])+str(i)
            D[KEY.pop(0)] = codegroup

        # Third row   
        for i in range(len(KEY)):
            codegroup = str(keys[1][1])+str(i)
            D[KEY.pop(0)] = codegroup

        return "".join([D[letter] for letter in text])
    
    if decode == True:
        # First row of the checkerboard
        for i in range(10):
            if i not in keys[1]:
                D[str(i)] = KEY.pop(0)
        
        # Second row
        for i in range(10):
            codegroup = str(keys[1][0])+str(i)
            D[codegroup] = KEY.pop(0)

        # Third row   
        for i in range(len(KEY)):
            codegroup = str(keys[1][1])+str(i)
            D[codegroup] = KEY.pop(0)
        
        L = []
        text = [sym for sym in text]

        while len(text) > 0:
            if text[0] in str(keys[1]):
                L.append(text.pop(0)+text.pop(0))
            else:
                L.append(text.pop(0))

        return "".join([D[i] for i in L])
예제 #4
0
def cipherDisk(text, key=["", "A"], decode=False, gaprange=[5, 9], turn=0):

    # The outer ring is in order
    outer = "ABCDEFGHIJKLMONPQRSTUVWXYZ0123456789"

    # Determine the inner ring
    if key[0] == "":
        inner = outer
    else:
        inner = alphabetPermutation(key[0], outer)

    if key[1] not in outer:
        raise Exception("Start position must exist in the inner ring.")

    # Turn the inner ring until the correct symbol is in the first position
    while inner[0] != key[1]:
        inner = stepN(inner, 1)

    out = []
    if decode == False:

        # Raise an error if there are digits in the plaintext since they will
        # cause decoding errors.
        for i in "0123456789":
            if i in text:
                raise Exception("Cannot include numbers in the plaintext.")

        # Choose were the first gap is
        gap = random.randint(gaprange[0], gaprange[1])
        for i in text:
            # Encrypt letters one by one and count down to the gap
            out.append(inner[outer.index(i)])
            gap -= 1
            if gap == 0:
                # If we reached the gap encrypt a number, turn the wheel, and
                # choose the size of the next gap
                R = random.choice("0123456789")
                out += inner[outer.index(R)]
                inner = stepN(inner, int(R))
                gap = random.randint(gaprange[0], gaprange[1])
            # Turn the inner ring if the cipher is set to do that
            inner = stepN(inner, turn)

    # Decoding works like simple substitution but numbers are skipped and the
    # the inner ring turns instead
    if decode == True:
        for i in text:
            dec = outer[inner.index(i)]
            if dec in "0123456789":
                inner = stepN(inner, int(dec))
            else:
                out.append(dec)
            inner = stepN(inner, turn)

    return "".join(out)
예제 #5
0
def polybiusSquare(text, key="", decode=False, mode="EX", sep=""):
    #the IJ version of the polybius (25 characters)
    if mode == "IJ":
        alpha = "ABCEDFGHIKLMNOPQRSTUVWXYZ"
        text = text.replace("J", "I")
        key = key.replace("J", "I")

    #the CK version of the polybius (25 characters)
    if mode == "CK":
        alpha = "ABEDFGHIJKLMNOPQRSTUVWXYZ"
        text = text.replace("C", "K")
        key = key.replace("C", "K")

    #the KQ version of the polybius (25 characters)
    if mode == "KQ":
        alpha = "ABCEDFGHIJKLMNOPRSTUVWXYZ"
        text = text.replace("Q", "K")
        key = key.replace("Q", "K")

    #the extended version of the polybius (36 characters)
    if mode == "EX":
        alpha = "ABCEDFGHIJKLMNOPQRSTUVWXYZ0123456789"

    # Generate the internal key using user key
    k = alphabetPermutation(key, alphabet=alpha)

    if mode == "EX":
        codegroups = ["".join(i) for i in product("123456", repeat=2)]
    else:
        codegroups = ["".join(i) for i in product("12345", repeat=2)]

    if decode == False:
        # Pair each letter with a codegroup
        D = {}
        for i, j in zip(k, codegroups):
            D[i] = j

        ctext = [D[let] for let in text]

        return sep.join(ctext)

    if decode == True:
        # Pair each codegrou with a letter
        D = {}
        for i, j in zip(k, codegroups):
            D[j] = i
        if sep != "":
            grps = text.split(sep)
        else:
            grps = [text[2 * j:2 * j + 2] for j in range(len(text) // 2)]
        dtext = [D[pair] for pair in grps]

        return "".join(dtext)
예제 #6
0
def ADFGX(text,keys=["A",[0,1]],decode=False,printkey=False):
    
    """
:param text: The text to be encrypyed. Must be alphanumeric and uppercase. The letter J will be replaced with I.
:param keys: Two keywords, the first to prepare a 5x5 square a the second to control a columnar transport cipher.
:param decode: Boolean. If false encrypt plaintext. If true decode ciphertext
    """
    
    # Adjust the text if necessary
    text = text.replace("J","I")
    while len(text) % len(keys[1]) != 0:
        text += "X"
        
    
    alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
    alpha = alphabetPermutation(keys[0],alpha)

    
    if printkey == True:
        sq = makeSquare(keys[0],mode="EX")
        for i in range(6):
            print(" ".join(sq[i]))
    
    pairs = product("ADFGX",repeat=2)
    
    D1 = {}
    D2 = {}
    for letter,pair in zip(alpha,pairs):
        D1[letter] = "".join(pair)
        D2["".join(pair)] = letter

    # The ADFGX cipher has a roughly symmetric encode and decoding process
    # the only difference is that the columnar transport is reversed.

    # Turn every letter into a pair of symbols
    ctext = "".join([D1[i] for i in text])
    # Scramble the symbols, this will break apart some of the pairs
    ctext = columnarTransport(ctext,keys[1],decode=decode)
    # Now take the scrambled symbols and turn them back into letters
    ctext = groups(ctext,2)
    ctext = "".join([D2[i] for i in ctext])

    return ctext
예제 #7
0
def hutton(text,keys=["",""],decode=False):
    alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    k1 = [alpha.index(i) + 1 for i in keys[0]]
    
    # Generate the initial alphabet then turn it into a list so it is easier to
    # manipulate by swapping letters.
    k2 = list(alphabetPermutation(keys[1]))

    out = ""
    
    if decode == False:
        for ctr,letter in enumerate(text):

            # Current position
            pos = k2.index(letter)
            # First increment, the alphabetic position of the first letter of the key
            inc1 = alpha.index(k2[0])+1
            # Second increment, the cyclic values from the first key aka "password"
            inc2 = k1[ctr%len(k1)]
            
            A = (pos+inc1+inc2) % 26
            
            out = out + k2[A]
            
            swap(k2,letter,k2[A])
    
    if decode == True:
        for ctr,letter in enumerate(text):
            
            # Current position
            pos = k2.index(letter)
            # First increment, the alphabetic position of the first letter of the key
            inc1 = alpha.index(k2[0])+1
            # Second increment, the cyclic values from the first key aka "password"
            inc2 = k1[ctr%len(k1)]
            
            A = (pos-inc1-inc2) % 26
            
            out = out + k2[A]
            
            swap(k2,letter,k2[A])
    
    return out
예제 #8
0
def substitution(text, key, decode=False, alphabet=""):

    if alphabet == "":
        alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

    validptext(text, alphabet)
    validkeys(key, str)

    # Derive the internally used key from the input
    KEY = alphabetPermutation(key, alphabet)

    out = []
    if decode == False:
        for i in text:
            out.append(KEY[alphabet.index(i)])
    if decode == True:
        for i in text:
            out.append(alphabet[KEY.index(i)])

    return "".join(out)
예제 #9
0
def trifid(text, key, decode=False):

    triplets = product("123", repeat=3)
    alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ+"
    alphabet = alphabetPermutation(key, alphabet)
    D1 = {}
    D2 = {}

    for trip, alph in zip(triplets, alphabet):
        D1[alph] = "".join(trip)
        D2["".join(trip)] = alph

    if decode == False:

        A, B, C = "", "", ""
        # Convert the letter into their triplets
        for letter in text:
            gr = D1[letter]
            A += gr[0]
            B += gr[1]
            C += gr[2]

        ctext = ""
        for gr in groups(A + B + C, 3):
            ctext += D2[gr]

        return ctext

    if decode == True:
        grs = ""
        for letter in text:
            gr = D1[letter]
            grs += gr

        A = grs[:len(grs) // 3]
        B = grs[len(grs) // 3:2 * len(grs) // 3]
        C = grs[2 * len(grs) // 3:]

        dtext = [i + j + k for i, j, k in zip(A, B, C)]
        return "".join([D2[n] for n in dtext])
예제 #10
0
def ADFGVX(text, keys=["A", [0, 1]], decode=False, printkey=False):
    """
:param text: The text to be encrypyed. Must be alphanumeric and uppercase.
:param keys: Two keywords, the first to prepare a 6x6 square a the second to control a columnar transport cipher.
:param decode: Boolean. If false encrypt plaintext. If true decode ciphertext
    """

    while len(text) % len(keys[1]) != 0:
        text += "X"

    alpha = alphabetPermutation(keys[0],
                                "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")

    sq = makeSquare(keys[0], mode="EX")

    if printkey == True:
        for i in range(6):
            print(" ".join(sq[i]))

    pairs = product("ADFGVX", repeat=2)

    D1 = {}
    D2 = {}
    for letter, pair in zip(alpha, pairs):
        D1[letter] = "".join(pair)
        D2["".join(pair)] = letter

    # Turn every letter into a pair of symbols
    ctext = "".join([D1[i] for i in text])
    # Scramble the symbols, this will break apart some of the pairs
    ctext = columnarTransport(ctext, keys[1], decode=decode)
    # Now take the scrambled symbols and turn them back into letters
    ctext = groups(ctext, 2)
    ctext = "".join([D2[i] for i in ctext])

    return ctext