192 lines
8.0 KiB
Python
192 lines
8.0 KiB
Python
import unittest
|
|
import onetimepad as OT
|
|
|
|
|
|
class TestMod25(unittest.TestCase):
|
|
msg = ('HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFA'
|
|
'WOODCHUCKCOULDCHUCKWOOD' * 50)
|
|
_padsize = 2000
|
|
PADLINES = (1, 4, 7, 10, 13, 16, 19, 22, 25)
|
|
TEXTLINES = (2, 5, 8, 11, 14, 17, 20, 23, 26)
|
|
CIPHERLINES = (3, 6, 9, 12, 15, 18, 21, 24, 27)
|
|
|
|
TEST_PADLINE = 'HUCHUGGHOBUXADDHOHPGQBKXQKAOLRL'
|
|
TEST_TEXTLINE = 'THISCAKEISUNSATISFACTORYTOMEYES'
|
|
TEST_CIPHERLINE = 'BCMAXHRNXUPLTEXRGOQKKQBWKYNTKWD'
|
|
|
|
TEST_MSG = \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOODCHUCKCOULDCHUCKWOOD' \
|
|
'HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFAWOO'
|
|
|
|
TEST_CIPHER = \
|
|
'FMHZRGHRITAMHVAOLBANWMNYPBYDCFCAVXAEEKXUTYXLUCYQVYPWZFSKYI' \
|
|
'LWKCHZSXLFCMZIEFHXKVUXVNBIQVSNYPTFVIZHSVTDCKWUSZHEHUPLZSUY' \
|
|
'BTPSMEISGTYDWCXVUCPGHHKXDOUHGCVDTDUQVKFDRDCHFIKTNFGDFODCQS' \
|
|
'RIWGZBLPTCSXLMPQODYLHQNGWNSCTHNDOZEUXWCEQAZMRGZIQUTUYSKOGW' \
|
|
'YGYPEDNUZDWBEPUHLWWBHLGADYTCNGEUFKPLQSAMMXCTXWQEOYBNKQAHBV' \
|
|
'PDKTMQSHDFCFBCVKXVTRSXRTBHAGKNLFASNVNENHHRNGCKXALMIBNZKOTL' \
|
|
'BZMWGSNMTLDNPXKVQZZUAZCSPWFNRKAMTNMCPHWGLGBVSNFDXSKVUFBZBW' \
|
|
'WICBUPCWZDUXCZTXHKQBMQNTBHAAGMBPKUIDTHITUEWEPPMACPXERXRYND' \
|
|
'RWQSBQQMSQRVWZMAQQKUGHLELKFLKHGNFFDHIWUZPDIMIOELSIHMUIZQCW' \
|
|
'KLPZQIFAXNDRRIIIHOYBGSCIYBIVSRTECEOZSBLYTNCXGQXEWMGIXHKBIL' \
|
|
'TOKWHGABPMXNAHEWFKIMOQPHVHSYZABWLMLSSDEHQIBNEMEMHCWOUBIIZS' \
|
|
'XPFWXMQNOTEANYGQBVMZAXNPAMWSUOGFAFFYUTKDZYHFTPYGOMDHESKOZI' \
|
|
'IPDXAMSAQOTGAQKYPYWWUYGHSBVODAHDSKDVPMLWRCXQXGAXQZBFNKXFKU' \
|
|
'WUDRWNRKECIQIUEEMQNCAZDDDOQOEGUVFVCTKLTISNOQILEKUYXCYZNHHZ' \
|
|
'OFHCSLOPPQAFLHHDZANGTXNQSDZSAFLLSGWULVHIDERMTZZHTDHTZPHEFN' \
|
|
'ORDEIYOVTTAWVTOOXSLZBOPMRCCKSMHQOVFERCOVUMWXFSNEMFALNWGRQC' \
|
|
'NLWELLXNCHZGXQEUGEVNCWMHRNGUTBKTVEXGASBRCEBSFITOEFSNIBTLME' \
|
|
'MERMOFVBNTFCTTWEGAIGRZQBBFOKOPXNCWXFBK'
|
|
|
|
TEST_PAD = """\
|
|
XXLNWDZOAYXBEGFCGADYHHKQUYOAULZQMRZHQVTRLDUARODERVGBWVVVKECHNQNWKUCLZBWU
|
|
|
|
|
|
KUDWNGFTSEGFFSKSVEKZUMLTOSLIZZTFXODBZZMACDFUTESFRBAPYYVTTOCKQBSSTDGPILKE
|
|
|
|
|
|
YHSTKXTTGVBAIIZXCUPHICYICDGOBOIUZUEYCMLHPNHXUEKCBWTMKYBKHZLNKTETDXIHYBHF
|
|
|
|
|
|
WBOSEXMRLZVHNZSSQSBCKAERRITRBAZWGVZNTGDSIVIZEMBKWDOOBDWIDCZIUHVTKVTSGFDT
|
|
|
|
|
|
NRGPNGRNKEVLZVYOAYTUWCDTOLGEQDBSHVRMMYYQIEZWKWZVCPGIAGKPNZEGTLPKMPEILQAC
|
|
|
|
|
|
MIPKMYCFMVZKUTVKIPXBKGLFATSDCMYLPYLSTPBARVELNSOUFPZMUTRIRNZLYMDITNXMKLGE
|
|
|
|
|
|
QXYRYEAOHGETEQMKTUMARPYMPKONUKYZIHTFGNHIKVOLTLRPMPNFSDHWQGVHBNDCWZCLUHQW
|
|
|
|
|
|
GIFBFZKZOFZRRYCBOSBWSNVFXXPSAGOUOXDNBNSOZADYYSKWQUTYNCDNGVLSZNDBCTSIYOUX
|
|
|
|
|
|
NNUGLZNKNDSYGRUCXTKLBIMXZMMZAEHVRFYMBFKVDPAEHOYCBXKADZOTRRMULOPAIKCIHKFY
|
|
|
|
|
|
BQKKMEXUPLMTKGFIMPMTDVRZEBFEFARDEVQADVKIVNBHNZLEAAGLFIKXHTQWXBPNLXZHFUDZ
|
|
|
|
|
|
XYLLVFETIDCYAXGTIHUFUSFMMWTLKZARVQOFGEBKIGWHFFFFKTHPQOMVAVILFLWMRLWPBWVW
|
|
|
|
|
|
PFKSLFFWKYQVPHVPQTTVFRLQXHFMGVXVHTNSVZQSETKHXAPPSLHAIAVXWGDFVKOBQLEWPAZY
|
|
|
|
|
|
WELQRIFCGSOVFSLYXMSETCTROLNKMDWZSGKREFEPEHCOKSMRTNCDSTHCSQKMKCBYEWZSQHPK
|
|
|
|
|
|
UNWWUBKICDYYOSIZWKWRLGGIMYWKMDXOUKYHCUYCACKSFRWWXADQUZTCNYEYCSQEBTCZMSCV
|
|
|
|
|
|
NTGCDGFUUCTQWINV........................................................
|
|
|
|
"""
|
|
|
|
def setUp(self):
|
|
self.m25 = OT.Mod25()
|
|
|
|
def test_mk_as_alpha_excludes_j(self):
|
|
self.assertTrue('J' not in self.m25._as_alpha.values())
|
|
|
|
def test_mk_as_alpha_dict_has_25_members(self):
|
|
self.assertEqual(25, len(self.m25._as_alpha.items()))
|
|
|
|
def test_creates_pad_of_desired_length(self):
|
|
for width in (72, 33, 99, 111):
|
|
pad = self.m25.create_pad(self._padsize, width=width)
|
|
lines = [line.strip('.') for line in pad.split()]
|
|
actual = len(''.join(lines))
|
|
self.assertEqual(self._padsize, len(''.join(lines)),
|
|
'pad of {0} chars created at width '
|
|
'{1}, actual={2}'.format(self._padsize,
|
|
width, actual))
|
|
|
|
def test_is_padline(self):
|
|
for lineno in self.PADLINES:
|
|
self.assertTrue(self.m25._is_padline(lineno),
|
|
'line {0} is padline'.format(lineno))
|
|
for lineno in self.TEXTLINES:
|
|
self.assertFalse(self.m25._is_padline(lineno),
|
|
'line {0} is not padline'.format(lineno))
|
|
for lineno in self.CIPHERLINES:
|
|
self.assertFalse(self.m25._is_padline(lineno),
|
|
'line {0} is not padline'.format(lineno))
|
|
|
|
def test_is_textline(self):
|
|
for lineno in self.TEXTLINES:
|
|
self.assertTrue(self.m25._is_textline(lineno),
|
|
'line {0} is textline'.format(lineno))
|
|
for lineno in self.PADLINES:
|
|
self.assertFalse(self.m25._is_textline(lineno),
|
|
'line {0} is not textline'.format(lineno))
|
|
for lineno in self.CIPHERLINES:
|
|
self.assertFalse(self.m25._is_textline(lineno),
|
|
'line {0} is not textline'.format(lineno))
|
|
|
|
def test_is_cipherline(self):
|
|
for lineno in self.CIPHERLINES:
|
|
self.assertTrue(self.m25._is_cipherline(lineno),
|
|
'line {0} is cipherline'.format(lineno))
|
|
for lineno in self.PADLINES:
|
|
self.assertFalse(self.m25._is_cipherline(lineno),
|
|
'line {0} is not cipherline'.format(lineno))
|
|
for lineno in self.TEXTLINES:
|
|
self.assertFalse(self.m25._is_cipherline(lineno),
|
|
'line {0} is not cipherline'.format(lineno))
|
|
|
|
def test_make_cipherline_from_padline_and_textline(self):
|
|
actual = \
|
|
self.m25._cipherline_from_padline_and_textline(self.TEST_PADLINE,
|
|
self.TEST_TEXTLINE)
|
|
self.assertEqual(self.TEST_CIPHERLINE, actual)
|
|
|
|
def test_make_textline_from_cipherline_and_padline(self):
|
|
actual = self.m25._textline_from_cipherline_and_padline(
|
|
self.TEST_CIPHERLINE, self.TEST_PADLINE)
|
|
self.assertEqual(self.TEST_TEXTLINE, actual)
|
|
|
|
def test_encode_equals_expected(self):
|
|
ciphertext = OT.mod25encode(self.TEST_MSG, self.TEST_PAD)
|
|
self.assertEqual(self.TEST_CIPHER, ciphertext)
|
|
|
|
def test_decode_equals_expected(self):
|
|
text = OT.mod25decode(self.TEST_CIPHER, self.TEST_PAD)
|
|
self.assertEqual(self.TEST_MSG, text)
|
|
|
|
|
|
class TestOneTimePad(unittest.TestCase):
|
|
|
|
def test_get_randint_on_nonexistent_randomness_file_fails_ioerror(self):
|
|
OT._DEV_URANDOM['fp'] = None
|
|
self.assertRaises(IOError, OT._get_randint,
|
|
25, randomness_file='/foo/bar/busted/borken',
|
|
fallback_to_fake=False)
|
|
|
|
def test_get_randint_on_nonexistent_randomness_file_uses_fake(self):
|
|
OT._DEV_URANDOM['fp'] = None
|
|
random_int = OT._get_randint(32, randomness_file='/broke/as/joke')
|
|
self.assertTrue(random_int in range(0, 255))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|