Example #1
0
    def __init__(self, key='AAA', swaps=None, rotor_order=['I', 'II', 'III']):
        '''
        Initializes the Enigma machine.

        key = Three letter string specifying the top/visible letter for the left, middle, and right rotors respectively. This determines indexing in the rotor.

        swaps = Specifies which plugboard swaps you would like to implement, if any. These should be provided in the form [('A', 'B'), ('T', 'G')] if you want to swap A,B and T,G.

        rotor_order = Defines which rotor to set as the left, middle, and right rotors respectively when considering the Enigma geometrically as described above.
        '''
        if len(key) != 3:
            print(
                'Please provide a three letter string as the initial window setting.'
            )
            return None
        # Set the key and rotor order.
        self.key = key
        self.rotor_order = rotor_order
        # Now define the components.
        self.r_rotor = Rotor(rotor_order[2], key[2])
        self.m_rotor = Rotor(rotor_order[1], key[1], self.r_rotor)
        self.l_rotor = Rotor(rotor_order[0], key[0], self.m_rotor)
        self.reflector = Reflector()
        self.plugboard = Plugboard(swaps)
        # Define prev_rotor information for middle and right rotors.
        self.m_rotor.prev_rotor = self.l_rotor
        self.r_rotor.prev_rotor = self.m_rotor
Example #2
0
def test_Plugboard_update_swaps_false():
    C = Plugboard(['AB', 'CD'])

    C.update_swaps(['EF', 'GH'], False)
    assert C.swaps == {
        'A': 'B',
        'C': 'D',
        'B': 'A',
        'D': 'C',
        'E': 'F',
        'G': 'H',
        'F': 'E',
        'H': 'G'
    }
Example #3
0
 def test(self):
     #print (self.grundStellung)
     grunds = self.decodeGrundStellung()
     enigmai = Enigma(
         rotors={
             1: Rotor("VIII", 19 - 1,
                      pomlist.index(grunds[0])),  #slowest, left-most
             2: Rotor("II", 7 - 1, pomlist.index(grunds[1])),  #middle
             3: Rotor("IV", 12 - 1,
                      pomlist.index(grunds[2])),  #fastest, right-most
         },
         reflector=Reflector("B"),
         plugboard=Plugboard({
             "B": "D",
             "C": "O",
             "E": "I",
             "G": "L",
             "J": "S",
             "K": "T",
             "N": "V",
             "P": "M",
             "Q": "R",
             "W": "Z"
         }))
     text = enigmai.EDcrypt(self.ttc)
     print("DECRYPTED TEXT: " + text)
     print("STECKERS: %s" % enigmai.plugboard.wiring)
Example #4
0
    def decodeGrundStellung(self):
        #find out the starting grund stellung if we know the other parts
        enigmai = Enigma(
            rotors={
                1: Rotor("VIII", 19 - 1, pomlist.index(
                    self.grundStellung[0])),  #slowest, left-most
                2: Rotor("II", 7 - 1,
                         pomlist.index(self.grundStellung[1])),  #middle
                3: Rotor("IV", 12 - 1, pomlist.index(
                    self.grundStellung[2])),  #fastest, right-most
            },
            reflector=Reflector("B"),
            plugboard=Plugboard({
                "B": "D",
                "C": "O",
                "E": "I",
                "G": "L",
                "J": "S",
                "K": "T",
                "N": "V",
                "P": "M",
                "Q": "R",
                "W": "Z"
            }))
        text = enigmai.EDcrypt(self.grundStellung[3:])

        return text
Example #5
0
def buildenigma(fn):
    """
    Builds an Enigma object from the given file object.
    Returns the Enigma object.
    """
    plugboard = [i for i in range(Plugboard.PLUGBOARD_LENGTH)]
    rotors = []
    notches = []
    reflector = []
    offsets = []

    for i in fn:
        i = i.strip().split()
        if i[0] == "ROTOR":
            rotors.append([int(j) for j in i[2:]])
            offsets.append(0)
        elif i[0] == "PLUGBOARD":
            pb = [int(j) for j in i[2:]]
        elif i[0] == "NOTCHES":
            notches = [int(j) for j in i[2:]]
        elif i[0] == "REFLECTOR":
            reflector = [int(j) for j in i[2:]]
        elif i[0] == "OFFSETS":
            offsets = [int(j) for j in i[2:]]

    PLUGBOARD = Plugboard(plugboard)
    ROTORS = [Rotor(i[0], i[1]) for i in zip(rotors, offsets)]
    REFLECTOR = Reflector(reflector)
    SHAFT = Shaft(ROTORS, notches, REFLECTOR)
    return Enigma(SHAFT, PLUGBOARD)
Example #6
0
    def steckerHillClimbTest(self, rotors, reflectori, score, plugsIC,
                             plugsGRAM):
        plugboardi = Plugboard({})

        # we'll try to hill-climb just the most used pairs
        mostusedletters = [
            "E", "N", "X", "R"
        ]  # we will use 4 most used letters for the 1st run using IC
        mostusedletters2ndrun = list(
            "STAHDULCGMOBWFKZVPJYQ")  #2nd run for trigrams
        letters = list(pomlist)
        bestpairscoreGRAM = -10000
        topscore = score
        bestpairscoreIC = score

        best = ["", ""]
        best[0] = ""
        best[1] = ""

        #print ("Top score: "+str(topscore))
        for i in range(
                plugsIC):  #find the first best pair out of most used letters
            #print (i)
            for firstletter in mostusedletters:
                for secondletter in letters:  #check every combination of the most used letters one by one
                    if secondletter != firstletter:
                        #plugboardtest = dict(plugboardi.wiring)
                        plugboardtestpairs = {firstletter: secondletter}
                        plugboardtestdict = dict(plugboardtestpairs,
                                                 **plugboardi.wiring)
                        plugboardtest = Plugboard(plugboardtestdict)
                        #print (plugboardtest.wiring)
                        enigmai = Enigma(rotors, reflectori, plugboardtest)
                        text = enigmai.EDcrypt(self.ttc)
                        myscore = self.scorer.icscore(text)
                        #print (myscore)
                        if myscore > bestpairscoreIC:
                            bestpairscoreIC = myscore
                            best = [firstletter, secondletter]
                            #print ("Best one: "+str(bestpairscore)+" "+firstletter+secondletter)
            #print ("letas:"+str(letters))
            #print ("most:"+str(mostusedletters))
            #print (best[0])
            #print (best[1])
            if best[0] in letters:
                letters.remove(best[0])

            if best[1] in letters:
                letters.remove(best[1])

            if best[0] in mostusedletters:
                mostusedletters.remove(best[0])

            plugboardi.wiring[best[0]] = best[1]

            best[0] = ""
            best[1] = ""

            #print ((plugboardi.wiring))

        if not plugboardi:
            return bestpairscoreIC, bestpairscoreGRAM, dict(plugboardi.wiring)

        if plugsGRAM > 0:
            # if we found something, we continue to hill-climb

            enigmai = Enigma(rotors, reflectori,
                             plugboardi)  # initial trigram score
            text = enigmai.EDcrypt(self.ttc)
            bestpairscoreGRAM = self.scorer.score(text)
            #print (bestpairscoreGRAM)

            for i in range(plugsGRAM):
                for firstletter in mostusedletters2ndrun:
                    for secondletter in letters:  #check every combination of the most used letters one by one
                        if secondletter != firstletter:
                            plugboardtestpairs = {firstletter: secondletter}
                            plugboardtestdict = dict(plugboardtestpairs,
                                                     **plugboardi.wiring)
                            plugboardtest = Plugboard(plugboardtestdict)
                            #print (plugboardtest.wiring)
                            enigmai = Enigma(rotors, reflectori, plugboardtest)
                            text = enigmai.EDcrypt(self.ttc)
                            myscore = self.scorer.score(text)
                            #print (myscore)
                            if myscore > bestpairscoreGRAM:
                                bestpairscoreGRAM = myscore
                                best = [firstletter, secondletter]

            if best[0] in letters:
                letters.remove(best[0])

            if best[1] in letters:
                letters.remove(best[1])

            if best[0] in mostusedletters2ndrun:
                mostusedletters2ndrun.remove(best[0])

            plugboardi.wiring[best[0]] = best[1]

            best[0] = ""
            best[1] = ""

        #print ((plugboardi.wiring))

        # IC calculation after the 2nd step of hill climb
        enigmai = Enigma(rotors, reflectori, plugboardi)
        text = enigmai.EDcrypt(self.ttc)
        afterwardsIC = self.scorer.icscore(text)

        return bestpairscoreIC, bestpairscoreGRAM, afterwardsIC, dict(
            plugboardi.wiring)
Example #7
0
    def steckerHillClimbTest(self, rotors, reflectori, score, plugsIC,
                             plugsGRAM):
        plugboardi = Plugboard()

        # we'll try to hill-climb the first 3 most frequent letters using IC
        # mostusedletters = ["E","N","X","R"] # we will use 4 most used letters for the 1st run using IC
        frequencyAnalysis = collections.Counter(self.ttc)
        print(frequencyAnalysis)
        print(frequencyAnalysis.most_common(3))
        mostCommon3 = frequencyAnalysis.most_common(3)
        input("Press Enter to continue...")

        #mostusedletters = ["E","N","X","R"] # we will use 4 most used letters for the 1st run using IC
        #mostusedletters2ndrun = list("STAHDULCGMOBWFKZVPJYQ") #2nd run for trigrams
        letters = list(pomlist)
        bestpairscoreGRAM = -10000
        topscore = score
        bestpairscoreIC = score

        best = ["", ""]
        best[0] = ""
        best[1] = ""

        print('Looking up best pair out of most used letters...')
        start = time()
        #print ("Top score: "+str(topscore))
        for i in range(
                plugsIC):  #find the first best pair out of most used letters
            #print (i)
            for firstletter, value in mostCommon3:
                for secondletter in letters:  #check every combination of the most used letters one by one
                    if secondletter != firstletter:
                        plugboardtestpairs = {firstletter: secondletter}
                        print(firstletter)
                        plugboardtestdict = dict(plugboardtestpairs,
                                                 **plugboardi.wiring)
                        plugboardtest = Plugboard(plugboardtestdict)
                        #print (plugboardtest.wiring)
                        enigmai = Enigma(rotors, reflectori, plugboardtest)
                        text = enigmai.EDcrypt(self.ttc)
                        myscore = self.scorer_IC.score(text)
                        #print (myscore)
                        if myscore > bestpairscoreIC:
                            bestpairscoreIC = myscore
                            best = [firstletter, secondletter]
                            #print ("Best one: "+str(bestpairscore)+" "+firstletter+secondletter)
            #print ("letas:"+str(letters))
            #print ("most:"+str(mostusedletters))
            #print (best[0])
            #print (best[1])
            if best[0] in letters:
                letters.remove(best[0])

            if best[1] in letters:
                letters.remove(best[1])

            if best[0] in mostCommon3:
                mostCommon3.remove(best[0])

            plugboardi.wiring[best[0]] = best[1]

            best[0] = ""
            best[1] = ""

            #print ((plugboardi.wiring))

        print('Finished in %.2f seconds.' % (time() - start))

        if not plugboardi:
            return bestpairscoreIC, bestpairscoreGRAM, dict(plugboardi.wiring)

        if bestpairscoreIC > score:
            # if we found something, we continue to hill-climb

            print('Continuing to hillclimb...')
            start = time()

            enigmai = Enigma(rotors, reflectori,
                             plugboardi)  # initial trigram score
            text = enigmai.EDcrypt(self.ttc)
            bestpairscoreGRAM = Decimal(self.scorer_bi.score(text))

            for i in range(plugsGRAM):
                for firstletter in letters:
                    for secondletter in letters:  #check every combination of the most used letters one by one
                        if secondletter != firstletter:
                            plugboardtestpairs = {firstletter: secondletter}
                            plugboardtestdict = dict(plugboardtestpairs,
                                                     **plugboardi.wiring)
                            plugboardtest = Plugboard(plugboardtestdict)
                            #print (plugboardtest.wiring)
                            enigmai = Enigma(rotors, reflectori, plugboardtest)
                            text = enigmai.EDcrypt(self.ttc)
                            myscore = Decimal(self.scorer_bi.score(text))
                            if myscore > bestpairscoreGRAM:
                                bestpairscoreGRAM = myscore
                                best = [firstletter, secondletter]

            if best[0] in letters:
                letters.remove(best[0])

            if best[1] in letters:
                letters.remove(best[1])

            #if best[0] in mostusedletters2ndrun:
            #    mostusedletters2ndrun.remove(best[0])

            plugboardi.wiring[best[0]] = best[1]

            best[0] = ""
            best[1] = ""

        #print ((plugboardi.wiring))

        # IC calculation after the 2nd step of hill climb
        enigmai = Enigma(rotors, reflectori, plugboardi)
        text = enigmai.EDcrypt(self.ttc)
        afterwardsIC = self.scorer_IC.score(text)

        return bestpairscoreIC, bestpairscoreGRAM, afterwardsIC, dict(
            plugboardi.wiring)
Example #8
0
def test_Plugboard_init():
    C = Plugboard(['AB', 'CD'])
    assert C.swaps == {'A': 'B', 'C': 'D', 'B': 'A', 'D': 'C'}
Example #9
0
 def valid_plug_swap(self):
     return Plugboard(['AB', 'XR'])
Example #10
0
def test_Plugboard_update_swaps_too_many():
    C = Plugboard(['AB', 'CD'])

    assert C.update_swaps(['EF', 'GH', 'IJ', 'KL', 'MN', 'OP', 'QR'],
                          True) == None
Example #11
0
def test_Plugboard_update_swaps_true():
    C = Plugboard(['AB', 'CD'])

    C.update_swaps(['EF', 'GH'], True)
    assert C.swaps == {'E': 'F', 'G': 'H', 'F': 'E', 'H': 'G'}
Example #12
0
def test_Plugboard_print_swaps():
    C = Plugboard(['AB', 'CD'])
    assert C.print_swaps() == None
Example #13
0
def test_Plugboard_repr():
    C = Plugboard(['AB', 'CD'])
    assert C.__repr__() == ''
Example #14
0
def test_Plugboard_init_empty_swaps():
    C = Plugboard([])
    assert C
Example #15
0
def test_Plugboard_init_no_swaps():
    C = Plugboard(None)
    assert C
Example #16
0
    def ultimate_MP_method_1_HILLCLIMB(self):
        #1st step is to find out the plausible walzen and ring settings candidates for next steps using IC
        strtowrite = "!!! Starting at " + format(
            datetime.now(), '%H:%M:%S') + " with: " + self.subset[
                0] + "-" + self.subset[1] + "-" + self.subset[2]
        self.q.put(strtowrite)
        messagelenght = len(self.ttc)
        ic = 0  #threshold, everything less than this won't be even evaluated further
        topic = ic

        scorer_bi = scorer_ngrams('grams/german_bigrams1941.txt')
        scorer_tri = scorer_ngrams('grams/german_trigrams1941.txt')
        scorer_quad = scorer_ngrams('grams/german_trigrams1941.txt')

        plugs1run = 4  #number of plugs to be indentified by IC
        plugs2run = 10 - plugs1run  #rest of the plugs, identified by trigram score

        plugboardi = Plugboard()
        bestoftherunIC = -10000
        bestoftherunGRAM = -10000
        myscore = -10000
        botrstring = ""

        #-1725 bi1941 #-2900 tri #-4300 quad
        steckertop = -2900

        for r in range(2):
            reflectori = Reflector("B" if r == 0 else "C")
            for i in range(26):
                for j in range(26):
                    for k in range(26):
                        rotors = {
                            1: Rotor(self.subset[0], 0,
                                     i),  #slowest, left-most
                            2: Rotor(self.subset[1], 0, j),  #middle
                            3: Rotor(self.subset[2], 0,
                                     k),  #fastest, right-most
                        }
                        enigmai = Enigma(rotors, reflectori, plugboardi)
                        text = enigmai.EDcrypt(self.ttc)
                        myic = self.scorer.icscore(text)
                        #myscore = self.scorer_mono.score(text) #in case we'd need monograms (but we don't at this moment)

                        if myic > ic:
                            topic = myic
                            '''
                            strtowrite = ""+format(datetime.now(), '%H:%M:%S')\
                            +"\n 1st step Score\n"+str(myic)+"\nGuess: "+text\
                            +"\nGrunds original: "+str(i)+":"+str(j)+":"+str(k)\
                            +" Ring3: "+str("0")+" Wheels: "\
                            +rotor1.number+":"+rotor2.number+":"+rotor3.number\
                            +" Ref:"+str(reflectori.typ)+"\n"
                            self.q.put(strtowrite)
                            '''

                            #2nd step is to test right-most and middle rotor combinations for the best scored ones
                            for x in range(26):
                                for y in range(26):
                                    #r3shift = 0+y
                                    #r2shift = 0
                                    #if rotor2.step>=r3shift:
                                    #    r2shift = 1

                                    #rotor1 = rotor(self.subset[0], 0,i)
                                    #rotor2 = rotor(self.subset[1], x,(abs(j-r2shift-x)%26))
                                    #rotor3 = rotor(self.subset[2], y,((k+r3shift)%26))
                                    rotors = {
                                        1: Rotor(self.subset[0], 0, i),
                                        2: Rotor(self.subset[1], x, j),
                                        3: Rotor(self.subset[2], y, k),
                                    }
                                    enigmai = Enigma(rotors, reflectori,
                                                     plugboardi)
                                    text = enigmai.EDcrypt(self.ttc)

                                    myic = self.scorer.icscore(text)

                                    #3rd step is Hill-climbing steckers using trigrams
                                    if myic > topic and myic > 0.040:
                                        topic = myic
                                        '''
                                            strtowrite = ""+format(datetime.now(), '%H:%M:%S')\
                                            +"\n2nd step Score\n"+str(myic)+"\nGuess: "+text\
                                            +"\nGrunds original: "+str(i)+":"+str(j)+":"+str(k)\
                                            +" Ring2: "+str(x)+ " Ring3: "+str(y)+" Wheels: "\
                                            +rotor1.number+":"+rotor2.number+":"+rotor3.number\
                                            +" Ref:"+str(reflectori.typ)+"\n"
                                            self.q.put(strtowrite)
                                            '''
                                        #bestoftherunIC = topscore #nope
                                        #stecker
                                        '''strtowrite = ""+format(datetime.now(), '%H:%M:%S')
                                            +"\nORIGINAL Score\n"+str(myscore)+"\nGuess: "
                                            +text+"\nGrunds original: "+str(i)+":"+str(j)+":"+str(k)
                                            +" Grunds new: "+str(i)+":"
                                            +str(abs(j-r2shift)%26)+":"+str((k+r3shift)%26)
                                            +" Ring3: "+str(o)
                                            +" Wheels: "+rotor1.number+":"+rotor2.number+":"+rotor3.number
                                            +" Ref:"+str(reflectori.typ)+"\n"
                                            #self.q.put(strtowrite)
                                            '''
                                        #myscore = self.scorer.score(text)
                                        steckerscoreIC, steckerscoreGRAM, steckerscoreAIC, steckerinfo = self.steckerHillClimbTest(
                                            rotor1, rotor2, rotor3, reflectori,
                                            myic, plugs1run, plugs2run)

                                        #strtowrite = "STECKER: "+str(steckerinfo)+"\n\n"
                                        #self.q.put(strtowrite)
                                        if ((steckerscoreIC > bestoftherunIC
                                             and steckerscoreAIC > 0.055) or
                                            (steckerscoreGRAM >
                                             bestoftherunGRAM
                                             and steckerscoreAIC > 0.055)):
                                            #print ("CHECKTHISOUT: " +text+"\n")
                                            bestoftherunIC = steckerscoreIC
                                            bestoftherunGRAM = steckerscoreGRAM
                                            strtowrite = "Time "\
                                            +format(datetime.now(), '%H:%M:%S')\
                                            +"\nORIGINAL Score\n"+str(myic)\
                                            +"\nScores\n"+"Original IC:"+str(steckerscoreIC)+"\nAfterwards IC:"+str(steckerscoreAIC)+"\nTrigram:"+str(steckerscoreGRAM)\
                                            +"\nGuess: "+text+"\nGrunds original: "\
                                            +str(i)+":"+str(j)+":"+str(k)+" Grunds new: "\
                                            +"Ring2: "+str(x)+" Ring3: "+str(y)\
                                            +" Wheels: "+rotor1.number+":"+rotor2.number+":"+rotor3.number\
                                            +" Ref:"+str(reflectori.typ)+"\n"\
                                            +"STECKER: "+str(steckerinfo)+"\n\n"
                                            self.q.put(strtowrite)

                                        if steckerscoreAIC > 0.06:
                                            print("BINGO IC!!! " +
                                                  str(steckerscoreAIC))
                                            print("CHECKTHISOUT: " + text +
                                                  "\n")

                                        if steckerscoreGRAM > -2900:
                                            print("CHECKTHISOUT: " + text +
                                                  "\n")
                                            print("BINGO GRAM!!! GRAM:" +
                                                  str(steckerscoreGRAM)
                                                  )  # Trigram score
                                            print(
                                                "BINGO GRAM!!! ORIC:" +
                                                str(myic))  # original IC score
                                            print(
                                                "BINGO GRAM!!! BEIC:" +
                                                str(steckerscoreIC)
                                            )  # IC score after first 3 plugs

                                            print(
                                                "BINGO GRAM!!! AFIC:" +
                                                str(steckerscoreAIC) + "\n\n"
                                            )  # IC sore after Trigrams applied
                                        #stecker

        if bestoftherunIC > -10000:
            strtowrite = "BOTR: " + str(bestoftherunIC) + "\n" + str(
                botrstring)
        strtowrite = ""
        self.q.put(strtowrite)
Example #17
0
    def testHillClimb(self):
        #print ("testHillClimb")
        bestoftherun = -10000
        bestoftherunIC = -10000
        bestoftherunGRAM = -10000
        myscore = -10000

        steckerscoreIC = -10000
        steckerscoreGRAM = -10000
        steckerscoreAIC = -10000

        steckerinfo = []

        plugsIC = 4  #how many plugs we'd like to try to find in 1st run IC
        plugsGRAM = 6  #how many plugs we'd like to try to find in 2nd run trigram
        plugs3 = 0  #how many plugs we'd like to try to find in 3rd run trigram

        f = open("testHillClimb.txt", 'a')
        start = datetime.now()
        f.write("\n\nSTART: " + format(start, '%H:%M:%S') + "\n\n")
        f.flush()

        grunds = self.decodeGrundStellung()
        plugboardi = Plugboard()
        reflectori = Reflector("B")
        rotors = {
            1: Rotor("VIII", 19 - 1,
                     pomlist.index(grunds[0])),  #slowest, left-most
            2: Rotor("II", 7 - 1, pomlist.index(grunds[1])),  #middle
            3: Rotor("IV", 12 - 1,
                     pomlist.index(grunds[2])),  #fastest, right-most
        }
        enigmai = Enigma(rotors, reflectori, plugboardi)
        print(enigmai)
        text = enigmai.EDcrypt(self.ttc)

        myic = self.scorer_IC.score(text)
        print("Original IC / plain text (before heuristics): " + str(myic))
        startTime = time()
        steckerscoreIC, steckerscoreGRAM, steckerscoreAIC, steckerinfo = self.steckerHillClimbTest(
            rotors, reflectori, myic, plugsIC, plugsGRAM)
        print("Execution time is: %.3fs" % (time() - startTime))
        print("\nScores\n" + "Original IC:" + str(myic) + "\nAfterwards IC:" +
              str(steckerscoreAIC) + "\nTrigram:" + str(steckerscoreGRAM))
        print("End of heuristics\n\n")

        print("Heuristics results:")
        if ((steckerscoreIC > bestoftherunIC and steckerscoreAIC > 0.05) or
            (steckerscoreGRAM > bestoftherunGRAM and steckerscoreAIC > 0.06)):
            #print ("CHECKTHISOUT: " +text+"\n")
            bestoftherunIC = steckerscoreIC
            bestoftherunGRAM = steckerscoreGRAM
            #print ("\nScores\n"+"Original IC:"+str(steckerscoreIC)+"\nAfterwards IC:"+str(steckerscoreAIC)+"\nTrigram:"+str(steckerscoreGRAM))
            #print (str(steckerinfo))
            #print ("TEXT: " +text+"\n")

            if steckerscoreAIC > 0.065:
                print("BINGO IC!!! " + str(steckerscoreAIC))
                print("BEST DESCRYPTED TEXT (IC METHOD): " + text + "\n")
                print("STECKERS:" + str(steckerinfo))

            if steckerscoreGRAM > -1500:
                print("BINGO GRAM!!! GRAM: " +
                      str(steckerscoreGRAM))  # Trigram score
                print("BINGO GRAM!!! ORIC: " + str(myic))  # original IC score
                print("BINGO GRAM!!! BEIC: " +
                      str(steckerscoreIC))  # IC score after first 4 plugs
                print("BINGO GRAM!!! AFIC: " + str(steckerscoreAIC) +
                      "\n")  # IC sore after Trigrams applied
                print("BEST DESCRYPTED TEXT (GRAM METHOD): " + text)
                print("STECKERS:" + str(steckerinfo))
Example #18
0
def test_Plugboard_update_swaps_no_swaps():
    C = Plugboard(['AB', 'CD'])
    assert C.update_swaps([], True) == None
Example #19
0
class Enigma():
    '''
    This class will bring together components to create an actual Enigma machine.

    Thought about geometrically, the Enigma can be viewed as follows:

    Keyboard -> Plugboard -> R Rotor -> M Rotor -> L Rotor -> Reflector.
    Lampboard <- Plugboard <- R Rotor <- M Rotor <- L Rotor <- Reflector.

    The generic initial rotor ordering (which can be changed by the user) is L = I, M = II, R = III (I,II,III are the three Wehrmacht Enigma rotors defined in components.py)
    '''

    def __init__(self, key='AAA', swaps=None, rotor_order=['I', 'II', 'III']):
        '''
        Initializes the Enigma machine.

        key = Three letter string specifying the top/visible letter for the left, middle, and right rotors respectively. This determines indexing in the rotor.

        swaps = Specifies which plugboard swaps you would like to implement, if any. These should be provided in the form [('A', 'B'), ('T', 'G')] if you want to swap A,B and T,G.

        rotor_order = Defines which rotor to set as the left, middle, and right rotors respectively when considering the Enigma geometrically as described above.
        '''
        if len(key) != 3:
            raise ValueError('Please provide a three letter string as the initial window setting.')
        # Set the key and rotor order.
        self.key = key
        self.rotor_order = rotor_order
        self.set_rotor_order(rotor_order)

        self.reflector = Reflector()
        self.plugboard = Plugboard(swaps)

    def __repr__(self):
        print('Keyboard <-> Plugboard <->  Rotor ' + self.rotor_order[0]
              + ' <-> Rotor ' + self.rotor_order[1]
              + ' <-> Rotor ' + self.rotor_order[2]
              + ' <-> Reflector ')
        return 'Key: ' + self.key

    def encipher(self, message):
        """
        Given a message string, encode or decode that message.
        """
        cipher = ''
        # Test the message string to make sure it only contains a-zA-Z
        if bool(re.compile(r'[^a-zA-Z ]').search(message)):
            return 'Please provide a string containing only the characters a-zA-Z and spaces.'
        for letter in message.upper().replace(" ", "").strip():
            cipher += self.encode_decode_letter(letter)
        return cipher

    def decipher(self, message):
        """
        Encryption == decryption.
        """
        return self.encipher(message)

    def encode_decode_letter(self, letter):
        """ Takes a letter as input, steps rotors accordingly, and returns letter output.
        Because Enigma is symmetrical, this works the same whether you encode or decode.
        """
        # Make sure the letter is in a-zA-Z.
        if bool(re.compile(r'[^a-zA-Z ]').search(letter)):
            return 'Please provide a letter in a-zA-Z.'
        # First, go through plugboard.
        if letter in self.plugboard.swaps:
            letter = self.plugboard.swaps[letter.upper()]
        # Next, step the rotors.
        self.r_rotor.step()
        # Send the letter through the rotors to the reflector.
        # Get the index of the letter that emerges from the rotor.
        left_pass = self.r_rotor.encode_letter(ALPHABET.index(letter.upper()))
        # Must match letter INDEX, not letter name to reflector as before.
        refl_output = self.reflector.wiring[ALPHABET[(left_pass)%26]]
        # Send the reflected letter back through the rotors.
        final_letter = ALPHABET[self.l_rotor.encode_letter(
            ALPHABET.index(refl_output), forward=False)]
        if final_letter in self.plugboard.swaps:
            return self.plugboard.swaps[final_letter]
        else:
            return final_letter

    def set_rotor_position(self, position_key, printIt=False):
        '''
        Updates the visible window settings of the Enigma machine, rotating the rotors.
        The syntax for the rotor position key is three letter string of the form 'AAA' or 'ZEK'.
        '''
        if type(position_key)==str and len(position_key)==3:
            self.key = position_key
            self.l_rotor.change_setting(self.key[0])
            self.m_rotor.change_setting(self.key[1])
            self.r_rotor.change_setting(self.key[2])
            if printIt:
                print('Rotor position successfully updated. Now using ' + self.key + '.')
        else:
            print('Please provide a three letter position key such as AAA.')

    def set_rotor_order(self, rotor_order):
        '''
        Changes the order of rotors in the Engima machine to match that specified by the user.
        The syntax for the rotor order is a list of the form ['I', 'II', 'III'], where 'I' is the left rotor, 'II' is the middle rotor, and 'III' is the right rotor.
        '''
        # Now define the components.
        self.l_rotor = Rotor(rotor_order[0], self.key[0])
        self.m_rotor = Rotor(rotor_order[1], self.key[1], self.l_rotor)
        self.r_rotor = Rotor(rotor_order[2], self.key[2], self.m_rotor)
        # Define prev_rotor information for middle and left rotors.
        self.m_rotor.prev_rotor = self.r_rotor
        self.l_rotor.prev_rotor = self.m_rotor

    def set_plugs(self, swaps, replace=False):
        '''
        Update the plugboard settings. Swaps takes the form ['AB', 'CD'].

        If replace is true, then this method will erase the current plugboard settings and replace them with new ones.
        '''
        self.plugboard.update_swaps(swaps, replace)
       # print('Plugboard successfully updated. New swaps are:')
       # for s in self.plugboard.swaps:
       #     print(s)
Example #20
0
def test_Plugboard_update_swaps_not_list():
    C = Plugboard(['AB', 'CD'])
    assert C.update_swaps({'A': 'F'}, True) == None
Example #21
0
 def none_plug_swap(self):
     return Plugboard(None)
Example #22
0
 def __init__(self, rotors: dict = None, reflector = None, plugboard = None):
     self.rotors = rotors  # create a new copy of rotors dict
     self.reflector = reflector
     self.plugboard = plugboard or Plugboard()