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)
|