File: test_enigma.py

package info (click to toggle)
python-enigma 0.1-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 268 kB
  • sloc: python: 750; makefile: 132
file content (188 lines) | stat: -rw-r--r-- 5,973 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# Copyright (C) 2012 by Brian Neal.
# This file is part of Py-Enigma, the Enigma Machine simulation.
# Py-Enigma is released under the MIT License (see License.txt).

"""Tests for the EnigmaMachine class."""

import unittest

from ..machine import EnigmaMachine


class SteppingTestCase(unittest.TestCase):

    def test_double_stepping(self):
        """Ensure the rotors step realistically by testing for a "double-step"
        case.
        
        """
        # This example taken from 
        # http://users.telenet.be/d.rijmenants/en/enigmatech.htm
        # in the section on "The Stepping Mechanism."
        m = EnigmaMachine.from_key_sheet(rotors=['III', 'II', 'I'])

        m.set_display('KDO')

        truth_data = ['KDP', 'KDQ', 'KER', 'LFS', 'LFT', 'LFU']
        for expected in truth_data:
            m.key_press('A')
            self.assertEqual(m.get_display(), expected)


class SimpleCipherTestCase(unittest.TestCase):
    """This example taken from Wikipedia"""

    PLAIN_TEXT = 'AAAAA'
    CIPHER_TEXT = 'BDZGO'

    def setUp(self):
        self.machine = EnigmaMachine.from_key_sheet(rotors=['I', 'II', 'III'])
        self.machine.set_display('AAA')

    def test_simple_encrypt(self):

        cipher_text = self.machine.process_text(self.PLAIN_TEXT)
        self.assertEqual(cipher_text, self.CIPHER_TEXT)

    def test_simple_decrypt(self):

        plain_text = self.machine.process_text(self.CIPHER_TEXT)
        self.assertEqual(plain_text, self.PLAIN_TEXT)


class ActualDecryptTestCase(unittest.TestCase):
    """This example taken from Dirk Rijmenants' simulator manual.
    
    It is credited to Frode Weierud and Geoff Sullivan.
        http://cryptocellar.com
    
    """
    def setUp(self):

        self.machine = EnigmaMachine.from_key_sheet(
                rotors='II IV V',
                reflector='B',
                ring_settings='B U L',
                plugboard_settings='AV BS CG DL FU HZ IN KM OW RX')

    def decrypt(self, start, enc_key, ciphertext, truth_data):

        # remove spaces & Kenngruppen from the ciphertext
        ciphertext = ciphertext.replace(' ', '')[5:]

        # remove spaces from the truth data
        truth_data = truth_data.replace(' ', '')

        # decrypt the message key
        self.machine.set_display(start)
        msg_key = self.machine.process_text(enc_key)

        # decrypt the cipher text with the unencrypted message key
        self.machine.set_display(msg_key)
        plaintext = self.machine.process_text(ciphertext)

        self.assertEqual(plaintext, truth_data)

    def test_decrypt_part1(self):

        ciphertext = (
            'RFUGZ EDPUD NRGYS ZRCXN'
            'UYTPO MRMBO FKTBZ REZKM'
            'LXLVE FGUEY SIOZV EQMIK'
            'UBPMM YLKLT TDEIS MDICA'
            'GYKUA CTCDO MOHWX MUUIA'
            'UBSTS LRNBZ SZWNR FXWFY'
            'SSXJZ VIJHI DISHP RKLKA'
            'YUPAD TXQSP INQMA TLPIF'
            'SVKDA SCTAC DPBOP VHJK'
        )

        truth_data = (
            'AUFKL XABTE ILUNG XVONX' 
            'KURTI NOWAX KURTI NOWAX'
            'NORDW ESTLX SEBEZ XSEBE'
            'ZXUAF FLIEG ERSTR ASZER'
            'IQTUN GXDUB ROWKI XDUBR'
            'OWKIX OPOTS CHKAX OPOTS'
            'CHKAX UMXEI NSAQT DREIN'
            'ULLXU HRANG ETRET ENXAN'
            'GRIFF XINFX RGTX'
        )

        self.decrypt('WXC', 'KCH', ciphertext, truth_data)

    def test_decrypt_part2(self):

        ciphertext = (
            'FNJAU SFBWD NJUSE GQOBH'
            'KRTAR EEZMW KPPRB XOHDR'
            'OEQGB BGTQV PGVKB VVGBI'
            'MHUSZ YDAJQ IROAX SSSNR'
            'EHYGG RPISE ZBOVM QIEMM'
            'ZCYSG QDGRE RVBIL EKXYQ'
            'IRGIR QNRDN VRXCY YTNJR'
        )

        truth_data = (
            'DREIG EHTLA NGSAM ABERS' 
            'IQERV ORWAE RTSXE INSSI' 
            'EBENN ULLSE QSXUH RXROE' 
            'MXEIN SXINF RGTXD REIXA' 
            'UFFLI EGERS TRASZ EMITA' 
            'NFANG XEINS SEQSX KMXKM' 
            'XOSTW XKAME NECXK'
        )

        self.decrypt('CRS', 'YPJ', ciphertext, truth_data)


class KriegsmarineTestCase(unittest.TestCase):
    """This is the Kriegsmarine example from Dirk Rijmenants' simulator manual.

    It is credited to Stefan Krah and the M4 project:
        http://www.bytereef.org/m4_project.html

    """
    def test_decrypt(self):

        stecker ='1/20 2/12 4/6 7/10 8/13 14/23 15/16 17/25 18/26 22/24'

        machine = EnigmaMachine.from_key_sheet(
                    rotors='Beta II IV I',
                    ring_settings='A A A V',
                    reflector='B-Thin',
                    plugboard_settings=stecker)

        ciphertext = (
        'FCLC QRKN NCZW VUSX PNYM INHZ XMQX SFWX WLKJ AHSH NMCO CCAK UQPM KCSM'
        'HKSE INJU SBLK IOSX CKUB HMLL XCSJ USRR DVKO HULX WCCB GVLI YXEO AHXR'
        'HKKF VDRE WEZL XOBA FGYU JQUK GRTV UKAM EURB VEKS UHHV OYHA BCJW MAKL'
        'FKLM YFVN RIZR VVRT KOFD ANJM OLBG FFLE OPRG TFLV RHOW OPBE KVWM UQFM'
        'PWPA RMFH AGKX IIBG FCLC QRKM VA'
        ).replace(' ', '')

        # remove the message indicators from the message (the first and last 2
        # groups of the message -- it appears the last partial group 'VA' should
        # be removed also)

        ciphertext = ciphertext[8:-10]

        machine.set_display('VJNA')
        plaintext = machine.process_text(ciphertext)

        truth_data = (
            'VONV ONJL OOKS JHFF TTTE'
            'INSE INSD REIZ WOYY QNNS'
            'NEUN INHA LTXX BEIA NGRI'
            'FFUN TERW ASSE RGED RUEC'
            'KTYW ABOS XLET ZTER GEGN'
            'ERST ANDN ULAC HTDR EINU'
            'LUHR MARQ UANT ONJO TANE'
            'UNAC HTSE YHSD REIY ZWOZ'
            'WONU LGRA DYAC HTSM YSTO'
            'SSEN ACHX EKNS VIER MBFA'
            'ELLT YNNN NNNO OOVI ERYS'
            'ICHT EINS NULL'
        ).replace(' ', '')

        self.assertEqual(plaintext, truth_data)