From 5fbb4bfd72f29c6ed185f66925c4e8eaa70e87a4 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Fri, 27 Nov 2009 15:33:02 -0500 Subject: [PATCH] finished implementing encode and decode funcs --- onetimepad.py | 54 +++++++++++++++++++++----- test_onetimepad.py | 96 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 9 deletions(-) diff --git a/onetimepad.py b/onetimepad.py index 50cbe9b..5842e93 100644 --- a/onetimepad.py +++ b/onetimepad.py @@ -11,11 +11,23 @@ NULLCHAR = '.' def encode(msg, pad): - return msg + ret = [] + filled = list(_text_padfill(msg, pad)) + for i, line in enumerate(_text_cipherfill(filled)): + lineno = i + 1 + if _is_cipherline(lineno): + ret.append(line) + return ''.join(ret).strip(NULLCHAR) -def decode(msg, pad): - return msg +def decode(ciphertext, pad): + ret = [] + filled = list(_cipher_padfill(ciphertext, pad)) + for i, line in enumerate(_cipher_textfill(filled)): + lineno = i + 1 + if _is_textline(lineno): + ret.append(line) + return ''.join(ret).strip(NULLCHAR) def create_pad(length, width=DEFAULT_PAD_WIDTH): @@ -47,7 +59,7 @@ def _chunk_chars_into_lines(chars, width=DEFAULT_PAD_WIDTH): def _as_line_chunks(chars, width=DEFAULT_PAD_WIDTH): chunk = [] - for char in chars: + for char in chars.replace('\n', ''): chunk.append(char) if len(chunk) == width: yield ''.join(chunk) @@ -57,7 +69,9 @@ def _as_line_chunks(chars, width=DEFAULT_PAD_WIDTH): yield ''.join(chunk) -def _padfill(text, padlines): +def _text_padfill(text, padlines): + if isinstance(padlines, basestring): + padlines = padlines.splitlines() padlines = [line.strip() for line in padlines if line.strip()] textlines = _chunk_chars_into_lines(text, _get_textwidth(padlines)) for textline, padline in izip(textlines, padlines): @@ -66,17 +80,39 @@ def _padfill(text, padlines): yield '' -def _cipherfill(padfilled_lines): - for i, line in enumerate(padfilled_lines): +def _cipher_padfill(ciphertext, padlines): + if isinstance(padlines, basestring): + padlines = padlines.splitlines() + padlines = [line.strip() for line in padlines if line.strip()] + cipherlines = _chunk_chars_into_lines(ciphertext, _get_textwidth(padlines)) + for cipherline, padline in izip(cipherlines, padlines): + yield padline + yield '' + yield cipherline + + +def _text_cipherfill(padfilled_text_lines): + for i, line in enumerate(padfilled_text_lines): lineno = i + 1 if _is_cipherline(lineno): - padline = padfilled_lines[i - abs(PADLINE_OFFSET)] - textline = padfilled_lines[i - abs(TEXTLINE_OFFSET)] + padline = padfilled_text_lines[i - abs(PADLINE_OFFSET)] + textline = padfilled_text_lines[i - abs(TEXTLINE_OFFSET)] yield padline yield textline yield _cipherline_from_padline_and_textline(padline, textline) +def _cipher_textfill(padfilled_cipher_lines): + for i, line in enumerate(padfilled_cipher_lines): + lineno = i + 1 + if _is_cipherline(lineno): + padline = padfilled_cipher_lines[i - abs(PADLINE_OFFSET)] + textline = padfilled_cipher_lines[i - abs(TEXTLINE_OFFSET)] + yield padline + yield _textline_from_cipherline_and_padline(line, padline) + yield line + + def _cipherline_from_padline_and_textline(padline, textline): ret = [] for padchar, textchar in izip(padline, textline): diff --git a/test_onetimepad.py b/test_onetimepad.py index b6c78ca..f88e0a4 100644 --- a/test_onetimepad.py +++ b/test_onetimepad.py @@ -66,6 +66,14 @@ class TestOneTimePad(unittest.TestCase): TEST_PADLINE) self.assertEqual(TEST_TEXTLINE, actual) + def test_encode_equals_expected(self): + ciphertext = OT.encode(TEST_MSG, TEST_PAD) + self.assertEqual(TEST_CIPHER, ciphertext) + + def test_decode_equals_expected(self): + text = OT.decode(TEST_CIPHER, TEST_PAD) + self.assertEqual(TEST_MSG, text) + PADLINES = (1, 4, 7, 10, 13, 16, 19, 22, 25) TEXTLINES = (2, 5, 8, 11, 14, 17, 20, 23, 26) @@ -75,5 +83,93 @@ 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........................................................ + +""" + + if __name__ == '__main__': unittest.main()