diff --git a/README.rst b/README.rst index 9215c8f..a163703 100644 --- a/README.rst +++ b/README.rst @@ -21,26 +21,22 @@ Description SecretPy is a cryptographic Python package. It uses the following classical cipher algorithms: -- ADFGX, ADFGVX - Affine - Atbash -- Autokey - Bazeries - Beaufort -- Bifid - Caesar, Caesar Progressive - Chaocipher -- Columnar Transposition, Myszkowski Transposition - Keyword -- Nihilist -- Simple Substitution - Playfair, Two Square(Double Playfair), Three Square, Four Square -- Polybius +- Polybius, ADFGX, ADFGVX, Bifid, Trifid, Nihilist - Rot13, Rot5, Rot18, Rot47 -- Trifid +- Scytale +- Simple Substitution +- Transposition + - Columnar, Myszkowski, Zigzag(Railfence) - Vic -- Vigenere, Gronsfeld, Porta -- Zigzag(Railfence) +- Vigenere, Autokey, Gronsfeld, Porta Installation ============ @@ -69,102 +65,116 @@ The cipher classes can encrypt only characters which exist in the alphabet, and .. code-block:: python - from secretpy import Caesar, alphabets + from secretpy import Caesar, alphabets as al + + + def encdec(cipher, plaintext, key, alphabet=al.ENGLISH): + print('========================================================================================') + print(plaintext) + enc = cipher.encrypt(plaintext, key, alphabet) + print(enc) + print(cipher.decrypt(enc, key, alphabet)) + - alphabet = alphabets.GERMAN - plaintext = u"thequickbrownfoxjumpsoverthelazydog" key = 3 cipher = Caesar() - print(plaintext) - enc = cipher.encrypt(plaintext, key, alphabet) - print(enc) - dec = cipher.decrypt(enc, key, alphabet) - print(dec) + plaintext = u"thequickbrownfoxjumpsoverthelazydog" + encdec(cipher, plaintext, key) - print('=====================================') + alphabet = al.GERMAN + plaintext = u"schweißgequältvomödentextzürnttypografjakob" + encdec(cipher, plaintext, key, alphabet) - print(plaintext) - # use default english alphabet - enc = cipher.encrypt(plaintext, key) - print(enc) - dec = cipher.decrypt(enc, key) - print(dec) + alphabet = al.SWEDISH + plaintext = u"faqomschweizklövdutrångpjäxby" + encdec(cipher, plaintext, key, alphabet) ''' Output: - thequickbrownfoxjumpsoverthelazydog - wkhtxlfneurzqirämxpsvryhuwkhodüögrj - thequickbrownfoxjumpsoverthelazydog - ===================================== + ======================================================================================== thequickbrownfoxjumpsoverthelazydog wkhtxlfneurzqiramxpsvryhuwkhodcbgrj thequickbrownfoxjumpsoverthelazydog + ======================================================================================== + schweißgequältvomödentextzürnttypografjakob + vfkzhlcjhtxßowyrpaghqwhäwübuqwwösrjudimdnre + schweißgequältvomödentextzürnttypografjakob + ======================================================================================== + faqomschweizklövdutrångpjäxby + idtrpvfkzhlönocygxwuaqjsmbåeä + faqomschweizklövdutrångpjäxby ''' CryptMachine ------------ ``CryptMachine`` saves a state. There are alphabet, key and cipher, they can be changed in anytime. -In the previous example, plaintext contains only characters existing in the alphabet i.e. without spaces. -To change the behaviour, you can use ``CryptMachine`` and decorators(``SaveAll``, ``RemoveNonAlphabet``), so it's a preferred way to do encryption/decryption: +In the previous example, plaintext contains only characters existing in the alphabet i.e. without spaces and etc. +To change the behaviour, you can use ``CryptMachine`` and decorators(``SaveAll``, ``Block``), so it's a preferred way to do encryption/decryption: .. code-block:: python - from secretpy import Atbash, Caesar, CryptMachine, alphabets - from secretpy.cmdecorators import SaveAll, RemoveNonAlphabet + from secretpy import Caesar, CryptMachine, alphabets as al + from secretpy.cmdecorators import SaveAll, Block def encdec(machine, plaintext): - print(plaintext) - enc = machine.encrypt(plaintext) - print(enc) - dec = machine.decrypt(enc) - print(dec) - print("-----------------------------------") + print("--------------------------------------------------------------------") + print(plaintext) + enc = machine.encrypt(plaintext) + print(enc) + print(machine.decrypt(enc)) - plaintext = u"thequickbrownfoxjumpsoverthelazydog" - key = 3 - cipher = Caesar() + cm0 = CryptMachine(cipher, key) - cm = CryptMachine(cipher, key) + cm = cm0 + cm.set_alphabet(al.ENGLISH) + plaintext = "I don't love non-alphabet characters. I will remove all of them: ^,&@$~(*;?&#. Great!" encdec(cm, plaintext) - cm.set_alphabet(alphabets.GERMAN) + cm = Block(cm, length=5, sep="-") + plaintext = "This text is divided by blocks of length 5!" encdec(cm, plaintext) - cm1 = SaveAll(cm) - cm1.set_key(9) - plaintext = u"the quick brown fox jumps over the lazy dog" - encdec(cm1, plaintext) + cm = SaveAll(cm0) + plaintext = "I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it!" + encdec(cm, plaintext) - cm2 = RemoveNonAlphabet(cm) - cm2.set_cipher(Atbash()) - plaintext = u"Achtung Minen" - encdec(cm2, plaintext) + cm.set_alphabet(al.ENGLISH_SQUARE_IJ) + plaintext = "Jj becomes Ii because we use ENGLISH_SQUARE_IJ!" + encdec(cm, plaintext) + cm.set_alphabet(al.JAPANESE_HIRAGANA) + cm.set_key(1) + plaintext = u"text あい だやぎへぐゆぢ" + encdec(cm, plaintext) ''' Output: - thequickbrownfoxjumpsoverthelazydog - wkhtxlfneurzqiramxpsvryhuwkhodcbgrj - thequickbrownfoxjumpsoverthelazydog - ----------------------------------- - thequickbrownfoxjumpsoverthelazydog - wkhtxlfneurzqirämxpsvryhuwkhodüögrj - thequickbrownfoxjumpsoverthelazydog - ----------------------------------- - the quick brown fox jumps over the lazy dog - üqn zßrlt käxbw oxc sßvyö xanä üqn ujed mxp - the quick brown fox jumps over the lazy dog - ----------------------------------- - Achtung Minen - ßöwkjqxrvqzq - achtungminen - ----------------------------------- + -------------------------------------------------------------------- + I don't love non-alphabet characters. I will remove all of them: ^,&@$~(*;?&#. Great! + lgrqworyhqrqdoskdehwfkdudfwhuvlzloouhpryhdooriwkhpjuhdw + idontlovenonalphabetcharactersiwillremoveallofthemgreat + -------------------------------------------------------------------- + This text is divided by blocks of length 5! + wklvw-hawlv-glylg-hgebe-orfnv-riohq-jwk + thistextisdividedbyblocksoflength + -------------------------------------------------------------------- + I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it! + L oryh qrq-doskdehw fkdudfwhuv. Wkhvh duh : ^,&@$~(*;?&#. Wkdw'v lw! + I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it! + -------------------------------------------------------------------- + Jj becomes Ii because we use ENGLISH_SQUARE_IJ! + Mm ehfrphv Mm ehfdxvh zh xvh HQKOMVL_VTXDUH_MM! + Ii becomes Ii because we use ENGLISH_SQUARE_II! + -------------------------------------------------------------------- + text あい だやぎへぐゆぢ + text いう ぢゆぐほげよづ + text あい だやぎへぐゆぢ ''' CompositeMachine @@ -175,16 +185,16 @@ Combining several ciphers to get more complex cipher, you can use ``CompositeMac .. code-block:: python from secretpy import Rot13, Caesar, CryptMachine, CompositeMachine - from secretpy.cmdecorators import SaveAll, RemoveNonAlphabet + from secretpy.cmdecorators import SaveAll def encdec(machine, plaintext): - print("=======================================") - print(plaintext) - enc = machine.encrypt(plaintext) - print(enc) - dec = machine.decrypt(enc) - print(dec) + print("=======================================") + print(plaintext) + enc = machine.encrypt(plaintext) + print(enc) + dec = machine.decrypt(enc) + print(dec) key = 5 diff --git a/docs/api.rst b/docs/api.rst index 4cca86a..8ad80dd 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -269,6 +269,17 @@ Examples .. literalinclude:: ../examples/rot47.py :linenos: +Simple Substitution +=================== +.. autoclass:: secretpy.Scytale + :members: + +Examples +-------- + +.. literalinclude:: ../examples/scytale.py + :linenos: + Simple Substitution =================== .. autoclass:: secretpy.SimpleSubstitution diff --git a/examples/affine.py b/examples/affine.py index b4d7740..7a2eae8 100755 --- a/examples/affine.py +++ b/examples/affine.py @@ -1,8 +1,8 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import Affine -from secretpy import alphabets +from secretpy import Affine, alphabets + alphabet = alphabets.GERMAN plaintext = u"thequickbrownfoxjumpsoverthelazydog" diff --git a/examples/autokey.py b/examples/autokey.py index e6872dd..69bf504 100755 --- a/examples/autokey.py +++ b/examples/autokey.py @@ -1,8 +1,8 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import Autokey -from secretpy import alphabets +from secretpy import Autokey, alphabets + alphabet = alphabets.GERMAN plaintext = u"thequickbrownfoxjumpsoverthelazydog" diff --git a/examples/beaufort.py b/examples/beaufort.py index 9e036cc..2876bae 100755 --- a/examples/beaufort.py +++ b/examples/beaufort.py @@ -1,38 +1,93 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import CryptMachine -from secretpy import Beaufort -from secretpy import alphabets +from secretpy import Beaufort, CryptMachine, alphabets as al +from secretpy.cmdecorators import SaveAll + + +def encdec(cipher, plaintext, key, alphabet=al.ENGLISH): + print('========================================================================================') + print(plaintext) + enc = cipher.encrypt(plaintext, key, alphabet) + print(enc) + print(cipher.decrypt(enc, key, alphabet)) + -plaintext = u"helloworld" key = "key" +cipher = Beaufort() + +plaintext = u"thequickbrownfoxjumpsoverthelazydog" +encdec(cipher, plaintext, key) + +alphabet = al.GERMAN +plaintext = u"schweißgequältvomödentextzürnttypografjakob" +encdec(cipher, plaintext, key, alphabet) + +alphabet = al.SWEDISH +plaintext = u"faqomschweizklövdutrångpjäxby" +encdec(cipher, plaintext, key, alphabet) -cm = CryptMachine(Beaufort(), key) +# using cryptmachine -print(plaintext) -enc = cm.encrypt(plaintext) -print(enc) -dec = cm.decrypt(enc) -print(dec) -print("-----------------------------------") +def encdec(machine, plaintext): + print("--------------------------------------------------------------------") + print(plaintext) + enc = machine.encrypt(plaintext) + print(enc) + print(machine.decrypt(enc)) -alphabet = alphabets.GERMAN -cm.set_alphabet(alphabet) -print(plaintext) -enc = cm.encrypt(plaintext) -print(enc) -dec = cm.decrypt(enc) -print(dec) +cm0 = CryptMachine(cipher, key) + +plaintext = "I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it!" +cm = SaveAll(cm0) +encdec(cm, plaintext) + +cm.set_alphabet(al.ENGLISH_SQUARE_IJ) +plaintext = "Jj becomes Ii because we use ENGLISH_SQUARE_IJ!" +encdec(cm, plaintext) + +cm.set_alphabet(al.JAPANESE_HIRAGANA) +cm.set_key(u"だやぎへ") +plaintext = u"text あい だやぎへぐゆぢ" +encdec(cm, plaintext) + +plaintext = "I don't love non-alphabet characters. I will remove all of them: ^,&@$~(*;?&#. Great!" +cm = cm0 +cm.set_alphabet(al.ENGLISH) +cm.set_key(key) +encdec(cm, plaintext) ''' -helloworld -danzqcwnnh -helloworld ------------------------------------ -helloworld -danßucärnh -helloworld +Output: + +======================================================================================== +thequickbrownfoxjumpsoverthelazydog +rxuukqiuxtqcxzknveypgwjutlrgtylgvwy +thequickbrownfoxjumpsoverthelazydog +======================================================================================== +schweißgequältvomödentextzürnttypografjakob +wcrsaqlüuyoüßpdäwöhalvabvjäxvfvkjäühkßpkykj +schweißgequältvomödentextzürnttypografjakob +======================================================================================== +faqomschweizklövdutrångpjäxby +feizvgiåcgzöawzsbeuqäåäjbgbjj +faqomschweizklövdutrångpjäxby +-------------------------------------------------------------------- +I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it! +C tkpa lwr-yzprkdur crknyilutm. Fdagg ehg : ^,&@$~(*;?&#. Lrkl'g cl! +I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it! +-------------------------------------------------------------------- +Jj becomes Ii because we use ENGLISH_SQUARE_IJ! +Bw xfclyag Bw xfcyqnu oa esa UXYOBNR_SPEKOU_BW! +Ii becomes Ii because we use ENGLISH_SQUARE_II! +-------------------------------------------------------------------- +text あい だやぎへぐゆぢ +text だも むもそすぇめぇ +text あい だやぎへぐゆぢ +-------------------------------------------------------------------- +I don't love non-alphabet characters. I will remove all of them: ^,&@$~(*;?&#. Great! +cbkxlnwjuxqlktjdexglwdehkcfgngciqzthgskpayztkflrgsstayr +idontlovenonalphabetcharactersiwillremoveallofthemgreat ''' diff --git a/examples/bifid.py b/examples/bifid.py index 1bb2eb3..ba67168 100755 --- a/examples/bifid.py +++ b/examples/bifid.py @@ -1,8 +1,7 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import Bifid -from secretpy import CryptMachine +from secretpy import Bifid, CryptMachine, alphabets def encdec(machine, plaintext): @@ -23,7 +22,6 @@ def encdec(machine, plaintext): u"щ", u"ы", u"ьъ", u"э", u"ю", u"я", u"1", u"2", u"3", u"4", u"5", u"6" ] - cm.set_alphabet(alphabet) plaintext = u"текст" encdec(cm, plaintext) @@ -35,8 +33,8 @@ def encdec(machine, plaintext): u"r", u"c", u"v", u"s", u"z", u"w", u"b", u"u", u"t", u"ij" ] -plaintext = u"defendtheeastwallofthecastle" cm.set_alphabet(alphabet) +plaintext = u"defendtheeastwallofthecastle" encdec(cm, plaintext) alphabet = [ @@ -46,18 +44,31 @@ def encdec(machine, plaintext): u"f", u"c", u"l", u"u", u"m", u"t", u"h", u"y", u"v", u"r" ] -plaintext = "fleeatonce" cm.set_alphabet(alphabet) cm.set_key(10) +plaintext = "fleeatonce" encdec(cm, plaintext) -alphabet = [ - u"Α", u"Β", u"Γ", u"Δ", u"Ε", - u"Ζ", u"Η", u"Θ", u"Ι", u"Κ", - u"Λ", u"Μ", u"Ν", u"Ξ", u"Ο", - u"Π", u"Ρ", u"Σ", u"Τ", u"Υ", - u"Φ", u"Χ", u"Ψ", u"Ω" -] +alphabet = alphabets.GREEK.upper() plaintext = u"ΠΙΝΑΚΑΣ" cm.set_alphabet(alphabet) encdec(cm, plaintext) + +''' +текст +нит4я +текст +---------------------------------- +defendtheeastwallofthecastle +ffyhmkhycpliashadtrlhcchlblr +defendtheeastwallofthecastle +---------------------------------- +fleeatonce +uaeolwrins +fleeatonce +---------------------------------- +ΠΙΝΑΚΑΣ +ΡΛΖΠΣΕΓ +ΠΙΝΑΚΑΣ +---------------------------------- +''' diff --git a/examples/caesar.py b/examples/caesar.py index 051f6c6..40ce969 100755 --- a/examples/caesar.py +++ b/examples/caesar.py @@ -1,29 +1,31 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import Caesar, CryptMachine, alphabets -from secretpy.cmdecorators import SaveAll, RemoveNonAlphabet +from secretpy import Caesar, CryptMachine, alphabets as al +from secretpy.cmdecorators import SaveAll, Block + + +def encdec(cipher, plaintext, key, alphabet=al.ENGLISH): + print('========================================================================================') + print(plaintext) + enc = cipher.encrypt(plaintext, key, alphabet) + print(enc) + print(cipher.decrypt(enc, key, alphabet)) -alphabet = alphabets.GERMAN -plaintext = u"thequickbrownfoxjumpsoverthelazydog" key = 3 cipher = Caesar() -print(plaintext) -enc = cipher.encrypt(plaintext, key, alphabet) -print(enc) -dec = cipher.decrypt(enc, key, alphabet) -print(dec) +plaintext = u"thequickbrownfoxjumpsoverthelazydog" +encdec(cipher, plaintext, key) -print('=====================================') +alphabet = al.GERMAN +plaintext = u"schweißgequältvomödentextzürnttypografjakob" +encdec(cipher, plaintext, key, alphabet) -print(plaintext) -# use default english alphabet -enc = cipher.encrypt(plaintext, key) -print(enc) -dec = cipher.decrypt(enc, key) -print(dec) +alphabet = al.SWEDISH +plaintext = u"faqomschweizklövdutrångpjäxby" +encdec(cipher, plaintext, key, alphabet) # using cryptmachine @@ -37,33 +39,63 @@ def encdec(machine, plaintext): cm0 = CryptMachine(cipher, key) -cm0.set_alphabet(alphabet) -plaintext = "I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it!" +cm = cm0 +cm.set_alphabet(al.ENGLISH) +plaintext = "I don't love non-alphabet characters. I will remove all of them: ^,&@$~(*;?&#. Great!" +encdec(cm, plaintext) + +cm = Block(cm, length=5, sep="-") +plaintext = "This text is divided by blocks of length 5!" +encdec(cm, plaintext) + cm = SaveAll(cm0) +plaintext = "I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it!" encdec(cm, plaintext) -plaintext = "I don't love non-alphabet characters. I will remove all of them: ^,&@$~(*;?&#. Great!" -cm = RemoveNonAlphabet(cm0) +cm.set_alphabet(al.ENGLISH_SQUARE_IJ) +plaintext = "Jj becomes Ii because we use ENGLISH_SQUARE_IJ!" encdec(cm, plaintext) +cm.set_alphabet(al.JAPANESE_HIRAGANA) +cm.set_key(1) +plaintext = u"text あい だやぎへぐゆぢ" +encdec(cm, plaintext) + + ''' Output: -thequickbrownfoxjumpsoverthelazydog -wkhtxlfneurzqirämxpsvryhuwkhodüögrj -thequickbrownfoxjumpsoverthelazydog -===================================== +======================================================================================== thequickbrownfoxjumpsoverthelazydog wkhtxlfneurzqiramxpsvryhuwkhodcbgrj thequickbrownfoxjumpsoverthelazydog +======================================================================================== +schweißgequältvomödentextzürnttypografjakob +vfkzhlcjhtxßowyrpaghqwhäwübuqwwösrjudimdnre +schweißgequältvomödentextzürnttypografjakob +======================================================================================== +faqomschweizklövdutrångpjäxby +idtrpvfkzhlönocygxwuaqjsmbåeä +faqomschweizklövdutrångpjäxby +-------------------------------------------------------------------- +I don't love non-alphabet characters. I will remove all of them: ^,&@$~(*;?&#. Great! +lgrqworyhqrqdoskdehwfkdudfwhuvlzloouhpryhdooriwkhpjuhdw +idontlovenonalphabetcharactersiwillremoveallofthemgreat +-------------------------------------------------------------------- +This text is divided by blocks of length 5! +wklvw-hawlv-glylg-hgebe-orfnv-riohq-jwk +thistextisdividedbyblocksoflength -------------------------------------------------------------------- I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it! L oryh qrq-doskdehw fkdudfwhuv. Wkhvh duh : ^,&@$~(*;?&#. Wkdw'v lw! I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it! -------------------------------------------------------------------- -I don't love non-alphabet characters. I will remove all of them: ^,&@$~(*;?&#. Great! -lgrqworyhqrqdoskdehwfkdudfwhuvlzloouhpryhdooriwkhpjuhdw -idontlovenonalphabetcharactersiwillremoveallofthemgreat - +Jj becomes Ii because we use ENGLISH_SQUARE_IJ! +Mm ehfrphv Mm ehfdxvh zh xvh HQKOMVL_VTXDUH_MM! +Ii becomes Ii because we use ENGLISH_SQUARE_II! +-------------------------------------------------------------------- +text あい だやぎへぐゆぢ +text いう ぢゆぐほげよづ +text あい だやぎへぐゆぢ ''' diff --git a/examples/caesar_progressive.py b/examples/caesar_progressive.py index fdb78fa..eb8c425 100755 --- a/examples/caesar_progressive.py +++ b/examples/caesar_progressive.py @@ -1,35 +1,92 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import CaesarProgressive -from secretpy import alphabets +from secretpy import CaesarProgressive, CryptMachine, alphabets as al +from secretpy.cmdecorators import SaveAll + + +def encdec(cipher, plaintext, key, alphabet=al.ENGLISH): + print('========================================================================================') + print(plaintext) + enc = cipher.encrypt(plaintext, key, alphabet) + print(enc) + print(cipher.decrypt(enc, key, alphabet)) + -alphabet = alphabets.ENGLISH plaintext = u"thequickbrownfoxjumpsoverthelazydog" key = 3 cipher = CaesarProgressive() -print(plaintext) -enc = cipher.encrypt(plaintext, key, alphabet) -print(enc) -dec = cipher.decrypt(enc, key, alphabet) -print(dec) +encdec(cipher, plaintext, key) + +alphabet = al.GERMAN +plaintext = u"schweißgequältvomödentextzürnttypografjakob" +encdec(cipher, plaintext, key, alphabet) + +alphabet = al.SWEDISH +plaintext = u"faqomschweizklövdutrångpjäxby" +encdec(cipher, plaintext, key, alphabet) + +# using cryptmachine + + +def encdec(machine, plaintext): + print("--------------------------------------------------------------------") + print(plaintext) + enc = machine.encrypt(plaintext) + print(enc) + print(machine.decrypt(enc)) -print('=====================================') -print(plaintext) -# use default english alphabet -enc = cipher.encrypt(plaintext, key) -print(enc) -dec = cipher.decrypt(enc, key) -print(dec) +cm0 = CryptMachine(cipher, key) + +plaintext = "I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it!" +cm = SaveAll(cm0) +encdec(cm, plaintext) + +cm.set_alphabet(al.ENGLISH_SQUARE_IJ) +plaintext = "Jj becomes Ii because we use ENGLISH_SQUARE_IJ!" +encdec(cm, plaintext) + +cm.set_alphabet(al.JAPANESE_HIRAGANA) +cm.set_key(1) +plaintext = u"text あい だやぎへぐゆぢ" +encdec(cm, plaintext) + +plaintext = "I don't love non-alphabet characters. I will remove all of them: ^,&@$~(*;?&#. Great!" +cm = cm0 +cm.set_alphabet(al.ENGLISH) +encdec(cm, plaintext) ''' +Output: + +======================================================================================== thequickbrownfoxjumpsoverthelazydog wljwbqlumdbkcvfpcohlpmuesvkiqgggmyr thequickbrownfoxjumpsoverthelazydog -===================================== -thequickbrownfoxjumpsoverthelazydog -wljwbqlumdbkcvfpcohlpmuesvkiqgggmyr -thequickbrownfoxjumpsoverthelazydog +======================================================================================== +schweißgequältvomödentextzürnttypografjakob +vgmülqiqpüdkäficbryägnßtqxörovwüuunzjpumxüq +schweißgequältvomödentextzürnttypografjakob +======================================================================================== +faqomschweizklövdutrångpjäxby +ievutålreqvkzäqkwllkuicmhåxcå +faqomschweizklövdutrångpjäxby +-------------------------------------------------------------------- +I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it! +L ptbl vxx-lxcvprvl vbvnxasesu. Wljyl iao : ^,&@$~(*;?&#. Etnh'h yk! +I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it! +-------------------------------------------------------------------- +Jj becomes Ii because we use ENGLISH_SQUARE_IJ! +Mn glkwvpd Vw qutsnmz sb sre FPKPOYP_AZEMDS_XY! +Ii becomes Ii because we use ENGLISH_SQUARE_II! +-------------------------------------------------------------------- +text あい だやぎへぐゆぢ +text いえ でりしぼそをは +text あい だやぎへぐゆぢ +-------------------------------------------------------------------- +I don't love non-alphabet characters. I will remove all of them: ^,&@$~(*;?&#. Great! +jfrryrvdnxzznzexrtxnxdxpzcuguwncptubpybjtqcdhzodbkfrfcw +idontlovenonalphabetcharactersiwillremoveallofthemgreat ''' diff --git a/examples/columnar_transposition.py b/examples/columnar_transposition.py index 35336c0..c7af394 100755 --- a/examples/columnar_transposition.py +++ b/examples/columnar_transposition.py @@ -2,7 +2,6 @@ # -*- encoding: utf-8 -*- from secretpy import ColumnarTransposition, CryptMachine -from secretpy import alphabets def encdec(machine, plaintext): @@ -16,9 +15,6 @@ def encdec(machine, plaintext): key = "cargo" cm = CryptMachine(ColumnarTransposition(), key) -alphabet = alphabets.ENGLISH - -cm.set_alphabet(alphabet) plaintext = "attackatdawn" encdec(cm, plaintext) @@ -29,11 +25,11 @@ def encdec(machine, plaintext): ''' attackatdawn -tanakwadzcazttz -attackatdawnzzz +tanakwadcatt +attackatdawn ------------------------------- howstuffworks -ushfowfztksrwo -howstuffworksz +ushfowftksrwo +howstuffworks ------------------------------- ''' diff --git a/examples/composite.py b/examples/composite.py index 39630c7..7411084 100755 --- a/examples/composite.py +++ b/examples/composite.py @@ -2,7 +2,7 @@ # -*- encoding: utf-8 -*- from secretpy import Rot13, Caesar, CryptMachine, CompositeMachine -from secretpy.cmdecorators import SaveAll, RemoveNonAlphabet +from secretpy.cmdecorators import SaveAll def encdec(machine, plaintext): diff --git a/examples/cryptmachine.py b/examples/cryptmachine.py index 9aa2361..6deb408 100755 --- a/examples/cryptmachine.py +++ b/examples/cryptmachine.py @@ -2,7 +2,7 @@ # -*- encoding: utf-8 -*- from secretpy import Atbash, Caesar, CryptMachine, alphabets -from secretpy.cmdecorators import SaveAll, RemoveNonAlphabet +from secretpy.cmdecorators import SaveAll def encdec(machine, plaintext): @@ -29,7 +29,7 @@ def encdec(machine, plaintext): plaintext = u"the quick brown fox jumps over the lazy dog" encdec(cm1, plaintext) -cm2 = RemoveNonAlphabet(cm) +cm2 = cm cm2.set_cipher(Atbash()) plaintext = u"Achtung Minen" encdec(cm2, plaintext) diff --git a/examples/four_square.py b/examples/four_square.py index a1c8fe9..a92930c 100755 --- a/examples/four_square.py +++ b/examples/four_square.py @@ -1,10 +1,8 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import FourSquare -from secretpy import CryptMachine -from secretpy import alphabets -from secretpy.cmdecorators import NoSpaces, UpperCase +from secretpy import FourSquare, CryptMachine, alphabets +from secretpy.cmdecorators import UpperCase def encdec(machine, plaintext): @@ -18,28 +16,36 @@ def encdec(machine, plaintext): alphabet = alphabets.ENGLISH_SQUARE_OQ -key = (u"exampl", u"keyword") +key = (u"example", u"keyword") -cm = NoSpaces(UpperCase(CryptMachine(FourSquare()))) +cm = UpperCase(CryptMachine(FourSquare())) cm.set_alphabet(alphabet) cm.set_key(key) plaintext = u"Help me Obi wan Kenobi" encdec(cm, plaintext) +plaintext = u"Help me Obi wan Kenobi a" +encdec(cm, plaintext) + alphabet = alphabets.ENGLISH_SQUARE_IJ cm.set_alphabet(alphabet) key = (u"criptog", u"segurt") cm.set_key(key) -plaintext = u"attack at dawn" +plaintext = u"Attack at dawn!" encdec(cm, plaintext) + ''' Help me Obi wan Kenobi FYGMKYHOBXMFKKKIMD HELPMEOBIWANKENOBI ---------------------------------- -attack at dawn +Help me Obi wan Kenobi a +FYGMKYHOBXMFKKKIMDPT +HELPMEOBIWANKENOBIAZ +---------------------------------- +Attack at dawn! PMMUTBPMCUXH ATTACKATDAWN ---------------------------------- diff --git a/examples/keyword-ex.py b/examples/keyword-ex.py index 14f067d..9283720 100755 --- a/examples/keyword-ex.py +++ b/examples/keyword-ex.py @@ -1,8 +1,7 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import Keyword -from secretpy import alphabets +from secretpy import Keyword, alphabets alphabet = alphabets.GERMAN diff --git a/examples/playfair.py b/examples/playfair.py index 4d89c7c..68778dc 100755 --- a/examples/playfair.py +++ b/examples/playfair.py @@ -1,9 +1,8 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import Playfair -from secretpy import CryptMachine -from secretpy.cmdecorators import NoSpaces, UpperCase +from secretpy import Playfair, CryptMachine +from secretpy.cmdecorators import UpperCase def encdec(machine, plaintext): @@ -15,7 +14,7 @@ def encdec(machine, plaintext): print("----------------------------------") -cm = NoSpaces(UpperCase(CryptMachine(Playfair()))) +cm = UpperCase(CryptMachine(Playfair())) alphabet = [ u"p", u"l", u"a", u"y", u"f", u"i", u"r", u"e", u"x", u"m", @@ -32,3 +31,18 @@ def encdec(machine, plaintext): plaintext = "this is a secret message" encdec(cm, plaintext) + +''' +Hide the gold in the tree stump +BMODZBXDNABEKUDMUIXMMOUVIF +HIDETHEGOLDINTHETREESTUMP +---------------------------------- +sometext +KQIXVIIW +SOMETEXT +---------------------------------- +this is a secret message +ZBMKMKFORDEXZIMOOFDX +THISISASECRETMESSAGE +---------------------------------- +''' diff --git a/examples/polybius.py b/examples/polybius.py index 27430a0..35caaf5 100755 --- a/examples/polybius.py +++ b/examples/polybius.py @@ -1,8 +1,7 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import Polybius -from secretpy import CryptMachine +from secretpy import Polybius, CryptMachine from secretpy.cmdecorators import LowerCase import secretpy.alphabets as alph diff --git a/examples/rot13.py b/examples/rot13.py index 021ea8c..e0c7602 100755 --- a/examples/rot13.py +++ b/examples/rot13.py @@ -1,10 +1,8 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import Rot13 -from secretpy import CryptMachine -from secretpy.cmdecorators import SaveCase, SaveSpaces -from secretpy import alphabets +from secretpy import Rot13, CryptMachine, alphabets as al +from secretpy.cmdecorators import SaveAll def encdec(machine, plaintext): @@ -16,20 +14,46 @@ def encdec(machine, plaintext): print(dec) -cm = SaveCase(CryptMachine(Rot13())) +cm = SaveAll(CryptMachine(Rot13())) -plaintext = u"thisisasecretmessage" +plaintext = u"This is a secret message" encdec(cm, plaintext) -cm = SaveSpaces(cm) - plaintext = u"Why did the chicken cross the road Gb trg gb gur bgure fvqr" encdec(cm, plaintext) -plaintext = u"thequickbrownfoxjumpsoverthelazydog" -cm.set_alphabet(alphabets.GERMAN) +plaintext = u"The quick brown fox jumps over the lazydog" +cm.set_alphabet(al.GERMAN) encdec(cm, plaintext) plaintext = u"текст" -cm.set_alphabet(alphabets.RUSSIAN) +cm.set_alphabet(al.RUSSIAN) +encdec(cm, plaintext) + +cm.set_alphabet(al.JAPANESE_HIRAGANA) +cm.set_key(1) +plaintext = u"あいうえおかきくけこがぎぐげごさしすせそざじずぜぞたちつてとだぢづでどなにぬねのはひふへほばびぶべぼぱぴぷぺぽまみむめもやゆよらりるれろわをんゃゅょぁぇ" encdec(cm, plaintext) + +''' +---------------------------------- +This is a secret message +Guvf vf n frperg zrffntr +This is a secret message +---------------------------------- +Why did the chicken cross the road Gb trg gb gur bgure fvqr +Jul qvq gur puvpxra pebff gur ebnq To get to the other side +Why did the chicken cross the road Gb trg gb gur bgure fvqr +---------------------------------- +The quick brown fox jumps over the lazydog +Ewt bfxrz qcßhü ußi yföad ßgtc ewt äpkjsßv +The quick brown fox jumps over the lazydog +---------------------------------- +текст +вхыбв +текст +---------------------------------- +あいうえおかきくけこがぎぐげごさしすせそざじずぜぞたちつてとだぢづでどなにぬねのはひふへほばびぶべぼぱぴぷぺぽまみむめもやゆよらりるれろわをんゃゅょぁぇ +ねのはひふへほばびぶべぼぱぴぷぺぽまみむめもやゆよらりるれろわをんゃゅょぁぇあいうえおかきくけこがぎぐげごさしすせそざじずぜぞたちつてとだぢづでどなにぬ +あいうえおかきくけこがぎぐげごさしすせそざじずぜぞたちつてとだぢづでどなにぬねのはひふへほばびぶべぼぱぴぷぺぽまみむめもやゆよらりるれろわをんゃゅょぁぇ +''' diff --git a/examples/scytale.py b/examples/scytale.py new file mode 100755 index 0000000..7c3b410 --- /dev/null +++ b/examples/scytale.py @@ -0,0 +1,69 @@ +#!/usr/bin/python +# -*- encoding: utf-8 -*- + +from secretpy import Scytale, CryptMachine, alphabets +from secretpy.cmdecorators import SaveAll + + +alphabet = alphabets.GERMAN +plaintext = u"thequickbrownfoxjumpsoverthelazydog" +key = 3 +cipher = Scytale() + +print(plaintext) +enc = cipher.encrypt(plaintext, key, alphabet) +print(enc) +dec = cipher.decrypt(enc, key, alphabet) +print(dec) + +print('=====================================') + +print(plaintext) +# use default english alphabet +enc = cipher.encrypt(plaintext, key) +print(enc) +dec = cipher.decrypt(enc, key) +print(dec) + +# using cryptmachine + + +def encdec(machine, plaintext): + print("--------------------------------------------------------------------") + print(plaintext) + enc = machine.encrypt(plaintext) + print(enc) + print(machine.decrypt(enc)) + + +cm0 = CryptMachine(cipher, key) +cm0.set_alphabet(alphabet) + +plaintext = "I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it!" +cm = SaveAll(cm0) +encdec(cm, plaintext) + +plaintext = "I don't love non-alphabet characters. I will remove all of them: ^,&@$~(*;?&#. Great!" +cm = cm0 +encdec(cm, plaintext) + +''' +Output: + +thequickbrownfoxjumpsoverthelazydog +tqcrnxmorezohukofjpvtlygeibwousehad +thequickbrownfoxjumpsoverthelazydog +===================================== +thequickbrownfoxjumpsoverthelazydog +tqcrnxmorezohukofjpvtlygeibwousehad +thequickbrownfoxjumpsoverthelazydog +-------------------------------------------------------------------- +I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it! +I vola tac-rheeaile npbcrtseat. Ttona heh : ^,&@$~(*;?&#. Aets'r hs! +I love non-alphabet characters. These are : ^,&@$~(*;?&#. That's it! +-------------------------------------------------------------------- +I don't love non-alphabet characters. I will remove all of them: ^,&@$~(*;?&#. Great! +inonahehaeilevlfertdtvolatacrwlmeltmeolenpbcrtsiroaohga +idontlovenonalphabetcharactersiwillremoveallofthemgreat + +''' diff --git a/examples/trifid.py b/examples/trifid.py index bf0d5d2..ddcf4e4 100755 --- a/examples/trifid.py +++ b/examples/trifid.py @@ -1,8 +1,8 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import Trifid -from secretpy import CryptMachine +from secretpy import Trifid, CryptMachine +from secretpy.cmdecorators import SaveAll def encdec(machine, plaintext): @@ -16,27 +16,50 @@ def encdec(machine, plaintext): key = 5 cm = CryptMachine(Trifid(), key) -alphabet = [ - u"e", u"p", u"s", - u"d", u"u", u"c", - u"v", u"w", u"y", - - u"m", u".", u"z", - u"l", u"k", u"x", - u"n", u"b", u"t", - - u"f", u"g", u"o", - u"r", u"i", u"j", - u"h", u"a", u"q", -] +alphabet = u"epsducvwym.zlkxnbtfgorijhaq" # 27 characters +cm.set_alphabet(alphabet) plaintext = u"defendtheeastwallofthecastle" -cm.set_alphabet(alphabet) encdec(cm, plaintext) +cm1 = cm +alphabet = ( + u"aåä", u"b", u"c", + u"d", u"e", u"f", + u"g", u"h", u"i", + + u"j", u"k", u"l", + u"m", u"n", u"oö", + u"p", u"q", u"r", + + u"s", u"t", u"u", + u"v", u"w", u"x", + u"y", u"z", u"+", +) +cm1.set_alphabet(alphabet) + +plaintext = u"Flygande bäckasiner söka hwila på mjuka tuvor!" +encdec(cm1, plaintext) + +cm2 = SaveAll(cm) +alphabet = "felixmardstbcghjknopquvwyz+" +cm2.set_alphabet(alphabet) + +plaintext = u"Aide-toi, le ciel t'aidera" +encdec(cm2, plaintext) + + ''' defendtheeastwallofthecastle suefecphsegyyjiximfofocejlrf defendtheeastwallofthecastle ---------------------------------- +Flygande bäckasiner söka hwila på mjuka tuvor! +fbiiajbmdmdsazckwpnujshvokdgpaqgackzkri +flygandebackasinersokahwilapamjukatuvor +---------------------------------- +Aide-toi, le ciel t'aidera +Fmjf-voi, ss uftf p'ufeqqc +Aide-toi, le ciel t'aidera +---------------------------------- ''' diff --git a/examples/two_square.py b/examples/two_square.py index 37fdb62..74842e2 100755 --- a/examples/two_square.py +++ b/examples/two_square.py @@ -1,10 +1,8 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import TwoSquare -from secretpy import CryptMachine -from secretpy import alphabets -from secretpy.cmdecorators import NoSpaces, UpperCase +from secretpy import TwoSquare, CryptMachine, alphabets +from secretpy.cmdecorators import UpperCase def encdec(machine, plaintext): @@ -20,16 +18,23 @@ def encdec(machine, plaintext): key = (u"example", u"keyword") -cm = NoSpaces(UpperCase(CryptMachine(TwoSquare()))) +cm = UpperCase(CryptMachine(TwoSquare())) cm.set_alphabet(alphabet) cm.set_key(key) plaintext = u"Help me Obi wan Kenobi" encdec(cm, plaintext) +plaintext = u"Help me Obi wan Kenobi y" +encdec(cm, plaintext) + ''' Help me Obi wan Kenobi XGDLXWSDJYRYHOTKDG HELPMEOBIWANKENOBI ---------------------------------- +Help me Obi wan Kenobi y +XGDLXWSDJYRYHOTKDGZX +HELPMEOBIWANKENOBIYZ +---------------------------------- ''' diff --git a/examples/vigenere.py b/examples/vigenere.py index 7566013..084ae3d 100755 --- a/examples/vigenere.py +++ b/examples/vigenere.py @@ -1,8 +1,7 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import Vigenere -from secretpy import alphabets +from secretpy import Vigenere, alphabets alphabet = alphabets.GERMAN plaintext = u"thequickbrownfoxjumpsoverthelazydog" diff --git a/examples/zigzag.py b/examples/zigzag.py index 2aa0a83..acd2f54 100755 --- a/examples/zigzag.py +++ b/examples/zigzag.py @@ -2,18 +2,18 @@ # -*- encoding: utf-8 -*- from secretpy import Zigzag -from secretpy import alphabets -alphabet = alphabets.GERMAN + plaintext = u"thequickbrownfoxjumpsoverthelazydog" +plaintext = u"thequick" key = 3 chipher = Zigzag() print(plaintext) -enc = chipher.encrypt(plaintext, key, alphabet) +enc = chipher.encrypt(plaintext, key) print(enc) -dec = chipher.decrypt(enc, key, alphabet) +dec = chipher.decrypt(enc, key) print(dec) ####################################################### diff --git a/secretpy/__init__.py b/secretpy/__init__.py index 596c8b8..be221b5 100755 --- a/secretpy/__init__.py +++ b/secretpy/__init__.py @@ -9,9 +9,8 @@ ColumnarTransposition, FourSquare, Gronsfeld, Keyword, MyszkowskiTransposition, Nihilist, SimpleSubstitution, Playfair, Porta, Polybius, Rot13, Rot18, Rot47, Rot5, - ThreeSquare, Trifid, TwoSquare, Vigenere, Vic, Zigzag) -# import alphabets -# from .cmdecorators import * + Scytale, ThreeSquare, Trifid, TwoSquare, Vigenere, Vic, + Zigzag) __all__ = [ "CompositeMachine", "CryptMachine", @@ -21,6 +20,6 @@ "Chao", "ColumnarTransposition", "FourSquare", "Gronsfeld", "Keyword", "MyszkowskiTransposition", "Nihilist", "SimpleSubstitution", "Playfair", "Porta", "Polybius", - "Rot13", "Rot18", "Rot47", "Rot5", "ThreeSquare", + "Rot13", "Rot18", "Rot47", "Rot5", "Scytale", "ThreeSquare", "Trifid", "TwoSquare", "Vigenere", "Vic", "Zigzag", ] diff --git a/secretpy/abstractmachine.py b/secretpy/abstractmachine.py index e139765..c29362d 100755 --- a/secretpy/abstractmachine.py +++ b/secretpy/abstractmachine.py @@ -1,7 +1,7 @@ #!/usr/bin/python -class AbstractCryptMachine: +class AbstractCryptMachine(object): def set_key(self, key): pass diff --git a/secretpy/alphabets.py b/secretpy/alphabets.py index f860e9e..d67c3d0 100755 --- a/secretpy/alphabets.py +++ b/secretpy/alphabets.py @@ -31,6 +31,7 @@ def get_index_in_alphabet(char, alphabet): POLISH = u"aąbcćdeęfghijklłmnńoóprsśtuwyzźż" RUSSIAN = u"абвгдеёжзийклмнопрстуфхцчшщъыьэюя" SPANISH = u"abcdefghijklmnñopqrstuvwxyz" +SWEDISH = u"abcdefghijklmnopqrstuvwxyzåäö" TURKISH = u"abcçdefgğhıijklmnoöprsştuüvyz" ENGLISH_SQUARE_IJ = ( @@ -100,5 +101,4 @@ def get_index_in_alphabet(char, alphabet): u"わを" u"ん" u"ゃゅょぁぇ" - u"じづ" ) diff --git a/secretpy/ciphers/__init__.py b/secretpy/ciphers/__init__.py index b0b1a35..fc7f794 100755 --- a/secretpy/ciphers/__init__.py +++ b/secretpy/ciphers/__init__.py @@ -25,6 +25,7 @@ from .rot18 import Rot18 from .rot47 import Rot47 from .rot5 import Rot5 +from .scytale import Scytale from .three_square import ThreeSquare from .trifid import Trifid from .two_square import TwoSquare @@ -38,6 +39,6 @@ "Chao", "ColumnarTransposition", "FourSquare", "Gronsfeld", "Keyword", "MyszkowskiTransposition", "Nihilist", "SimpleSubstitution", "Playfair", "Porta", "Polybius", - "Rot13", "Rot18", "Rot47", "Rot5", "ThreeSquare", + "Rot13", "Rot18", "Rot47", "Rot5", "Scytale", "ThreeSquare", "Trifid", "TwoSquare", "Vigenere", "Vic", "Zigzag", ] diff --git a/secretpy/ciphers/adfgvx.py b/secretpy/ciphers/adfgvx.py index 4586c09..4a6547a 100755 --- a/secretpy/ciphers/adfgvx.py +++ b/secretpy/ciphers/adfgvx.py @@ -20,72 +20,6 @@ class ADFGVX: u"6", u"7", u"8", u"9", u"0", u".", ] - def __dec(self, alphabet, key, text, isEncrypt): - keysize = len(key) - size = len(text) - rows = int(math.ceil(size/keysize)) - reminder = size % keysize - keyword = list(key) - indices = sorted(range(len(keyword)), key=lambda k: keyword[k]) - - myarr = list(indices) - lefti = 0 - righti = 0 - for key, value in enumerate(indices): - righti = lefti - righti += rows - if reminder > 0 and value > reminder-1: - righti -= 1 - myarr[value] = text[lefti:righti] - lefti = righti - - column = 0 - row = 0 - res = '' - for i in range(size): - res += (myarr[column][row]) - column += 1 - if column == keysize: - column = 0 - row += 1 - code = [] - try: - for char in res: - code.append(str(self.__header.index(char)+1)) - except ValueError: - wrchar = char.encode('utf-8') - raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") - - code = "".join(code) - return self.__polybius.decrypt(code, alphabet=alphabet) - - def __enc(self, alphabet, key, text, isEncrypt): - ans0 = self.__polybius.encrypt(text, alphabet=alphabet) - ans = [self.__header[int(char)-1] for char in ans0] - - keyword = list(key) - keysize = len(key) - size = len(ans) - indices = sorted(range(len(keyword)), key=lambda k: keyword[k]) - row = int(math.ceil(size/keysize)) - for i in range(row): - p = "" - for j in range(keysize): - myi = i*keysize+j - if myi < len(ans): - eee = ans[myi] - p += "".join(eee) - - ans2 = "" - for s in indices: - ind = s - while ind < size: - p = ans[ind] - ans2 += p - ind += keysize - - return ans2 - def encrypt(self, text, key, alphabet=None): """ Encryption method @@ -101,7 +35,13 @@ def encrypt(self, text, key, alphabet=None): :rtype: string """ alphabet = alphabet or self.__alphabet - return self.__enc(alphabet, key, text, 1) + ans = self.__polybius.encrypt(text, alphabet=alphabet) + ans = [self.__header[int(char)-1] for char in ans] + + keysize = len(key) + size = len(ans) + indices = sorted(range(keysize), key=lambda k: key[k]) + return "".join(ans[ind] for s in indices for ind in range(s, size, keysize)) def decrypt(self, text, key, alphabet=None): """ @@ -118,4 +58,39 @@ def decrypt(self, text, key, alphabet=None): :rtype: string """ alphabet = alphabet or self.__alphabet - return self.__dec(alphabet, key, text, -1) + keysize = len(key) + size = len(text) + rows = int(math.ceil(size/keysize)) + reminder = size % keysize + indices = sorted(range(keysize), key=lambda k: key[k]) + + myarr = [0] * keysize + lefti = 0 + righti = 0 + for key, value in enumerate(indices): + righti = lefti + righti += rows + if reminder > 0 and value > reminder-1: + righti -= 1 + myarr[value] = text[lefti:righti] + lefti = righti + + column = 0 + row = 0 + res = [] + for i in range(size): + res.append(myarr[column][row]) + column += 1 + if column == keysize: + column = 0 + row += 1 + code = [] + try: + for char in res: + code.append(self.__header.index(char)+1) + except ValueError: + wrchar = char.encode('utf-8') + raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") + + code = "".join(map(str, code)) + return self.__polybius.decrypt(code, alphabet=alphabet) diff --git a/secretpy/ciphers/adfgx.py b/secretpy/ciphers/adfgx.py index deea722..f34636a 100755 --- a/secretpy/ciphers/adfgx.py +++ b/secretpy/ciphers/adfgx.py @@ -4,6 +4,7 @@ from __future__ import division import math from .polybius import Polybius +from secretpy import alphabets as al class ADFGX: @@ -12,23 +13,50 @@ class ADFGX: """ __header = u"adfgx" __polybius = Polybius() - __alphabet = [ - u"a", u"b", u"c", u"d", u"e", - u"f", u"g", u"h", u"ij", u"k", - u"l", u"m", u"n", u"o", u"p", - u"q", u"r", u"s", u"t", u"u", - u"v", u"w", u"x", u"y", u"z" - ] - def __dec(self, alphabet, key, text): + def encrypt(self, text, key, alphabet=al.ENGLISH_SQUARE_IJ): + """ + Encryption method + + :param text: Text to encrypt + :param key: Encryption key + :param alphabet: Alphabet which will be used, + if there is no a value, English is used + :type text: string + :type key: integer + :type alphabet: string + :return: text + :rtype: string + """ + ans = self.__polybius.encrypt(text, alphabet=alphabet) + ans = [self.__header[int(char)-1] for char in ans] + + keysize = len(key) + size = len(ans) + indices = sorted(range(keysize), key=lambda k: key[k]) + return "".join(ans[ind] for s in indices for ind in range(s, size, keysize)) + + def decrypt(self, text, key, alphabet=al.ENGLISH_SQUARE_IJ): + """ + Decryption method + + :param text: Text to decrypt + :param key: Decryption key + :param alphabet: Alphabet which will be used, + if there is no a value, English is used + :type text: string + :type key: integer + :type alphabet: string + :return: text + :rtype: string + """ keysize = len(key) size = len(text) rows = int(math.ceil(size/keysize)) reminder = size % keysize - keyword = list(key) - indices = sorted(range(len(keyword)), key=lambda k: keyword[k]) + indices = sorted(range(keysize), key=lambda k: key[k]) - myarr = list(indices) + myarr = [0] * keysize lefti = 0 righti = 0 for key, value in enumerate(indices): @@ -41,9 +69,9 @@ def __dec(self, alphabet, key, text): column = 0 row = 0 - res = '' + res = [] for i in range(size): - res += (myarr[column][row]) + res.append(myarr[column][row]) column += 1 if column == keysize: column = 0 @@ -51,72 +79,10 @@ def __dec(self, alphabet, key, text): code = [] try: for char in res: - code.append(str(self.__header.index(char)+1)) + code.append(self.__header.index(char)+1) except ValueError: wrchar = char.encode('utf-8') raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") - code = "".join(code) - dec = self.__polybius.decrypt(code, alphabet=alphabet) - return dec - - def __enc(self, alphabet, key, text): - ans0 = self.__polybius.encrypt(text, alphabet=alphabet) - ans = [self.__header[int(char)-1] for char in ans0] - - keyword = list(key) - keysize = len(key) - size = len(ans) - indices = sorted(range(len(keyword)), key=lambda k: keyword[k]) - row = int(math.ceil(size/keysize)) - for i in range(row): - p = "" - for j in range(keysize): - myi = i*keysize+j - if myi < len(ans): - eee = ans[myi] - p += "".join(eee) - - ans2 = "" - for s in indices: - ind = s - while ind < size: - p = ans[ind] - ans2 += p - ind += keysize - - return ans2 - - def encrypt(self, text, key, alphabet=None): - """ - Encryption method - - :param text: Text to encrypt - :param key: Encryption key - :param alphabet: Alphabet which will be used, - if there is no a value, English is used - :type text: string - :type key: integer - :type alphabet: string - :return: text - :rtype: string - """ - alphabet = alphabet or self.__alphabet - return self.__enc(alphabet, key, text) - - def decrypt(self, text, key, alphabet=None): - """ - Decryption method - - :param text: Text to decrypt - :param key: Decryption key - :param alphabet: Alphabet which will be used, - if there is no a value, English is used - :type text: string - :type key: integer - :type alphabet: string - :return: text - :rtype: string - """ - alphabet = alphabet or self.__alphabet - return self.__dec(alphabet, key, text) + code = "".join(map(str, code)) + return self.__polybius.decrypt(code, alphabet=alphabet) diff --git a/secretpy/ciphers/affine.py b/secretpy/ciphers/affine.py index 2778123..c4352db 100755 --- a/secretpy/ciphers/affine.py +++ b/secretpy/ciphers/affine.py @@ -6,25 +6,25 @@ class Affine: The Affine Cipher """ - def __encDec(self, alphabet, key, text, isEncrypt): + def __crypt(self, alphabet, key, text, is_encrypt): a = key[0] b = key[1] - ans = "" - aInverse = self.__getInverse(a, alphabet) + res = [] + a_inverse = self.__get_inverse(a, alphabet) try: for char in text: - if isEncrypt == 1: - alphI = (alphabet.index(char) * a + b) % len(alphabet) + if is_encrypt == 1: + a_index = (alphabet.index(char) * a + b) % len(alphabet) else: - alphI = (aInverse * (alphabet.index(char) - b)) % len(alphabet) - enc = alphabet[alphI] - ans += enc + a_index = (a_inverse * (alphabet.index(char) - b)) % len(alphabet) + enc = alphabet[a_index] + res.append(enc) except ValueError: wrchar = char.encode('utf-8') raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") - return ans + return "".join(res) - def __getInverse(self, a, alphabet): + def __get_inverse(self, a, alphabet): for i in range(1, len(alphabet)): if ((int(a)*int(i)) % int(len(alphabet))) == 1: return i @@ -44,7 +44,7 @@ def encrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :return: text :rtype: string """ - return self.__encDec(alphabet, key, text, 1) + return self.__crypt(alphabet, key, text, 1) def decrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): """ @@ -60,4 +60,4 @@ def decrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :return: text :rtype: string """ - return self.__encDec(alphabet, key, text, -1) + return self.__crypt(alphabet, key, text, -1) diff --git a/secretpy/ciphers/atbash.py b/secretpy/ciphers/atbash.py index 583502c..f742d21 100755 --- a/secretpy/ciphers/atbash.py +++ b/secretpy/ciphers/atbash.py @@ -6,16 +6,16 @@ class Atbash: The Atbash Cipher """ - def __encDec(self, alphabet, text): - ans = "" + def __crypt(self, alphabet, text): + res = [] for char in text: try: alphIndex = len(alphabet) - (alphabet.index(char)) - 1 except ValueError: wrchar = char.encode('utf-8') raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") - ans += alphabet[alphIndex] - return ans + res.append(alphabet[alphIndex]) + return "".join(res) def encrypt(self, text, key=None, alphabet=u"abcdefghijklmnopqrstuvwxyz"): """ @@ -31,7 +31,7 @@ def encrypt(self, text, key=None, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :return: text :rtype: string """ - return self.__encDec(alphabet, text) + return self.__crypt(alphabet, text) def decrypt(self, text, key=None, alphabet=u"abcdefghijklmnopqrstuvwxyz"): """ @@ -47,4 +47,4 @@ def decrypt(self, text, key=None, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :return: text :rtype: string """ - return self.__encDec(alphabet, text) + return self.__crypt(alphabet, text) diff --git a/secretpy/ciphers/autokey.py b/secretpy/ciphers/autokey.py index 55a297f..654f15b 100755 --- a/secretpy/ciphers/autokey.py +++ b/secretpy/ciphers/autokey.py @@ -7,31 +7,30 @@ class Autokey: The Autokey Cipher """ - def __encDec(self, alphabet, key, text, isEncrypt): - ans = "" - for i in range(len(text)): - m = text[i] + def __crypt(self, alphabet, key, text, is_encrypt): + res = [] + for i, t in enumerate(text): + try: + a_index = alphabet.index(t) + except ValueError: + wrchar = t.encode('utf-8') + raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") if i < len(key): k = key[i] else: - if isEncrypt == 1: + if is_encrypt == 1: k = text[i - len(key)] else: - k = ans[i - len(key)] - try: - alphI = alphabet.index(m) - except ValueError: - wrchar = m.encode('utf-8') - raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") + k = res[i - len(key)] try: - alphI += isEncrypt * alphabet.index(k) + a_index += is_encrypt * alphabet.index(k) except ValueError: wrchar = k.encode('utf-8') raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") - alphI = alphI % len(alphabet) - enc = alphabet[alphI] - ans += enc - return ans + a_index = a_index % len(alphabet) + enc = alphabet[a_index] + res.append(enc) + return "".join(res) def encrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): """ @@ -47,7 +46,7 @@ def encrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :return: text :rtype: string """ - return self.__encDec(alphabet, key, text, 1) + return self.__crypt(alphabet, key, text, 1) def decrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): """ @@ -63,4 +62,4 @@ def decrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :return: text :rtype: string """ - return self.__encDec(alphabet, key, text, -1) + return self.__crypt(alphabet, key, text, -1) diff --git a/secretpy/ciphers/beaufort.py b/secretpy/ciphers/beaufort.py index 0ba27e2..bc87991 100755 --- a/secretpy/ciphers/beaufort.py +++ b/secretpy/ciphers/beaufort.py @@ -1,32 +1,34 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- +from itertools import cycle +from secretpy import alphabets as al + class Beaufort: """ The Beaufort Cipher """ - def __encDec(self, alphabet, key, text): - ans = "" - for i in range(len(text)): - char = text[i] - keychar = key[i % len(key)] + def __crypt(self, alphabet, key, text): + # prepare alphabet for substitution + indeces = {c: i for i, letters in enumerate(alphabet) for c in letters} + res = [] + for k, t in zip(cycle(key), text): try: - alphIndex = alphabet.index(keychar) - except ValueError: - wrchar = keychar.encode('utf-8') + i = indeces[k] + except KeyError: + wrchar = k.encode('utf-8') raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") try: - alphIndex -= alphabet.index(char) - except ValueError: - wrchar = char.encode('utf-8') + i -= indeces[t] + except KeyError: + wrchar = t.encode('utf-8') raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") - alphIndex %= len(alphabet) - ans += alphabet[alphIndex] - return ans + res.append(alphabet[i][0]) + return "".join(res) - def encrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): + def encrypt(self, text, key, alphabet=al.ENGLISH): """ Encryption method @@ -35,14 +37,14 @@ def encrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :param alphabet: Alphabet which will be used, if there is no a value, English is used :type text: string - :type key: integer + :type key: string :type alphabet: string :return: text :rtype: string """ - return self.__encDec(alphabet, key, text) + return self.__crypt(alphabet, key, text) - def decrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): + def decrypt(self, text, key, alphabet=al.ENGLISH): """ Decryption method @@ -51,9 +53,9 @@ def decrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :param alphabet: Alphabet which will be used, if there is no a value, English is used :type text: string - :type key: integer + :type key: string :type alphabet: string :return: text :rtype: string """ - return self.__encDec(alphabet, key, text) + return self.__crypt(alphabet, key, text) diff --git a/secretpy/ciphers/bifid.py b/secretpy/ciphers/bifid.py index 916f312..7edb26a 100755 --- a/secretpy/ciphers/bifid.py +++ b/secretpy/ciphers/bifid.py @@ -1,7 +1,8 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from .polybius import Polybius +from .polybius_square import PolybiusSquare +from secretpy import alphabets as al class Bifid: @@ -9,36 +10,7 @@ class Bifid: The Bifid Cipher """ - __polybius = Polybius() - - def __enc(self, alphabet, text, key): - code = self.__polybius.encrypt(text, alphabet=alphabet) - even = code[::2] - odd = code[1::2] - ret = "" - for i in range(0, len(even), key): - ret += even[i:i+key] + odd[i:i+key] - return self.__polybius.decrypt(ret, alphabet=alphabet) - - def __dec(self, alphabet, text, key): - code = self.__polybius.encrypt(text, alphabet=alphabet) - even = "" - odd = "" - rem = len(code) % (key << 1) - for i in range(0, len(code)-rem, key << 1): - ikey = i+key - even += code[i:ikey] - odd += code[ikey:ikey+key] - - even += code[-rem:-(rem >> 1)] - odd += code[-(rem >> 1):] - - code = "" - for i in range(len(even)): - code += even[i] + odd[i] - return self.__polybius.decrypt(code, alphabet=alphabet) - - def encrypt(self, text, key=None, alphabet=None): + def encrypt(self, text, key=None, alphabet=al.ENGLISH_SQUARE_IJ): """ Encryption method @@ -48,23 +20,25 @@ def encrypt(self, text, key=None, alphabet=None): if there is no a value, English is used :type text: string :type key: integer - :type alphabet: string + :type alphabet: string or tuple or list :return: text :rtype: string """ - alphabet = alphabet or [ - u"a", u"b", u"c", u"d", u"e", - u"f", u"g", u"h", u"ij", u"k", - u"l", u"m", u"n", u"o", u"p", - u"q", u"r", u"s", u"t", u"u", - u"v", u"w", u"x", u"y", u"z" - ] key = int(key) - if not key > 0: + if key <= 0: key = len(text) - return self.__enc(alphabet, text, key) + square = PolybiusSquare(alphabet) + coords = tuple(map(square.get_coordinates, text)) + res = [] + for i in range(0, len(coords), key): + block = coords[i:i+key] + block = list(zip(*block)) + block = block[0] + block[1] + for j in range(1, len(block), 2): + res.append(square.get_char(block[j-1], block[j])) + return "".join(res) - def decrypt(self, text, key=None, alphabet=None): + def decrypt(self, text, key=None, alphabet=al.ENGLISH_SQUARE_IJ): """ Decryption method @@ -74,18 +48,22 @@ def decrypt(self, text, key=None, alphabet=None): if there is no a value, English is used :type text: string :type key: integer - :type alphabet: string + :type alphabet: string or tuple or list :return: text :rtype: string """ - alphabet = alphabet or [ - u"a", u"b", u"c", u"d", u"e", - u"f", u"g", u"h", u'ij', u"k", - u"l", u"m", u"n", u"o", u"p", - u"q", u"r", u"s", u"t", u"u", - u"v", u"w", u"x", u"y", u"z" - ] key = int(key) - if not key > 0: + if key <= 0: key = len(text) - return self.__dec(alphabet, text, key) + square = PolybiusSquare(alphabet) + coords = tuple(map(square.get_coordinates, text)) + res = [] + for i in range(0, len(coords), key): + block = [] + for coord in coords[i:i+key]: + block.append(coord[0]) + block.append(coord[1]) + half = len(block) // 2 + for row, column in zip(block[:half], block[half:]): + res.append(square.get_char(row, column)) + return "".join(res) diff --git a/secretpy/ciphers/caesar.py b/secretpy/ciphers/caesar.py index 6d254c9..0308ffa 100755 --- a/secretpy/ciphers/caesar.py +++ b/secretpy/ciphers/caesar.py @@ -2,28 +2,30 @@ # -*- encoding: utf-8 -*- import secretpy.alphabets as al +from itertools import chain class Caesar: """ The Caesar Cipher """ - __alphabet = al.ENGLISH - def __encDec(self, alphabet, key, text, isEncrypt): - alphabet = alphabet or self.__alphabet - ans = "" - for char in text: + def __crypt(self, key, text, alphabet): + # key should be between 0 and len(alphabet) + key %= len(alphabet) + # prepare alphabet for substitution + ch = chain(range(key, len(alphabet)), range(key)) + subst = {c: alphabet[i][0] for i, letters in zip(ch, alphabet) for c in letters} + res = [] + for c in text: try: - alphIndex = alphabet.index(char) - except ValueError: - wrchar = char.encode('utf-8') + res.append(subst[c]) + except KeyError: + wrchar = c.encode('utf-8') raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") - alphIndex = (alphIndex + isEncrypt * key) % len(alphabet) - ans += alphabet[alphIndex] - return ans + return u"".join(res) - def encrypt(self, text, key, alphabet=None): + def encrypt(self, text, key=3, alphabet=al.ENGLISH): """ Encryption method @@ -37,9 +39,9 @@ def encrypt(self, text, key, alphabet=None): :return: encrypted text :rtype: string """ - return self.__encDec(alphabet, key, text, 1) + return self.__crypt(key, text, alphabet) - def decrypt(self, text, key, alphabet=None): + def decrypt(self, text, key=3, alphabet=al.ENGLISH): """ Decryption method @@ -53,4 +55,4 @@ def decrypt(self, text, key, alphabet=None): :return: decrypted text :rtype: string """ - return self.__encDec(alphabet, key, text, -1) + return self.__crypt(-key, text, alphabet) diff --git a/secretpy/ciphers/caesar_progressive.py b/secretpy/ciphers/caesar_progressive.py index 955203c..2ea7fa6 100755 --- a/secretpy/ciphers/caesar_progressive.py +++ b/secretpy/ciphers/caesar_progressive.py @@ -2,30 +2,31 @@ # -*- encoding: utf-8 -*- import secretpy.alphabets as al +from itertools import chain, cycle class CaesarProgressive: """ The Caesar Progressive Cipher """ - __alphabet = al.ENGLISH - def __encDec(self, alphabet, key, text, isEncrypt): - alphabet = alphabet or self.__alphabet - ans = "" - for i, char in enumerate(text): + def __crypt(self, alphabet, key, text, is_encrypt): + # key should be between 0 and len(alphabet) + key %= len(alphabet) + # prepare alphabet for substitution + subst = {c: i for i, letters in enumerate(alphabet) for c in letters} + res = [] + ch = chain(range(key, len(alphabet)), range(key)) + for k, t in zip(cycle(ch), text): try: - alphIndex = alphabet.index(char) - except ValueError as e: - wrchar = char.encode('utf-8') - e.args = ( - "Can't find char '" + wrchar + "' of text in alphabet!",) - raise - alphIndex = (alphIndex + isEncrypt * (key + i)) % len(alphabet) - ans += alphabet[alphIndex] - return ans - - def encrypt(self, text, key, alphabet=None): + i = (subst[t] + is_encrypt * k) % len(alphabet) + except KeyError: + wrchar = t.encode('utf-8') + raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") + res.append(alphabet[i][0]) + return "".join(res) + + def encrypt(self, text, key=3, alphabet=al.ENGLISH): """ Encryption method @@ -39,9 +40,9 @@ def encrypt(self, text, key, alphabet=None): :return: encrypted text :rtype: string """ - return self.__encDec(alphabet, key, text, 1) + return self.__crypt(alphabet, key, text, 1) - def decrypt(self, text, key, alphabet=None): + def decrypt(self, text, key=3, alphabet=al.ENGLISH): """ Decryption method @@ -55,4 +56,4 @@ def decrypt(self, text, key, alphabet=None): :return: decrypted text :rtype: string """ - return self.__encDec(alphabet, key, text, -1) + return self.__crypt(alphabet, key, text, -1) diff --git a/secretpy/ciphers/columnar_transposition.py b/secretpy/ciphers/columnar_transposition.py index 9d9b942..ca21669 100755 --- a/secretpy/ciphers/columnar_transposition.py +++ b/secretpy/ciphers/columnar_transposition.py @@ -8,39 +8,11 @@ class ColumnarTransposition: The Columnar Transposition Cipher """ - def __dec(self, alphabet, key, text): - chars = [alphabets.get_index_in_alphabet(char, alphabet) - for char in key] - keyorder = sorted(enumerate(chars), key=lambda x: x[1]) - ret = u"" - rows = int(len(text) / len(key)) + def __keyorder(self, alphabet, key): + chars = [alphabet.index(char) for char in key] + return [i for i, _ in sorted(enumerate(chars), key=lambda x: x[1])] - cols = [0] * len(key) - for i, item in enumerate(range(0, len(text), rows)): - cols[keyorder[i][0]] = text[item: item + rows] - - for j in range(rows): - for i in range(len(cols)): - ret += cols[i][j] - return ret - - def __enc(self, alphabet, key, text): - # add endings to the text to fill the square - rmd = len(text) % len(key) - if rmd != 0: - text += alphabet[-1] * (len(key) - rmd) - - chars = [alphabets.get_index_in_alphabet(char, alphabet) - for char in key] - keyorder1 = sorted(enumerate(chars), key=lambda x: x[1]) - - ret = u"" - for i in range(len(key)): - ret += text[keyorder1[i][0]::len(key)] - - return ret - - def encrypt(self, text, key, alphabet=None): + def encrypt(self, text, key, alphabet=alphabets.ENGLISH): """ Encryption method @@ -49,15 +21,15 @@ def encrypt(self, text, key, alphabet=None): :param alphabet: Alphabet which will be used, if there is no a value, English is used :type text: string - :type key: integer + :type key: string :type alphabet: string :return: text :rtype: string """ - alphabet = alphabet or alphabets.ENGLISH - return self.__enc(alphabet, key, text) + keyorder = self.__keyorder(alphabet, key) + return u"".join(text[i::len(key)] for i in keyorder) - def decrypt(self, text, key, alphabet=None): + def decrypt(self, text, key, alphabet=alphabets.ENGLISH): """ Decryption method @@ -66,10 +38,28 @@ def decrypt(self, text, key, alphabet=None): :param alphabet: Alphabet which will be used, if there is no a value, English is used :type text: string - :type key: integer + :type key: string :type alphabet: string :return: text :rtype: string """ - alphabet = alphabet or alphabets.ENGLISH - return self.__dec(alphabet, key, text) + keyorder = self.__keyorder(alphabet, key) + rows, rmd = divmod(len(text), len(key)) + + p = [] + acc = 0 + for i in keyorder: + p.append(acc) + acc += rows + if i < rmd: + acc += 1 + + roworder = [0] * len(key) + for i, j in enumerate(keyorder): + roworder[j] = p[i] + + res = [text[i + row] for row in range(rows) for i in roworder] + # add tail(remainder) to the end of result + for i in roworder[:rmd]: + res.append(text[i + rows]) + return u"".join(res) diff --git a/secretpy/ciphers/four_square.py b/secretpy/ciphers/four_square.py index 8c7f397..e8eefcd 100755 --- a/secretpy/ciphers/four_square.py +++ b/secretpy/ciphers/four_square.py @@ -2,6 +2,7 @@ # -*- encoding: utf-8 -*- from .polybius_square import PolybiusSquare +from secretpy import alphabets as al class FourSquare: @@ -9,44 +10,36 @@ class FourSquare: The Four-Square Cipher """ - def __enc(self, alphabet, text, key, isEncrypt): + def __crypt(self, alphabet, text, key, is_encrypt): square01 = PolybiusSquare(alphabet, key[0]) square10 = PolybiusSquare(alphabet, key[1]) - square = PolybiusSquare(alphabet, "") + square = PolybiusSquare(alphabet) + square00 = square + square11 = square - # text encryption - if len(text) % 2: - text += alphabet[-1][0] - odd = text[1::2] - even = text[::2] - enc = u"" - if isEncrypt: - for i in range(len(even)): - coords = square.get_coordinates(even[i]) - row00 = coords[0] - column00 = coords[1] - - coords = square.get_coordinates(odd[i]) - row11 = coords[0] - column11 = coords[1] - - enc += square01.get_char(row00, column11) - enc += square10.get_char(row11, column00) - else: - for i in range(len(even)): - coords = square01.get_coordinates(even[i]) - row00 = coords[0] - column00 = coords[1] + res = [] + if is_encrypt: + square01, square10, square00, square11 = square00, square11, square01, square10 - coords = square10.get_coordinates(odd[i]) - row11 = coords[0] - column11 = coords[1] - - enc += square.get_char(row00, column11) - enc += square.get_char(row11, column00) - return enc + # text encryption + it = iter(text) + while True: + try: + even = next(it) + except StopIteration: + break + try: + odd = next(it) + except StopIteration: + # add the last letter in the alphabet + odd = alphabet[-1][0] + row00, column00 = square01.get_coordinates(even) + row11, column11 = square10.get_coordinates(odd) + res.append(square00.get_char(row00, column11)) + res.append(square11.get_char(row11, column00)) + return "".join(res) - def encrypt(self, text, key=None, alphabet=None): + def encrypt(self, text, key=None, alphabet=al.ENGLISH_SQUARE_IJ): """ Encryption method @@ -55,21 +48,14 @@ def encrypt(self, text, key=None, alphabet=None): :param alphabet: Alphabet which will be used, if there is no a value, English is used :type text: string - :type key: integer + :type key: tuple of two strings :type alphabet: string :return: text :rtype: string """ - alphabet = alphabet or [ - u"a", u"b", u"c", u"d", u"e", - u"f", u"g", u"h", u"ij", u"k", - u"l", u"m", u"n", u"o", u"p", - u"q", u"r", u"s", u"t", u"u", - u"v", u"w", u"x", u"y", u"z" - ] - return self.__enc(alphabet, text, key, True) + return self.__crypt(alphabet, text, key, True) - def decrypt(self, text, key=None, alphabet=None): + def decrypt(self, text, key=None, alphabet=al.ENGLISH_SQUARE_IJ): """ Decryption method @@ -78,16 +64,9 @@ def decrypt(self, text, key=None, alphabet=None): :param alphabet: Alphabet which will be used, if there is no a value, English is used :type text: string - :type key: integer + :type key: tuple of two strings :type alphabet: string :return: text :rtype: string """ - alphabet = alphabet or [ - u"a", u"b", u"c", u"d", u"e", - u"f", u"g", u"h", u"ij", u"k", - u"l", u"m", u"n", u"o", u"p", - u"q", u"r", u"s", u"t", u"u", - u"v", u"w", u"x", u"y", u"z" - ] - return self.__enc(alphabet, text, key, False) + return self.__crypt(alphabet, text, key, False) diff --git a/secretpy/ciphers/keyword.py b/secretpy/ciphers/keyword.py index e824080..16cf64a 100755 --- a/secretpy/ciphers/keyword.py +++ b/secretpy/ciphers/keyword.py @@ -8,36 +8,26 @@ class Keyword: The Keyword Cipher """ - def __removeDup(self, input_str): - newstring = input_str[0] - for i in range(len(input_str)): - if newstring[(len(newstring) - 1)] != input_str[i]: - newstring += input_str[i] - else: - pass - return newstring - - def __encDec(self, alphabet, key, text, isEncrypt): + def __crypt(self, alphabet, key, text, is_encrypt): # remove repeats of letters in the key newkey = "".join(OrderedDict.fromkeys(key)) # create the substitution string longkey = "".join(OrderedDict.fromkeys(newkey+"".join(alphabet))) # do encryption - ans = "" - for i in range(len(text)): - m = text[i] + res = [] + for i, t in enumerate(text): try: - if isEncrypt == 1: - index = alphabet.index(m) + if is_encrypt == 1: + index = alphabet.index(t) enc = longkey[index] else: - index = longkey.index(m) + index = longkey.index(t) enc = alphabet[index] except ValueError: - wrchar = m.encode('utf-8') + wrchar = t.encode('utf-8') raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") - ans += enc - return ans + res.append(enc) + return "".join(res) def encrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): """ @@ -53,7 +43,7 @@ def encrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :return: text :rtype: string """ - return self.__encDec(alphabet, key, text, 1) + return self.__crypt(alphabet, key, text, 1) def decrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): """ @@ -69,4 +59,4 @@ def decrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :return: text :rtype: string """ - return self.__encDec(alphabet, key, text, -1) + return self.__crypt(alphabet, key, text, -1) diff --git a/secretpy/ciphers/playfair.py b/secretpy/ciphers/playfair.py index 7c94316..248581a 100755 --- a/secretpy/ciphers/playfair.py +++ b/secretpy/ciphers/playfair.py @@ -2,6 +2,7 @@ # -*- encoding: utf-8 -*- from .polybius_square import PolybiusSquare +from secretpy import alphabets as al class Playfair: @@ -9,141 +10,89 @@ class Playfair: The Playfair Cipher """ - def __dec_two_letters(self, a, b, square): + # encrypt or decrypt two letters + def __crypt(self, a, b, square, is_encrypt): cols = square.get_columns() rows = square.get_rows() - coords = square.get_coordinates(a) - arow = coords[0] - acolumn = coords[1] - - coords = square.get_coordinates(b) - brow = coords[0] - bcolumn = coords[1] - - if arow == brow: - a = square.get_char(arow, (acolumn - 1) % cols) - b = square.get_char(brow, (bcolumn - 1) % cols) - elif acolumn == bcolumn: - arow -= 1 - if arow >= rows: - arow = 0 - a = square.get_char(arow, acolumn) - - brow -= 1 - if brow >= rows: - brow = 0 - b = square.get_char(brow, bcolumn) - else: - a = square.get_char(arow, bcolumn) - b = square.get_char(brow, acolumn) - return a + b - - def __enc_two_letters(self, a, b, square): - cols = square.get_columns() - rows = square.get_rows() - - coords = square.get_coordinates(a) - arow = coords[0] - acolumn = coords[1] - - coords = square.get_coordinates(b) - brow = coords[0] - bcolumn = coords[1] + arow, acolumn = square.get_coordinates(a) + brow, bcolumn = square.get_coordinates(b) if arow == brow: - a = square.get_char(arow, (acolumn + 1) % cols) - b = square.get_char(brow, (bcolumn + 1) % cols) + acolumn = (acolumn + is_encrypt) % cols + bcolumn = (bcolumn + is_encrypt) % cols elif acolumn == bcolumn: - arow += 1 + arow += is_encrypt + brow += is_encrypt if arow >= rows: arow = 0 - a = square.get_char(arow, acolumn) - brow += 1 if brow >= rows: brow = 0 - b = square.get_char(brow, bcolumn) else: - a = square.get_char(arow, bcolumn) - b = square.get_char(brow, acolumn) + acolumn, bcolumn = bcolumn, acolumn + a = square.get_char(arow, acolumn) + b = square.get_char(brow, bcolumn) return a + b - def __enc(self, alphabet, text, key): - enc = u"" - insert_char = 'x' - i = 1 - square = PolybiusSquare(alphabet, key) - - while i < len(text): - if text[i-1] == text[i]: - text = text[:i] + insert_char + text[i:] - enc += self.__enc_two_letters(text[i-1], text[i], square) - i += 2 - - if len(text) & 1: - enc += self.__enc_two_letters(text[-1], insert_char, square) - - return enc - - def __dec(self, alphabet, text, key): - dec = "" - insert_char = 'x' - - square = PolybiusSquare(alphabet, key) - - for i in range(1, len(text), 2): - pair = self.__dec_two_letters(text[i-1], text[i], square) - if len(dec) > 1 and dec[-1] == insert_char and pair[0] == dec[-2]: - dec = dec[:-1] + pair[0] - dec += pair[1] - else: - dec += self.__dec_two_letters(text[i-1], text[i], square) - if dec[-1] == insert_char: - dec = dec[:-1] - return dec - - def encrypt(self, text, key="", alphabet=None): + def encrypt(self, text, key="", alphabet=al.ENGLISH_SQUARE_IJ): """ Encryption method :param text: Text to encrypt :param key: Encryption key :param alphabet: Alphabet which will be used, - if there is no a value, English is used + if there is no a value, ENGLISH_SQUARE_IJ is used :type text: string :type key: integer :type alphabet: string :return: text :rtype: string """ - alphabet = alphabet or [ - u"a", u"b", u"c", u"d", u"e", - u"f", u"g", u"h", u"ij", u"k", - u"l", u"m", u"n", u"o", u"p", - u"q", u"r", u"s", u"t", u"u", - u"v", u"w", u"x", u"y", u"z" - ] - return self.__enc(alphabet, text, key) + insert_char = 'x' + square = PolybiusSquare(alphabet, key) - def decrypt(self, text, key="", alphabet=None): + # prepare text + txt = [] + i = 1 + while i < len(text): + txt.append(text[i-1]) + if text[i-1] == text[i]: + txt.append(insert_char) + i += 1 + else: + txt.append(text[i]) + i += 2 + # add the last character + if i == len(text): + txt.append(text[i-1]) + txt.append(insert_char) + + return "".join(self.__crypt(txt[i-1], txt[i], square, 1) for i in range(1, len(txt), 2)) + + def decrypt(self, text, key="", alphabet=al.ENGLISH_SQUARE_IJ): """ Decryption method :param text: Text to decrypt :param key: Decryption key :param alphabet: Alphabet which will be used, - if there is no a value, English is used + if there is no a value, ENGLISH_SQUARE_IJ is used :type text: string :type key: integer :type alphabet: string :return: text :rtype: string """ - alphabet = alphabet or [ - u"a", u"b", u"c", u"d", u"e", - u"f", u"g", u"h", u"ij", u"k", - u"l", u"m", u"n", u"o", u"p", - u"q", u"r", u"s", u"t", u"u", - u"v", u"w", u"x", u"y", u"z" - ] - return self.__dec(alphabet, text, key) + insert_char = 'x' + square = PolybiusSquare(alphabet, key) + + res = [self.__crypt(text[i-1], text[i], square, -1) for i in range(1, len(text), 2)] + # remove the insert character + for i in range(1, len(res)): + if res[i-1][0] == res[i][0] and res[i-1][1] == insert_char: + res[i-1] = res[i-1][0] + # check the last character + if res[-1][1] == insert_char: + res[-1] = res[-1][0] + + return "".join(res) diff --git a/secretpy/ciphers/polybius.py b/secretpy/ciphers/polybius.py index e3152fc..df8667a 100755 --- a/secretpy/ciphers/polybius.py +++ b/secretpy/ciphers/polybius.py @@ -1,6 +1,7 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- +import secretpy.alphabets as al from .polybius_square import PolybiusSquare @@ -9,33 +10,7 @@ class Polybius: The Polybius Cipher """ - def __encDec(self, alphabet, text, key, isEncrypt=True): - square = PolybiusSquare(alphabet, key) - res = "" - header = range(1, square.get_columns() + 1) - header = "".join(map(str, header)) - if isEncrypt: - for char in text: - coords = square.get_coordinates(char) - row = coords[0] - column = coords[1] - res += header[row] + header[column] - else: - for i in range(0, len(text), 2): - try: - row = header.index(text[i]) - except ValueError: - wrchar = text[i].encode('utf-8') - raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") - try: - column = header.index(text[i+1]) - except ValueError: - wrchar = text[i+1].encode('utf-8') - raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") - res += square.get_char(row, column) - return res - - def encrypt(self, text, key="", alphabet=None): + def encrypt(self, text, key="", alphabet=al.ENGLISH_SQUARE_IJ): """ Encryption method @@ -49,16 +24,16 @@ def encrypt(self, text, key="", alphabet=None): :return: text :rtype: string """ - alphabet = alphabet or ( - u"a", u"b", u"c", u"d", u"e", - u"f", u"g", u"h", u"ij", u"k", - u"l", u"m", u"n", u"o", u"p", - u"q", u"r", u"s", u"t", u"u", - u"v", u"w", u"x", u"y", u"z" - ) - return self.__encDec(alphabet, text, key, True) + square = PolybiusSquare(alphabet, key) + header = list(map(str, range(1, square.get_columns() + 1))) + res = [] + for t in text: + row, column = square.get_coordinates(t) + res.append(header[row]) + res.append(header[column]) + return "".join(res) - def decrypt(self, text, key="", alphabet=None): + def decrypt(self, text, key="", alphabet=al.ENGLISH_SQUARE_IJ): """ Decryption method @@ -72,11 +47,19 @@ def decrypt(self, text, key="", alphabet=None): :return: text :rtype: string """ - alphabet = alphabet or ( - u"a", u"b", u"c", u"d", u"e", - u"f", u"g", u"h", u"ij", u"k", - u"l", u"m", u"n", u"o", u"p", - u"q", u"r", u"s", u"t", u"u", - u"v", u"w", u"x", u"y", u"z" - ) - return self.__encDec(alphabet, text, key, False) + square = PolybiusSquare(alphabet, key) + header = list(map(str, range(1, square.get_columns() + 1))) + res = [] + for i in range(1, len(text), 2): + try: + row = header.index(text[i-1]) + except ValueError: + wrchar = text[i-1].encode('utf-8') + raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") + try: + column = header.index(text[i]) + except ValueError: + wrchar = text[i].encode('utf-8') + raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") + res.append(square.get_char(row, column)) + return "".join(res) diff --git a/secretpy/ciphers/polybius_square.py b/secretpy/ciphers/polybius_square.py index 711b36f..85d986b 100755 --- a/secretpy/ciphers/polybius_square.py +++ b/secretpy/ciphers/polybius_square.py @@ -3,27 +3,24 @@ import math from collections import OrderedDict +from secretpy import alphabets as al class PolybiusSquare: """ PolybiusSquare. It's used by many classical ciphers """ - __alphabet = None - __side = 0 def __init__(self, alphabet, key=""): keyi = [] if key: for char in key: - index = self.__find_index_in_alphabet(char, alphabet) + index = al.get_index_in_alphabet(char, alphabet) keyi.append(index) # remove duplicates keyi = OrderedDict.fromkeys(keyi) - alph_out = [] - for i in keyi: - alph_out.append(alphabet[i]) + alph_out = [alphabet[i] for i in keyi] for i in range(len(alphabet)): if i not in keyi: @@ -32,15 +29,6 @@ def __init__(self, alphabet, key=""): self.__alphabet = alph_out self.__side = int(math.ceil(math.sqrt(len(alphabet)))) - def __find_index_in_alphabet(self, char, alphabet): - for j in range(len(alphabet)): - try: - alphabet[j].index(char) - break - except ValueError: - pass - return j - def get_coordinates(self, char): for j in range(len(self.__alphabet)): try: @@ -49,9 +37,7 @@ def get_coordinates(self, char): except ValueError: pass - row = int(j / self.__side) - column = j % self.__side - return (row, column) + return divmod(j, self.__side) def get_char(self, row, column): return self.__alphabet[row * self.__side + column][0] @@ -60,4 +46,4 @@ def get_columns(self): return self.__side def get_rows(self): - return int(len(self.__alphabet) / self.__side) + return len(self.__alphabet) // self.__side diff --git a/secretpy/ciphers/rot13.py b/secretpy/ciphers/rot13.py index 66ec485..199e6e9 100755 --- a/secretpy/ciphers/rot13.py +++ b/secretpy/ciphers/rot13.py @@ -6,21 +6,20 @@ class Rot13: """ - The Rot13 Cipher + The Rot13 Cipher (Half) """ __caesar = Caesar() - __alphabet = al.ENGLISH - - def __encDec(self, alphabet, text): - alphabet = alphabet or self.__alphabet - key = len(alphabet) >> 1 - # if number letters in the alphabet is odd - if len(alphabet) & 1: - alphabet += alphabet[key] + + def __crypt(self, alphabet, text): + alph = alphabet + key = len(alph) >> 1 + # if number of letters in the alphabet is odd + if len(alph) & 1: + alph += alph[key] key += 1 - return self.__caesar.encrypt(text, key, alphabet) + return self.__caesar.encrypt(text, key, alph) - def encrypt(self, text, key=None, alphabet=None): + def encrypt(self, text, key=None, alphabet=al.ENGLISH): """ Encryption method @@ -34,9 +33,9 @@ def encrypt(self, text, key=None, alphabet=None): :return: text :rtype: string """ - return self.__encDec(alphabet, text) + return self.__crypt(alphabet, text) - def decrypt(self, text, key=None, alphabet=None): + def decrypt(self, text, key=None, alphabet=al.ENGLISH): """ Decryption method @@ -50,4 +49,4 @@ def decrypt(self, text, key=None, alphabet=None): :return: text :rtype: string """ - return self.__encDec(alphabet, text) + return self.__crypt(alphabet, text) diff --git a/secretpy/ciphers/rot18.py b/secretpy/ciphers/rot18.py index a5fcf0c..f84e8ad 100755 --- a/secretpy/ciphers/rot18.py +++ b/secretpy/ciphers/rot18.py @@ -10,17 +10,16 @@ class Rot18: """ __rot13 = Rot13() - def __createAlphabet(self, alphabet): + def __create_alphabet(self, alphabet): ahalf = len(alphabet) >> 1 - dhalf = len(al.DECIMAL) >> 1 return ( - alphabet[:ahalf] + al.DECIMAL[:dhalf] + - alphabet[ahalf:] + al.DECIMAL[dhalf:] + alphabet[:ahalf] + al.DECIMAL[:5] + + alphabet[ahalf:] + al.DECIMAL[5:] ) - def __encDec(self, text, alphabet=None): + def __crypt(self, text, alphabet=None): alphabet = alphabet or al.ENGLISH - alphabet = self.__createAlphabet(alphabet) + alphabet = self.__create_alphabet(alphabet) return self.__rot13.encrypt(text, alphabet=alphabet) def encrypt(self, text, key=None, alphabet=None): @@ -37,7 +36,7 @@ def encrypt(self, text, key=None, alphabet=None): :return: text :rtype: string """ - return self.__encDec(text, alphabet) + return self.__crypt(text, alphabet) def decrypt(self, text, key=None, alphabet=None): """ @@ -53,4 +52,4 @@ def decrypt(self, text, key=None, alphabet=None): :return: text :rtype: string """ - return self.__encDec(text, alphabet) + return self.__crypt(text, alphabet) diff --git a/secretpy/ciphers/rot47.py b/secretpy/ciphers/rot47.py index 2dbf455..8599b19 100755 --- a/secretpy/ciphers/rot47.py +++ b/secretpy/ciphers/rot47.py @@ -1,6 +1,6 @@ #!/usr/bin/python -from .rot13 import Rot13 +from .caesar import Caesar class Rot47: @@ -8,13 +8,11 @@ class Rot47: The Rot47 Cipher """ - __rot13 = Rot13() + __caesar = Caesar() + __alphabet = "".join(chr(asc) for asc in range(33, 33 + 47 * 2)) - def __init__(self): - self.__alphabet = "".join([chr(asc) for asc in range(33, 33 + 47*2)]) - - def __encDec(self, text): - return self.__rot13.encrypt(text, alphabet=self.__alphabet) + def __crypt(self, text): + return self.__caesar.encrypt(text, 47, self.__alphabet) def encrypt(self, text, key=None, alphabet=None): """ @@ -30,7 +28,7 @@ def encrypt(self, text, key=None, alphabet=None): :return: text :rtype: string """ - return self.__encDec(text) + return self.__crypt(text) def decrypt(self, text, key=None, alphabet=None): """ @@ -46,4 +44,4 @@ def decrypt(self, text, key=None, alphabet=None): :return: text :rtype: string """ - return self.__encDec(text) + return self.__crypt(text) diff --git a/secretpy/ciphers/rot5.py b/secretpy/ciphers/rot5.py index 5bc262e..063ea70 100755 --- a/secretpy/ciphers/rot5.py +++ b/secretpy/ciphers/rot5.py @@ -1,6 +1,6 @@ #!/usr/bin/python -from .rot13 import Rot13 +from .caesar import Caesar import secretpy.alphabets as al @@ -8,11 +8,7 @@ class Rot5: """ The Rot5 Cipher """ - __rot13 = Rot13() - __alphabet = al.DECIMAL - - def __encDec(self, text): - return self.__rot13.encrypt(text, alphabet=self.__alphabet) + __caesar = Caesar() def encrypt(self, text, key=None, alphabet=None): """ @@ -28,7 +24,7 @@ def encrypt(self, text, key=None, alphabet=None): :return: text :rtype: string """ - return self.__encDec(text) + return self.__caesar.encrypt(text, 5, al.DECIMAL) def decrypt(self, text, key=None, alphabet=None): """ @@ -44,4 +40,4 @@ def decrypt(self, text, key=None, alphabet=None): :return: text :rtype: string """ - return self.__encDec(text) + return self.__caesar.encrypt(text, 5, al.DECIMAL) diff --git a/secretpy/ciphers/scytale.py b/secretpy/ciphers/scytale.py new file mode 100644 index 0000000..56110ac --- /dev/null +++ b/secretpy/ciphers/scytale.py @@ -0,0 +1,53 @@ +#!/usr/bin/python +# -*- encoding: utf-8 -*- + +import secretpy.alphabets as al + + +class Scytale: + """ + The Scytale Cipher + """ + __alphabet = al.ENGLISH + + def __enc(self, text, key, alphabet): + # key is columns + return "".join(text[i::key] for i in range(key)) + + def __dec(self, text, key, alphabet): + full_rows, rmd = len(text) // key, len(text) % key + rows = full_rows + (rmd > 0) + b_index = rows * rmd + res = [text[i:b_index:rows] for i in range(rows)] + add_res = [res[i] + text[b_index+i::full_rows] for i in range(full_rows)] + if rmd: + add_res.append(res[-1]) + return "".join(add_res) + + def encrypt(self, text, key, alphabet=None): + """ + Encryption method + :param text: Text to encrypt + :param key: Encryption key - Number of windings + :param alphabet: Alphabet which will be used, + if there is no a value, English is used + :type text: string + :type key: integer + :return: encrypted text + :rtype: string + """ + return self.__enc(text, key, alphabet) + + def decrypt(self, text, key, alphabet=None): + """ + Decryption method + :param text: Text to decrypt + :param key: Decryption key - Number of windings + :param alphabet: Alphabet which will be used, + if there is no a value, English is used + :type text: string + :type key: integer + :return: decrypted text + :rtype: string + """ + return self.__dec(text, key, alphabet) diff --git a/secretpy/ciphers/simplesubstitution.py b/secretpy/ciphers/simplesubstitution.py index 2d2e938..5c6dbee 100755 --- a/secretpy/ciphers/simplesubstitution.py +++ b/secretpy/ciphers/simplesubstitution.py @@ -7,25 +7,6 @@ class SimpleSubstitution: The Simple Substitution Cipher """ - def __encDec(self, alphabet, key, text, isEncrypt): - if len(alphabet) != len(key): - return - - ans = "" - for i in range(len(text)): - m = text[i] - k = "" - try: - if isEncrypt == 1: - k = key[alphabet.index(m)] - else: - k = alphabet[key.index(m)] - except ValueError: - wrchar = m.encode('utf-8') - raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") - ans += k - return ans - def encrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): """ Encryption method @@ -40,7 +21,17 @@ def encrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :return: text :rtype: string """ - return self.__encDec(alphabet, key, text, 1) + if len(alphabet) != len(key): + return + res = [] + for c in text: + try: + k = key[alphabet.index(c)] + except ValueError: + wrchar = c.encode('utf-8') + raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") + res.append(k) + return "".join(res) def decrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): """ @@ -56,4 +47,14 @@ def decrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :return: text :rtype: string """ - return self.__encDec(alphabet, key, text, -1) + if len(alphabet) != len(key): + return + res = [] + for c in text: + try: + k = alphabet[key.index(c)] + except ValueError: + wrchar = c.encode('utf-8') + raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") + res.append(k) + return "".join(res) diff --git a/secretpy/ciphers/trifid.py b/secretpy/ciphers/trifid.py index 002faf5..a407879 100755 --- a/secretpy/ciphers/trifid.py +++ b/secretpy/ciphers/trifid.py @@ -1,77 +1,34 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- +from secretpy import alphabets as al +from itertools import product + class Trifid: """ The Trifid Cipher """ - alphabet = [ - u"a", u"b", u"c", - u"d", u"e", u"f", - u"g", u"h", u"i", - - u"j", u"k", u"l", - u"m", u"n", u"o", - u"p", u"q", u"r", - - u"s", u"t", u"u", - u"v", u"w", u"x", - u"y", u"z", u".", - ] + alphabet = al.ENGLISH + "." def __code(self, text, alphabet): - code = "" + # prepare coordinates for each character in the alphabet + # coord : (square, row, column) + coords = {c: coord for i, coord in enumerate(product(range(3), repeat=3)) for c in alphabet[i]} + code = [] for char in text: - for index in range(len(alphabet)): - try: - alphabet[index].index(char) - break - except ValueError: - pass - square = int(index / 9) - index = index % 9 - row = int(index / 3) - col = index % 3 - code += str(square+1) + str(row+1) + str(col+1) + code.extend(coords[char]) return code - def __decode(self, text, alphabet): - code = "" - for i in range(0, len(text), 3): - square = int(text[i])-1 - row = int(text[i+1])-1 - col = int(text[i+2])-1 - index = square*9 + row*3 + col - code += alphabet[index][0] - return code - - def __enc(self, alphabet, text, key): - code = self.__code(text, alphabet) - - code0 = "" - for j in range(0, len(text)*3, 3*key): - for i in range(3): - code0 += code[j+i:j+3*key:3] - - code = self.__decode(code0, alphabet) - return code - - def __dec(self, alphabet, text, key): - code = self.__code(text, alphabet) - - code0 = "" - rmd = (len(text) % key) - for j in range(0, (len(text) - rmd) * 3, 3*key): - for i in range(key): - code0 += code[j+i:j+3*key:key] - - j = (len(text) - rmd) * 3 - for i in range(rmd): - code0 += code[j+i:j+3*rmd:rmd] - - code = self.__decode(code0, alphabet) - return code + def __decode(self, code, alphabet): + text = [] + size = 3 + for i in range(0, len(code), size): + index = code[i] # square + index = index * size + code[i+1] # row + index = index * size + code[i+2] # column + text.append(alphabet[index][0]) + return "".join(text) def encrypt(self, text, key=None, alphabet=None): """ @@ -80,7 +37,7 @@ def encrypt(self, text, key=None, alphabet=None): :param text: Text to encrypt :param key: Encryption key :param alphabet: Alphabet which will be used, - if there is no a value, English is used + if there is no a value, English with '.' is used :type text: string :type key: integer :type alphabet: string @@ -88,10 +45,21 @@ def encrypt(self, text, key=None, alphabet=None): :rtype: string """ alphabet = alphabet or self.alphabet + assert len(alphabet) == 27, "Length of the alphabet should be 27" + + size = 3 key = int(key) - if not key > 0: + if key <= 0: key = len(text) - return self.__enc(alphabet, text, key) + code = self.__code(text, alphabet) + + code0 = [] + for j in range(0, len(text)*size, size*key): + for i in range(size): + for item in code[j+i:j+size*key:size]: + code0.append(item) + + return self.__decode(code0, alphabet) def decrypt(self, text, key=None, alphabet=None): """ @@ -100,7 +68,7 @@ def decrypt(self, text, key=None, alphabet=None): :param text: Text to decrypt :param key: Decryption key :param alphabet: Alphabet which will be used, - if there is no a value, English is used + if there is no a value, English with '.' is used :type text: string :type key: integer :type alphabet: string @@ -108,7 +76,20 @@ def decrypt(self, text, key=None, alphabet=None): :rtype: string """ alphabet = alphabet or self.alphabet + assert len(alphabet) == 27, "Length of the alphabet should be 27" + key = int(key) - if not key > 0: + if key <= 0: key = len(text) - return self.__dec(alphabet, text, key) + code = self.__code(text, alphabet) + + size = 3 + res = [] + period = size * key + for i in range(0, len(code), period): + block = code[i:i+period] + third = len(block) // size + # coord : (square, row, column) + for coord in zip(block[:third], block[third:2*third], block[2*third:]): + res.extend(coord) + return self.__decode(res, alphabet) diff --git a/secretpy/ciphers/two_square.py b/secretpy/ciphers/two_square.py index 718c11f..48ba12c 100755 --- a/secretpy/ciphers/two_square.py +++ b/secretpy/ciphers/two_square.py @@ -2,42 +2,43 @@ # -*- encoding: utf-8 -*- from .polybius_square import PolybiusSquare +from secretpy import alphabets as al class TwoSquare: """ - The Two-Square Cipher + The Two-Square Cipher, also called Double Playfair """ - def __enc(self, alphabet, text, key): + def __crypt(self, alphabet, text, key): square1 = PolybiusSquare(alphabet, key[0]) square2 = PolybiusSquare(alphabet, key[1]) # text encryption - if len(text) % 2: - text += alphabet[-1][0] - odd = text[1::2] - even = text[::2] - enc = u"" + res = [] + it = iter(text) + while True: + try: + even = next(it) + except StopIteration: + break + try: + odd = next(it) + except StopIteration: + # add the last letter in the alphabet + odd = alphabet[-1][0] + row1, column1 = square1.get_coordinates(even) + row2, column2 = square2.get_coordinates(odd) - for i in range(len(even)): - coords = square1.get_coordinates(even[i]) - row1 = coords[0] - column1 = coords[1] + if column1 == column2: + row1, row2 = row2, row1 - coords = square2.get_coordinates(odd[i]) - row2 = coords[0] - column2 = coords[1] + res.append(square1.get_char(row1, column2)) + res.append(square2.get_char(row2, column1)) - if column1 == column2: - enc += square1.get_char(row2, column1) - enc += square2.get_char(row1, column1) - else: - enc += square1.get_char(row1, column2) - enc += square2.get_char(row2, column1) - return enc + return "".join(res) - def encrypt(self, text, key=None, alphabet=None): + def encrypt(self, text, key=None, alphabet=al.ENGLISH_SQUARE_IJ): """ Encryption method @@ -51,16 +52,9 @@ def encrypt(self, text, key=None, alphabet=None): :return: text :rtype: string """ - alphabet = alphabet or [ - u"a", u"b", u"c", u"d", u"e", - u"f", u"g", u"h", u"ij", u"k", - u"l", u"m", u"n", u"o", u"p", - u"q", u"r", u"s", u"t", u"u", - u"v", u"w", u"x", u"y", u"z" - ] - return self.__enc(alphabet, text, key) + return self.__crypt(alphabet, text, key) - def decrypt(self, text, key=None, alphabet=None): + def decrypt(self, text, key=None, alphabet=al.ENGLISH_SQUARE_IJ): """ Decryption method @@ -74,11 +68,4 @@ def decrypt(self, text, key=None, alphabet=None): :return: text :rtype: string """ - alphabet = alphabet or [ - u"a", u"b", u"c", u"d", u"e", - u"f", u"g", u"h", u"ij", u"k", - u"l", u"m", u"n", u"o", u"p", - u"q", u"r", u"s", u"t", u"u", - u"v", u"w", u"x", u"y", u"z" - ] - return self.__enc(alphabet, text, key) + return self.__crypt(alphabet, text, key) diff --git a/secretpy/ciphers/vigenere.py b/secretpy/ciphers/vigenere.py index e064cb8..c0abf14 100755 --- a/secretpy/ciphers/vigenere.py +++ b/secretpy/ciphers/vigenere.py @@ -7,24 +7,23 @@ class Vigenere: The Vigenere Cipher """ - def __encDec(self, alphabet, key, text, isEncrypt): - ans = "" - for i in range(len(text)): - char = text[i] + def __crypt(self, alphabet, key, text, is_encrypt): + res = [] + for i, char in enumerate(text): keychar = key[i % len(key)] try: - alphIndex = alphabet.index(char) + a_index = alphabet.index(char) except ValueError: wrchar = char.encode('utf-8') raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") try: - alphIndex += isEncrypt * alphabet.index(keychar) + a_index += is_encrypt * alphabet.index(keychar) except ValueError: wrchar = keychar.encode('utf-8') raise Exception("Can't find char '" + wrchar + "' of text in alphabet!") - alphIndex %= len(alphabet) - ans += alphabet[alphIndex] - return ans + a_index %= len(alphabet) + res.append(alphabet[a_index]) + return "".join(res) def encrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): """ @@ -40,7 +39,7 @@ def encrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :return: text :rtype: string """ - return self.__encDec(alphabet, key, text, 1) + return self.__crypt(alphabet, key, text, 1) def decrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): """ @@ -56,4 +55,4 @@ def decrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): :return: text :rtype: string """ - return self.__encDec(alphabet, key, text, -1) + return self.__crypt(alphabet, key, text, -1) diff --git a/secretpy/ciphers/zigzag.py b/secretpy/ciphers/zigzag.py index 7d9fabf..d3bd63e 100755 --- a/secretpy/ciphers/zigzag.py +++ b/secretpy/ciphers/zigzag.py @@ -4,87 +4,74 @@ class Zigzag: """ - The Zigzag Cipher + The Zigzag Cipher (Rail-Fence) """ - def __enc(self, key, text): - crypted = "" - step = (key - 1) << 1 - textlen = len(text) - - # first row - left = 0 - while (left < textlen): - crypted += text[left] - left += step - - # next rows - for row in range(1, key): - left = row - while (left < textlen): - crypted += text[left] - right = left + step - (row << 1) - if right < textlen and right != left: - crypted += text[right] - left += step - - return crypted - - def __dec(self, key, text): - step = (key - 1) << 1 - textlen = len(text) - decrypted = ["."] * textlen - - # first row - left = 0 - i = 0 - while (left < textlen): - decrypted[left] = text[i] - left += step - i += 1 - - # next rows - for row in range(1, key): - left = row - while (left < textlen): - decrypted[left] = text[i] - i += 1 - right = left + step - (row << 1) - if right < textlen and right != left: - decrypted[right] = text[i] - i += 1 - left += step - - return "".join(decrypted) - - def encrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): + def encrypt(self, text, key, alphabet=None): """ Encryption method :param text: Text to encrypt :param key: Encryption key - :param alphabet: Alphabet which will be used, - if there is no a value, English is used + :param alphabet: unused :type text: string :type key: integer :type alphabet: string :return: text :rtype: string """ - return self.__enc(key, text) + if key <= 0: + return + key0 = key - 1 + step = key0 << 1 - def decrypt(self, text, key, alphabet=u"abcdefghijklmnopqrstuvwxyz"): + # the first row + crypted = [text[::step]] + + # next rows + textlen = len(text) + for row in range(1, key0): + right = step - row + for left in range(row, textlen, step): + crypted.append(text[left]) + if right < textlen: + crypted.append(text[right]) + right += step + # the last row + crypted.append(text[key0::step]) + return "".join(crypted) + + def decrypt(self, text, key, alphabet=None): """ Decryption method :param text: Text to decrypt :param key: Decryption key - :param alphabet: Alphabet which will be used, - if there is no a value, English is used + :param alphabet: unused :type text: string :type key: integer :type alphabet: string :return: text :rtype: string """ - return self.__dec(key, text) + step = (key - 1) << 1 + textlen = len(text) + decrypted = [None] * textlen + + # first row + i = 0 + for left in range(0, textlen, step): + decrypted[left] = text[i] + i += 1 + + # next rows + for row in range(1, key): + for left in range(row, textlen, step): + decrypted[left] = text[i] + i += 1 + right = left + step - (row << 1) + if right < textlen and right != left: + decrypted[right] = text[i] + i += 1 + + return "".join(decrypted) diff --git a/secretpy/cmdecorators/__init__.py b/secretpy/cmdecorators/__init__.py index 6ab042b..4998196 100644 --- a/secretpy/cmdecorators/__init__.py +++ b/secretpy/cmdecorators/__init__.py @@ -7,9 +7,10 @@ from .savecase import SaveCase from .save_all import SaveAll from .remove_non_alphabet import RemoveNonAlphabet +from .block import Block __all__ = [ "UpperCase", "LowerCase", "NoSpaces", "SaveSpaces", "SaveCase", - "SaveAll", "RemoveNonAlphabet" + "SaveAll", "RemoveNonAlphabet", "Block" ] diff --git a/secretpy/cmdecorators/block.py b/secretpy/cmdecorators/block.py new file mode 100755 index 0000000..a720714 --- /dev/null +++ b/secretpy/cmdecorators/block.py @@ -0,0 +1,22 @@ +#!/usr/bin/python +# -*- encoding: utf-8 -*- + +from .decorator import AbstractMachineDecorator + + +class Block(AbstractMachineDecorator): + + def __init__(self, machine, length=5, sep=" "): + self.length = length + self.sep = sep + super(Block, self).__init__(machine) + + def encrypt(self, text): + txt = self._machine.encrypt(text.lower()) + return self.sep.join(txt[i:i+self.length] for i in range(0, len(txt), self.length)) + + def decrypt(self, text): + # remove separator + step = self.length + len(self.sep) + txt = "".join(text[i:i+self.length] for i in range(0, len(text), step)) + return self._machine.decrypt(txt.lower()) diff --git a/secretpy/cmdecorators/lowercase.py b/secretpy/cmdecorators/lowercase.py index 6af62e1..120df5d 100755 --- a/secretpy/cmdecorators/lowercase.py +++ b/secretpy/cmdecorators/lowercase.py @@ -7,7 +7,7 @@ class LowerCase(AbstractMachineDecorator): def encrypt(self, text): - return self._machine.encrypt(text.lower()) + return self._machine.encrypt(text).lower() def decrypt(self, text): - return self._machine.decrypt(text.lower()) + return self._machine.decrypt(text).lower() diff --git a/secretpy/cmdecorators/nospaces.py b/secretpy/cmdecorators/nospaces.py index c55deae..9e3a659 100755 --- a/secretpy/cmdecorators/nospaces.py +++ b/secretpy/cmdecorators/nospaces.py @@ -4,6 +4,7 @@ from .decorator import AbstractMachineDecorator +# Depricated: the functionality included in CryptMachine class NoSpaces(AbstractMachineDecorator): def encrypt(self, text): diff --git a/secretpy/cmdecorators/remove_non_alphabet.py b/secretpy/cmdecorators/remove_non_alphabet.py index 26d7461..d44b613 100755 --- a/secretpy/cmdecorators/remove_non_alphabet.py +++ b/secretpy/cmdecorators/remove_non_alphabet.py @@ -4,16 +4,20 @@ from .decorator import AbstractMachineDecorator +# Depricated: the functionality is included in CryptMachine class RemoveNonAlphabet(AbstractMachineDecorator): def encrypt(self, text): - return self.__encDec(text, lambda text: self._machine.encrypt(text)) + return self.__crypt(text, self._machine.encrypt) def decrypt(self, text): - return self.__encDec(text, lambda text: self._machine.decrypt(text)) + return self.__crypt(text, self._machine.decrypt) - def __encDec(self, text, func): + def __crypt(self, text, func): alphabet = self._machine.get_alphabet() - text2 = filter(lambda char: char in alphabet, text.lower()) - res = func(text2) - return res + # prepare alphabet + alpha = {c: 1 for letters in alphabet for c in letters} + + # filter text by alphabet + res = filter(lambda char: char in alpha, text.lower()) + return func("".join(res)) diff --git a/secretpy/cmdecorators/save_all.py b/secretpy/cmdecorators/save_all.py index f9c59b7..7177a5b 100755 --- a/secretpy/cmdecorators/save_all.py +++ b/secretpy/cmdecorators/save_all.py @@ -7,28 +7,32 @@ class SaveAll(AbstractMachineDecorator): def encrypt(self, text): - return self.__encDec(text, lambda text: self._machine.encrypt(text)) + return self.__crypt(text, self._machine.encrypt) def decrypt(self, text): - return self.__encDec(text, lambda text: self._machine.decrypt(text)) + return self.__crypt(text, self._machine.decrypt) - def __encDec(self, text, func): - chars = [] - upcases = [] + def __crypt(self, text, func): + # make lower case and save indexes + upcases = [i for i, c in enumerate(text) if c.isupper()] + txt = text.lower() + + # prepare alphabet alphabet = self._machine.get_alphabet() - text2 = text - for i, char in enumerate(text2): - if char.isupper(): - upcases.append(i) - text2 = text2.lower() - for i, char in enumerate(text2): - if char not in alphabet: - chars.append(i) - for i in reversed(chars): - text2 = text2[:i] + text2[i+1:] - res = func(text2) + alpha = {c: 1 for letters in alphabet for c in letters} + + # save indexes of non-alphabet characters + chars = [i for i, c in enumerate(txt) if c not in alpha] + + # execute function + res = list(func(txt)) + + # restore non-alphabet characters for i in chars: - res = res[:i] + text[i] + res[i:] + res.insert(i, text[i]) + + # restore uppercase for i in upcases: - res = res[:i] + res[i].upper() + res[i+1:] - return res + res[i] = res[i].upper() + + return "".join(res) diff --git a/secretpy/cmdecorators/savecase.py b/secretpy/cmdecorators/savecase.py index 1efc7ce..897173e 100755 --- a/secretpy/cmdecorators/savecase.py +++ b/secretpy/cmdecorators/savecase.py @@ -7,18 +7,18 @@ class SaveCase(AbstractMachineDecorator): def encrypt(self, text): - return self.__encDec(text, lambda text: self._machine.encrypt(text)) + return self.__crypt(text, self._machine.encrypt) def decrypt(self, text): - return self.__encDec(text, lambda text: self._machine.decrypt(text)) + return self.__crypt(text, self._machine.decrypt) - def __encDec(self, text, func): - uppercases = [] - for i, char in enumerate(text): - if char == char.upper(): - uppercases.append(i) + def __crypt(self, text, func): + uppercases = [i for i, char in enumerate(text) if char == char.upper()] text = text.lower() + res = func(text) + res = list(res) + for i in uppercases: - res = res[:i] + res[i].upper() + res[i+1:] - return res + res[i] = res[i].upper() + return u"".join(res) diff --git a/secretpy/cmdecorators/savespaces.py b/secretpy/cmdecorators/savespaces.py index a5680c3..59b322c 100755 --- a/secretpy/cmdecorators/savespaces.py +++ b/secretpy/cmdecorators/savespaces.py @@ -4,6 +4,7 @@ from .decorator import AbstractMachineDecorator +# depricated: use SaveAll class SaveSpaces(AbstractMachineDecorator): def encrypt(self, text): diff --git a/secretpy/cmdecorators/uppercase.py b/secretpy/cmdecorators/uppercase.py index 1ed3a01..bc3034a 100755 --- a/secretpy/cmdecorators/uppercase.py +++ b/secretpy/cmdecorators/uppercase.py @@ -7,11 +7,7 @@ class UpperCase(AbstractMachineDecorator): def encrypt(self, text): - text = text.lower() - res = self._machine.encrypt(text) - return res.upper() + return self._machine.encrypt(text).upper() def decrypt(self, text): - text = text.lower() - res = self._machine.decrypt(text) - return res.upper() + return self._machine.decrypt(text).upper() diff --git a/secretpy/cryptmachine.py b/secretpy/cryptmachine.py index ab1ed44..9be3185 100755 --- a/secretpy/cryptmachine.py +++ b/secretpy/cryptmachine.py @@ -1,6 +1,7 @@ #!/usr/bin/python from .abstractmachine import AbstractCryptMachine +from .cmdecorators import RemoveNonAlphabet from secretpy import alphabets @@ -9,6 +10,7 @@ def __init__(self, cipher, key=None, alphabet=alphabets.ENGLISH): self.__alphabet = alphabet self.__key = key or "" self.__cipher = cipher + self.__decorator = RemoveNonAlphabet(self) def set_key(self, key): self.__key = key @@ -23,7 +25,14 @@ def set_cipher(self, cipher): self.__cipher = cipher def encrypt(self, text): - return self.__cipher.encrypt(text, self.__key, self.__alphabet) + return self.__crypt(text, self.__cipher.encrypt) def decrypt(self, text): - return self.__cipher.decrypt(text, self.__key, self.__alphabet) + return self.__crypt(text, self.__cipher.decrypt) + + def __crypt(self, text, func): + # prepare alphabet + alpha = {c: 1 for letters in self.__alphabet for c in letters} + # filter text by alphabet + txt = "".join(filter(lambda c: c in alpha, text.lower())) + return func(txt, self.__key, self.__alphabet) diff --git a/setup.py b/setup.py index 8c673df..b550a94 100755 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setuptools.setup( name="secretpy", - version="0.10.0", + version="0.11.0", author="Max Vetrov", author_email="maxvetrov555@yandex.ru", description="Classical ciphers", diff --git a/tests/test_affine.py b/tests/test_affine.py index 9993975..fd3553f 100755 --- a/tests/test_affine.py +++ b/tests/test_affine.py @@ -29,7 +29,7 @@ class TestAffine(unittest.TestCase): u"даэяд", u"vgtvjiwövhewöv", u"fsñbsvizbwbabtac", - u"うぁらろわいく") + u"きおらゃわこぎ") def test_encrypt(self): for i, alphabet in enumerate(self.alphabet): diff --git a/tests/test_atbash.py b/tests/test_atbash.py index e5daec8..91f950b 100755 --- a/tests/test_atbash.py +++ b/tests/test_atbash.py @@ -29,7 +29,7 @@ class TestAtbash(unittest.TestCase): u"мъфнм", u"kzgkqßöwkmvöwk", u"fnñvnhzqvwvgvcgl", - u"ぶすれどるしび") + u"ばさりづらごほ") def test_encrypt(self): for i, alphabet in enumerate(self.alphabet): diff --git a/tests/test_autokey.py b/tests/test_autokey.py index b1b01bb..0fbb2a5 100755 --- a/tests/test_autokey.py +++ b/tests/test_autokey.py @@ -34,7 +34,7 @@ class TestAutokey(unittest.TestCase): u"эриие", u"hgaalsulagmzäc", u"wxmzqnnuipwtnbws", - u"ぐたぜぁふへふ") + u"ごつぜぁふばふ") def test_encrypt(self): for i, alphabet in enumerate(self.alphabet): diff --git a/tests/test_beaufort.py b/tests/test_beaufort.py index c26274a..13dfd88 100755 --- a/tests/test_beaufort.py +++ b/tests/test_beaufort.py @@ -34,7 +34,7 @@ class TestBeaufort(unittest.TestCase): u"ßüowpsqöwbyfej", u"iyorrklrrbyrwylñ", u"шжуёш", - u"だゆいれべやも") + u"だもいりべめむ") def test_encrypt(self): cipher = Beaufort() diff --git a/tests/test_bifid.py b/tests/test_bifid.py index 6444887..8252ea5 100755 --- a/tests/test_bifid.py +++ b/tests/test_bifid.py @@ -1,8 +1,7 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import Bifid -from secretpy import alphabets +from secretpy import Bifid, alphabets from unittest import TestCase, main diff --git a/tests/test_caesar.py b/tests/test_caesar.py index 9d789f1..b21879d 100755 --- a/tests/test_caesar.py +++ b/tests/test_caesar.py @@ -22,14 +22,16 @@ class TestCaesar(unittest.TestCase): u"съешьжеещёэтихмягкихфранцузскихбулокдавыпейчаю", u"textnachtricht", u"unmensajedetexto", - u"だやぎへぐゆぢ") + u"あいうえおかきくけこがぎぐげごさしすせそざじずぜぞたちつてとだぢづでどなにぬねのはひふへほばびぶべぼぱぴぷぺぽまみむめもやゆよらりるれろわをんゃゅょぁぇ" + ) ciphertext = ( u"qebnrfzhyoltkclugrjmplsboqebixwvald", u"фэзыяйззьиахлшпвёнлшчугрщцкфнлшдцоснжгеютзмъгб", u"whäwqdfkwulfkw", u"xpohpvdmhghwhawr", - u"でらごびさりど") + u"えおかきくけこがぎぐげごさしすせそざじずぜぞたちつてとだぢづでどなにぬねのはひふへほばびぶべぼぱぴぷぺぽまみむめもやゆよらりるれろわをんゃゅょぁぇあいう" + ) def test_encrypt(self): for i, alphabet in enumerate(self.alphabet): diff --git a/tests/test_caesar_progressive.py b/tests/test_caesar_progressive.py index f2e461b..972e7c8 100755 --- a/tests/test_caesar_progressive.py +++ b/tests/test_caesar_progressive.py @@ -30,7 +30,7 @@ class TestCaesarProgressive(unittest.TestCase): u"ъдпдифуфйчпёэкгцыдгррнюмцфйфонызыфшхпмпйяхыйут", u"ämcßympvedzuäj", u"yrrlubktppritñlh", - u"へぁちもといぱ" + u"へぁちもとえぱ" ) cipher = CaesarProgressive() diff --git a/tests/test_columnar_transposition.py b/tests/test_columnar_transposition.py index b7e26d9..4360ea6 100755 --- a/tests/test_columnar_transposition.py +++ b/tests/test_columnar_transposition.py @@ -9,9 +9,14 @@ class TestColumnarTransposition(unittest.TestCase): alphabet = ( alphabets.ENGLISH, + alphabets.ENGLISH, + alphabets.ENGLISH, + alphabets.GERMAN, + alphabets.SPANISH, ) key = ( + u"zebras", u"zebras", u"german", u"schlüssel", @@ -20,6 +25,7 @@ class TestColumnarTransposition(unittest.TestCase): plaintext = ( u"wearediscoveredfleeatonceqkjeu", + u"wearediscoveredfleeatonce", u"defendtheeastwallofthecastlexx", u"textnachtricht", u"unmensaiedetexto", @@ -27,9 +33,10 @@ class TestColumnarTransposition(unittest.TestCase): ciphertext = ( u"evlneacdtkeseaqrofojdeecuwiree", + u"evlnacdtesearofodeecwiree", u"nalcxehwttdttfseeleedsoaxfeahl", - u"111111111", - u"222222222222222", + u"eihxcthttracnt", + u"mieuseondtnateex", ) cipher = ColumnarTransposition() diff --git a/tests/test_composite.py b/tests/test_composite.py index 5eefa06..90d155f 100755 --- a/tests/test_composite.py +++ b/tests/test_composite.py @@ -37,9 +37,9 @@ def test_main(self, Atbash, Caesar): self.assertEqual(dec, "ATBASH_DECRYPTED") cipher2.encrypt.assert_called_with( - "CAESAR_ENCRYPTED", "", u"abcdefghijklmnopqrstuvwxyz") + "caesarencrypted", "", u"abcdefghijklmnopqrstuvwxyz") cipher2.decrypt.assert_called_with( - "CAESAR_DECRYPTED", "", u"abcdefghijklmnopqrstuvwxyz") + "caesardecrypted", "", u"abcdefghijklmnopqrstuvwxyz") if __name__ == '__main__': diff --git a/tests/test_cryptmachine.py b/tests/test_cryptmachine.py index ca00351..4666eed 100755 --- a/tests/test_cryptmachine.py +++ b/tests/test_cryptmachine.py @@ -31,7 +31,7 @@ def test_main(self, Caesar): cipher.encrypt.assert_called_with( "text", 5, u"abcdefghijklmnopqrstuvwxyz") cipher.decrypt.assert_called_with( - "ENCRYPTED", 5, u"abcdefghijklmnopqrstuvwxyz") + "encrypted", 5, u"abcdefghijklmnopqrstuvwxyz") if __name__ == '__main__': diff --git a/tests/test_four_square.py b/tests/test_four_square.py index e3f08d9..4b8ec3f 100755 --- a/tests/test_four_square.py +++ b/tests/test_four_square.py @@ -1,8 +1,7 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- -from secretpy import FourSquare -from secretpy import alphabets +from secretpy import FourSquare, alphabets import unittest diff --git a/tests/test_rot13.py b/tests/test_rot13.py index 4eda819..fc5f352 100755 --- a/tests/test_rot13.py +++ b/tests/test_rot13.py @@ -30,7 +30,7 @@ class TestRot13(TestCase): u"вхыбв", u"etieüprwecxrwe", u"hnzrnfñwrqrgrkgb", - u"をじぱおぴずん" + u"わずぼかぱぜを", ) cipher = Rot13() diff --git a/tests/test_scytale.py b/tests/test_scytale.py new file mode 100644 index 0000000..5999474 --- /dev/null +++ b/tests/test_scytale.py @@ -0,0 +1,42 @@ +#!/usr/bin/python +# -*- encoding: utf-8 -*- + + +from secretpy import Scytale +from secretpy import alphabets +import unittest + + +class TestScytale(unittest.TestCase): + alphabet = ( + alphabets.ENGLISH + ) + + key = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + + plaintext = "Iamhurtverybadlyhelp" + + ciphertext = ["Iamhurtverybadlyhelp", # 1 + "Imuteyalhlahrvrbdyep", # 2 + "Ihtraylauvydhpmreble", # 3 + "Iueaharrdemtyllhvbyp", # 4 + "Iryyatbhmvaehedlurlp", # 5 + "Italavdpmelhryuyhrbe", # 6 + "Ivlaeymrhhyeublraptd", # 7 + "Ieharemylhbpuardtlvy", # 8 + "Irlaypmbhaudrltyvhee", # 9 + "Iyabmahdulrythveelrp"] # 10 + + def test_encrypt(self): + for i, key in enumerate(self.key): + enc = Scytale().encrypt(self.plaintext, key, self.alphabet) + self.assertEqual(enc, self.ciphertext[i]) + + def test_decrypt(self): + for i, key in enumerate(self.key): + dec = Scytale().decrypt(self.ciphertext[i], key, self.alphabet) + self.assertEqual(dec, self.plaintext) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_simplesubstitution.py b/tests/test_simplesubstitution.py index 3dcdaa1..d1f6e99 100755 --- a/tests/test_simplesubstitution.py +++ b/tests/test_simplesubstitution.py @@ -38,7 +38,7 @@ class TestSimpleSubstitution(TestCase): u"わを" u"ん" u"ゃゅょぁぇ" - u"じづあ" + u"あ" ) ) diff --git a/tests/test_vigenere.py b/tests/test_vigenere.py index 39f0a41..86d9bfa 100755 --- a/tests/test_vigenere.py +++ b/tests/test_vigenere.py @@ -34,7 +34,7 @@ class TestVigenere(unittest.TestCase): u"эрииэ", u"hgaalsulafkjsr", u"wxmzquljzhgeesxq", - u"ぐたぜぁゅちへ") + u"ごつぜぁゅてへ") def test_encrypt(self): for i, alphabet in enumerate(self.alphabet):