You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
box-o-sand/one-time-pad/itest_onetimepad.py

192 lines
8.0 KiB

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