├── .gitignore ├── AtBash.py ├── Bacon.py ├── Bifid.py ├── Caesar.py ├── CharFreq.py ├── Polybius.py ├── README.md ├── char_freq.ico ├── encryption.ico ├── make_exe.bat ├── setup_atbash.py ├── setup_bacon.py ├── setup_bifid.py ├── setup_caesar.py ├── setup_char_freq.py └── setup_polybius.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | 21 | # Installer logs 22 | pip-log.txt 23 | 24 | # Unit test / coverage reports 25 | .coverage 26 | .tox 27 | nosetests.xml 28 | 29 | # Translations 30 | *.mo 31 | 32 | # Mr Developer 33 | .mr.developer.cfg 34 | .project 35 | .pydevproject 36 | 37 | # PyCharm 38 | .idea -------------------------------------------------------------------------------- /AtBash.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from unicodedata import normalize 3 | import optparse 4 | import codecs 5 | import sys 6 | 7 | __author__ = 'Lukasz Banasiak ' 8 | __version__ = '1.1' 9 | 10 | 11 | def atbash(words, mode=0): 12 | """AtBash cipher. 13 | 14 | Atbash is a simple substitution cipher for the Hebrew alphabet. 15 | 16 | :param words: string to encrypt 17 | :param mode: set alphabet to use. 18 | 0 for replace diacritic marks 19 | 1 for EN 20 | 2 for PL 21 | :return: encrypted string 22 | """ 23 | 24 | if mode == 1: 25 | alphabet = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') 26 | elif mode == 2: 27 | alphabet = list(u'AĄBCĆDEĘFGHIJKLŁMNŃOÓPRSŚTUWYZŹŻ') 28 | else: 29 | alphabet = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') 30 | words = normalize('NFKD', words).encode('ascii', 'ignore') # replace national characters to ASCII equivalents 31 | 32 | cipher = '' 33 | 34 | for word in words: 35 | if not word.upper() in alphabet: 36 | cipher += word 37 | else: 38 | if word in [x.lower() for x in alphabet]: 39 | cipher += alphabet[len(alphabet) - alphabet.index(word.upper()) - 1 % len(alphabet)].lower() 40 | else: 41 | cipher += alphabet[len(alphabet) - alphabet.index(word) - 1 % len(alphabet)] 42 | return cipher 43 | 44 | 45 | if __name__ == '__main__': 46 | parser = optparse.OptionParser(version=__version__, 47 | usage='Usage: %prog [options] [args]', 48 | description='Atbash is a simple substitution cipher for the Hebrew alphabet.') 49 | parser.add_option('-d', dest='decrypt', action='store_true', default=False, 50 | help='tryb deszyfrowania') 51 | parser.add_option('-l', dest='lang', action='store', default=0, 52 | help='''ustawienie kodowania tekstu:\n 53 | 0 - zamiana znakow diakrytycznych na ich odpowiedniki\n 54 | 1 - kodowanie dla angielskiego alfabetu\n 55 | 2 - kodowanie dla polskiego alfabetu''', type='int') 56 | parser.add_option('-f', dest='file', action='store', default=False, 57 | help='wskaz plik z tekstem do (de)szyfrowania') 58 | 59 | (options, args) = parser.parse_args() 60 | 61 | print '' 62 | print 'Szyfr AtBash' 63 | print '' 64 | print ' Autor: ' + __author__ 65 | 66 | if options.lang == 1: 67 | print ' Kodowanie: dla angielskiego alfabetu' 68 | elif options.lang == 2: 69 | print ' Kodowanie: dla polskiego alfabetu' 70 | else: 71 | print ' Kodowanie: zamiana znakow diakrytycznych na ich odpowiedniki' 72 | 73 | if options.file: 74 | print '' 75 | print ' IN> ' + options.file 76 | 77 | try: 78 | file_stream = codecs.open(options.file, 'r', 'dbcs') 79 | file_output = codecs.open('_' + options.file, 'w', 'dbcs') 80 | for line in file_stream: 81 | file_output.write(atbash(line, mode=options.lang)) 82 | file_stream.close() 83 | file_output.close() 84 | except IOError as e: 85 | print '\nI/O error({0}): {1}'.format(e.errno, e.strerror) 86 | sys.exit(1) 87 | 88 | print 'OUT> ' + '_' + options.file 89 | 90 | else: 91 | while 1: 92 | print '' 93 | try: 94 | text = raw_input(' IN> ').decode(sys.stdin.encoding) 95 | print 'OUT> ' + atbash(text, mode=options.lang) 96 | except (SystemExit, KeyboardInterrupt): 97 | sys.exit(0) 98 | -------------------------------------------------------------------------------- /Bacon.py: -------------------------------------------------------------------------------- 1 | from unicodedata import normalize 2 | import optparse 3 | import codecs 4 | import sys 5 | import re 6 | 7 | __author__ = 'Lukasz Banasiak ' 8 | __version__ = '1.0' 9 | 10 | 11 | def generate_dict(): 12 | 13 | """ 14 | Create Bacon dictionary. 15 | 16 | a AAAAA g AABBA n ABBAA t BAABA 17 | b AAAAB h AABBB o ABBAB u-v BAABB 18 | c AAABA i-j ABAAA p ABBBA w BABAA 19 | d AAABB k ABAAB q ABBBB x BABAB 20 | e AABAA l ABABA r BAAAA y BABBA 21 | f AABAB m ABABB s BAAAB z BABBB 22 | 23 | :return: Bacon dict 24 | """ 25 | 26 | bacon_dict = {} 27 | 28 | for i in xrange(0, 26): 29 | tmp = bin(i)[2:].zfill(5) 30 | tmp = tmp.replace('0', 'a') 31 | tmp = tmp.replace('1', 'b') 32 | bacon_dict[tmp] = chr(65 + i) 33 | 34 | return bacon_dict 35 | 36 | 37 | def encode(words, bacon_dict): 38 | 39 | """ 40 | Encrypt text to Bacon's cipher. 41 | 42 | :param words: string to encrypt 43 | :param bacon_dict: Bacon dict 44 | :return: encrypted string 45 | """ 46 | 47 | cipher = '' 48 | bacon_dict = {v: k for k, v in bacon_dict.items()} # hack to get key from value - reverse dict 49 | words = normalize('NFKD', words).encode('ascii', 'ignore') # replace national characters to ASCII equivalents 50 | words = words.upper() 51 | words = re.sub(r'[^A-Z]+', '', words) 52 | 53 | for i in words: 54 | cipher += bacon_dict.get(i).upper() 55 | return cipher 56 | 57 | 58 | def decode(words, bacon_dict): 59 | 60 | """ 61 | Decrypt Bacon's cipher to text. 62 | 63 | :param words: string to decrypt 64 | :param bacon_dict: Bacon dict 65 | :return: decrypted string 66 | """ 67 | 68 | cipher = '' 69 | words = words.lower() 70 | words = re.sub(r'[^ab]+', '', words) 71 | 72 | for i in xrange(0, len(words) / 5): 73 | cipher += bacon_dict.get(words[i * 5:i * 5 + 5], ' ') 74 | return cipher 75 | 76 | 77 | if __name__ == '__main__': 78 | parser = optparse.OptionParser(version=__version__, 79 | usage='Usage: %prog [options] [args]', 80 | description='Method of steganography devised by Francis Bacon in 1605.') 81 | parser.add_option('-d', dest='decrypt', action='store_true', default=False, 82 | help='tryb deszyfrowania') 83 | parser.add_option('-f', dest='file', action='store', default=False, 84 | help='wskaz plik z tekstem do (de)szyfrowania') 85 | 86 | (options, args) = parser.parse_args() 87 | 88 | print '' 89 | print 'Szyfr Bacona' 90 | print '' 91 | print ' Autor: ' + __author__ 92 | 93 | if options.decrypt: 94 | print ' Tryb: Deszyfrowanie' 95 | else: 96 | print ' Tryb: Szyfrowanie' 97 | 98 | bacon_dict = generate_dict() 99 | 100 | if options.file: 101 | print '' 102 | print ' IN> ' + options.file 103 | 104 | try: 105 | file_stream = codecs.open(options.file, 'r', 'dbcs') 106 | file_output = codecs.open('_' + options.file, 'w', 'dbcs') 107 | for line in file_stream: 108 | if options.decrypt: 109 | file_output.write(decode(line, bacon_dict)) 110 | else: 111 | file_output.write(encode(line, bacon_dict)) 112 | file_stream.close() 113 | file_output.close() 114 | except IOError as e: 115 | print '\nI/O error({0}): {1}'.format(e.errno, e.strerror) 116 | sys.exit(1) 117 | 118 | print 'OUT> ' + '_' + options.file 119 | 120 | else: 121 | while 1: 122 | print '' 123 | try: 124 | text = raw_input(' IN> ').decode(sys.stdin.encoding) 125 | if options.decrypt: 126 | print 'OUT> ' + decode(text, bacon_dict) 127 | else: 128 | print 'OUT> ' + encode(text, bacon_dict) 129 | except (SystemExit, KeyboardInterrupt): 130 | sys.exit(0) -------------------------------------------------------------------------------- /Bifid.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import Polybius 3 | import optparse 4 | import codecs 5 | import sys 6 | import re 7 | 8 | __author__ = 'Lukasz Banasiak ' 9 | __version__ = '1.0' 10 | 11 | 12 | def transform(data): 13 | 14 | data = re.sub(r'[\D]+', '', data) 15 | 16 | return data[::2] + data[1::2] 17 | 18 | 19 | def transform_back(data): 20 | 21 | data = re.sub(r'[\D]+', '', data) 22 | numbers = '' 23 | 24 | a, b = (data[:len(data) / 2], data[len(data) / 2:]) 25 | 26 | for i in range(len(a)): 27 | numbers += a[i] + b[i] 28 | 29 | return numbers 30 | 31 | 32 | if __name__ == '__main__': 33 | parser = optparse.OptionParser(version=__version__, 34 | usage='Usage: %prog [options] [args]', 35 | description='Bifid cipher is a cipher which combines the Polybius square with transposition, and uses fractionation to achieve diffusion.') 36 | parser.add_option('-d', dest='decrypt', action='store_true', default=False, 37 | help='tryb deszyfrowania') 38 | parser.add_option('-k', dest='key', action='store', default='', type='string', 39 | help='klucz transformacji szachownicy') 40 | parser.add_option('-V', dest='verbose', action='store_true', default=False, 41 | help='pokazuje posrednie etapy') 42 | parser.add_option('-f', dest='file', action='store', default=False, 43 | help='wskaz plik z tekstem do (de)szyfrowania') 44 | 45 | (options, args) = parser.parse_args() 46 | 47 | print '' 48 | print 'Szyfr Delastelle\'a' 49 | print '' 50 | print ' Autor: ' + __author__ 51 | 52 | if options.decrypt: 53 | print ' Tryb: Deszyfrowanie' 54 | else: 55 | print ' Tryb: Szyfrowanie' 56 | 57 | if options.verbose: 58 | print 'Tryb verbose: Tak' 59 | else: 60 | print 'Tryb verbose: Nie' 61 | 62 | array = Polybius.generate_array(key=options.key) 63 | 64 | print ' Szachownica:' 65 | Polybius.display_array(array) 66 | 67 | if options.file: 68 | print '' 69 | print ' IN> ' + options.file 70 | 71 | try: 72 | file_stream = codecs.open(options.file, 'r', 'dbcs') 73 | file_output = codecs.open('_' + options.file, 'w', 'dbcs') 74 | for line in file_stream: 75 | if options.decrypt: 76 | file_output.write(Polybius.decode( 77 | transform_back( 78 | Polybius.encode(line, array)), array)) 79 | else: 80 | file_output.write(Polybius.decode( 81 | transform( 82 | Polybius.encode(line, array)), array)) 83 | file_stream.close() 84 | file_output.close() 85 | except IOError as e: 86 | print '\nI/O error({0}): {1}'.format(e.errno, e.strerror) 87 | sys.exit(1) 88 | 89 | print 'OUT> ' + '_' + options.file 90 | 91 | else: 92 | while 1: 93 | print '' 94 | try: 95 | text = raw_input(' IN> ').decode(sys.stdin.encoding) 96 | if options.decrypt: 97 | if options.verbose: 98 | print ' 1: %s # po wyznaczeniu wspolrzednych' % Polybius.format_cipher( 99 | Polybius.encode(text, array)) 100 | print ' 2: %s # po transformacji poziomej' % Polybius.format_cipher( 101 | transform_back( 102 | Polybius.encode(text, array))) 103 | print 'OUT> ' + Polybius.decode( 104 | transform_back( 105 | Polybius.encode(text, array)), array) 106 | else: 107 | if options.verbose: 108 | print ' 1: %s # po wyznaczeniu wspolrzednych' % Polybius.format_cipher( 109 | Polybius.encode(text, array)) 110 | print ' 2: %s # po transformacji poziomej' % Polybius.format_cipher( 111 | transform_back( 112 | Polybius.encode(text, array))) 113 | print 'OUT> ' + Polybius.decode( 114 | transform( 115 | Polybius.encode(text, array)), array) 116 | except (SystemExit, KeyboardInterrupt): 117 | sys.exit(0) -------------------------------------------------------------------------------- /Caesar.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from unicodedata import normalize 3 | import optparse 4 | import codecs 5 | import sys 6 | 7 | __author__ = 'Lukasz Banasiak ' 8 | __version__ = '1.1' 9 | 10 | 11 | def caesar(words, shift, mode=0): 12 | """Caesar cipher. 13 | 14 | Simplest and most widely known encryption techniques. 15 | 16 | :param words: string to encrypt 17 | :param shift: number to rotate 18 | :param mode: set alphabet to use. 19 | 0 for replace diacritic marks 20 | 1 for EN 21 | 2 for PL 22 | :return: encrypted string 23 | """ 24 | 25 | if mode == 1: 26 | alphabet = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') 27 | elif mode == 2: 28 | alphabet = list(u'AĄBCĆDEĘFGHIJKLŁMNŃOÓPRSŚTUWYZŹŻ') 29 | else: 30 | alphabet = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') 31 | words = normalize('NFKD', words).encode('ascii', 'ignore') # replace national characters to ASCII equivalents 32 | 33 | cipher = '' 34 | 35 | for word in words: 36 | if not word.upper() in alphabet: 37 | cipher += word 38 | else: 39 | if word in [x.lower() for x in alphabet]: 40 | cipher += alphabet[(alphabet.index(word.upper()) + shift) % len(alphabet)].lower() 41 | else: 42 | cipher += alphabet[(alphabet.index(word) + shift) % len(alphabet)] 43 | return cipher 44 | 45 | 46 | if __name__ == '__main__': 47 | parser = optparse.OptionParser(version=__version__, 48 | usage='Usage: %prog [options] [args]', 49 | description='In cryptography a Caesar cipher is one of the simplest and most widely known encryption techniques.') 50 | parser.add_option('-d', dest='decrypt', action='store_true', default=False, 51 | help='tryb deszyfrowania') 52 | parser.add_option('-s', dest='shift', action='store', default=3, 53 | help='liczba przesuniecia wzgledem pierwszej litery alfabetu', type="int") 54 | parser.add_option('-l', dest='lang', action='store', default=0, 55 | help='''ustawienie kodowania tekstu:\n 56 | 0 - zamiana znakow diakrytycznych na ich odpowiedniki\n 57 | 1 - kodowanie dla angielskiego alfabetu\n 58 | 2 - kodowanie dla polskiego alfabetu''', type="int") 59 | parser.add_option('-f', dest='file', action='store', default=False, 60 | help='wskaz plik z tekstem do (de)szyfrowania') 61 | 62 | (options, args) = parser.parse_args() 63 | 64 | print '' 65 | print 'Szyfr Cezara' 66 | print '' 67 | print ' Autor: ' + __author__ 68 | 69 | if options.lang == 1: 70 | print ' Kodowanie: dla angielskiego alfabetu' 71 | elif options.lang == 2: 72 | print ' Kodowanie: dla polskiego alfabetu' 73 | else: 74 | print ' Kodowanie: zamiana znakow diakrytycznych na ich odpowiedniki' 75 | 76 | print 'Przesuniecie: ' + str(options.shift) 77 | 78 | if options.decrypt: 79 | print ' Tryb: Deszyfrowanie' 80 | options.shift = options.shift.__neg__() 81 | else: 82 | print ' Tryb: Szyfrowanie' 83 | 84 | if options.file: 85 | print '' 86 | print ' IN> ' + options.file 87 | 88 | try: 89 | file_stream = codecs.open(options.file, 'r', 'dbcs') 90 | file_output = codecs.open('_' + options.file, 'w', 'dbcs') 91 | for line in file_stream: 92 | file_output.write(caesar(line, options.shift, mode=options.lang)) 93 | file_stream.close() 94 | file_output.close() 95 | except IOError as e: 96 | print '\nI/O error({0}): {1}'.format(e.errno, e.strerror) 97 | sys.exit(1) 98 | 99 | print 'OUT> ' + '_' + options.file 100 | 101 | else: 102 | while 1: 103 | print '' 104 | try: 105 | text = raw_input(' IN> ').decode(sys.stdin.encoding) 106 | print 'OUT> ' + caesar(text, options.shift, mode=options.lang) 107 | except (SystemExit, KeyboardInterrupt): 108 | sys.exit(0) 109 | -------------------------------------------------------------------------------- /CharFreq.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from collections import Counter 3 | from math import log, ceil 4 | from heapq import heappush, heappop, heapify 5 | from unicodedata import normalize as norm 6 | import codecs 7 | import optparse 8 | import re 9 | import sys 10 | 11 | __author__ = 'Lukasz Banasiak' 12 | __version__ = '1.1' 13 | __description__ = """In cryptanalysis, frequency analysis is the study 14 | of the frequency of letters or groups of letters in a ciphertext.""" 15 | 16 | 17 | def national2ascii(data): 18 | return norm('NFKD', data).encode('ascii', 'ignore') 19 | 20 | 21 | def huffman(counter): 22 | heap = [[wt, [sym, ""]] for sym, wt in counter.items()] 23 | heapify(heap) 24 | while len(heap) > 1: 25 | lo = heappop(heap) 26 | hi = heappop(heap) 27 | for pair in lo[1:]: 28 | pair[1] = '0' + pair[1] 29 | for pair in hi[1:]: 30 | pair[1] = '1' + pair[1] 31 | heappush(heap, [lo[0] + hi[0]] + lo[1:] + hi[1:]) 32 | return sorted(heappop(heap)[1:], key=lambda p: (len(p[-1]), p)) 33 | 34 | 35 | def fi(per, v): 36 | return per/100 * int(ceil(v)) 37 | 38 | 39 | def hi(per): 40 | return -log(per/100, 2) 41 | 42 | 43 | def entropy(per): 44 | return -(per/100 * log(per/100, 2)) 45 | 46 | 47 | def percentage(p, lns): 48 | return float(p) / float(lns) * 100 49 | 50 | 51 | def count(words, all_chars=False, normalize=False): 52 | """Character frequency analysis. 53 | 54 | A simple analysis of the characters in the text. 55 | 56 | :param words: string to count 57 | :param all_chars: set counting all characters 58 | :param normalize: replace national characters to ASCII equivalents 59 | """ 60 | 61 | if normalize: 62 | words = national2ascii(words) 63 | 64 | regex = re.compile(u'^[a-zA-ZĄĘŚĆŻŹŁÓĆŃąęśćżźłóćń]+$') 65 | counter = Counter() 66 | 67 | for char in words: 68 | if not all_chars: 69 | if regex.match(char): 70 | counter[char] += 1 71 | else: 72 | if not char in ['\r', '\n', u'\u2013']: 73 | counter[char] += 1 74 | return counter 75 | 76 | 77 | def _print(counter): 78 | H = [] 79 | L = [] 80 | print 'Char\tCount\t\tPercent\tHi\tFi\tHuffman' 81 | print '-'*70 82 | for char in huffman(counter): 83 | per = percentage(counter[char[0]], sum(counter.values())) 84 | h = entropy(per) 85 | H.append(h) 86 | l = fi(per, hi(per)) 87 | L.append(l) 88 | print '%s\t%d\t\t%.3f%%\t%.3f\t%.3f\t%s' % (char[0], counter[char[0]], per, hi(per), l, char[1]) 89 | print '-'*70 90 | print '+:\t%s' % sum(counter.values()) 91 | print '='*70 92 | print 'H: %s' % sum(H) 93 | print 'L: %s' % sum(L) 94 | 95 | 96 | if __name__ == '__main__': 97 | parser = optparse.OptionParser(version=__version__, usage='Usage: %prog [options] [args]', 98 | description=__description__) 99 | parser.add_option('-a', dest='allchars', action='store_true', default=True, help='count all chars') 100 | parser.add_option('-c', dest='case_sensitive', action='store_true', default=True, help='case-sensitivity') 101 | parser.add_option('-n', dest='normalize', action='store_true', default=False, 102 | help='replace national characters to ASCII equivalents') 103 | parser.add_option('-f', dest='file', action='store', default=False, help='text file') 104 | 105 | (options, args) = parser.parse_args() 106 | 107 | print 'Characters Frequency Analysis' 108 | print 'Author: %s' % __author__ 109 | print 'Count all chars: %s' % options.allchars 110 | print 'Case-sensitivity: %s' % options.case_sensitive 111 | print 'Replace national characters to ASCII equivalents: %s' % options.normalize 112 | print 113 | if options.file: 114 | try: 115 | file_stream = codecs.open(options.file, 'r', 'dbcs') 116 | except IOError as e: 117 | print '%s: %s' % (e.strerror, options.file) 118 | else: 119 | print '>>> ' + options.file 120 | text = file_stream.read() 121 | if not options.case_sensitive: 122 | text = text.upper() 123 | _print(count(text, all_chars=options.allchars, normalize=options.normalize)) 124 | file_stream.close() 125 | else: 126 | while 1: 127 | try: 128 | text = raw_input('>>> ').decode(sys.stdin.encoding) 129 | except (SystemExit, KeyboardInterrupt) as e: 130 | sys.exit(0) 131 | else: 132 | if not options.case_sensitive: 133 | text = text.upper() 134 | _print(count(text, all_chars=options.allchars, normalize=options.normalize)) -------------------------------------------------------------------------------- /Polybius.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from unicodedata import normalize 3 | import optparse 4 | import codecs 5 | import sys 6 | import re 7 | 8 | __author__ = 'Lukasz Banasiak ' 9 | __version__ = '1.1' 10 | 11 | 12 | def generate_array(key=''): 13 | 14 | """Create Polybius square with transposition. 15 | 16 | :param key: transposition word 17 | :return: array 18 | """ 19 | alphabet = 'ABCDEFGHIKLMNOPQRSTUVWXYZ' 20 | array = [] 21 | _tmp = [] 22 | key = re.sub(r'[^a-zA-Z]+', '', key) # remove non-alpha character 23 | key = key.upper() 24 | 25 | if key: 26 | for k in key: 27 | alphabet = alphabet.replace(k, '') 28 | 29 | alphabet = key + alphabet 30 | 31 | for y in range(5): 32 | for x in range(5): 33 | _tmp.append(alphabet[0 + 5 * y + x]) 34 | array.append(_tmp) 35 | _tmp = [] 36 | 37 | return array 38 | 39 | 40 | def display_array(array): 41 | 42 | """Display Polybius square. 43 | 44 | """ 45 | row_labels = ['1', '2', '3', '4', '5'] 46 | print ' 1 2 3 4 5' 47 | for row_label, row in zip(row_labels, array): 48 | print ' %s [%s ]' % (row_label, ' '.join('%03s' % i for i in row)) 49 | 50 | 51 | def format_cipher(data): 52 | 53 | """Format cipher. 54 | 55 | Every second number put space, e.g. 112423 => 11 24 23 56 | 57 | :param data: cipher 58 | :return: cipher with spaces 59 | """ 60 | 61 | return " ".join(data[i:i + 2] for i in range(0, len(data), 2)) 62 | 63 | 64 | def encode(words, array): 65 | 66 | """ 67 | Polybius square encryption. 68 | 69 | :param words: string to encrypt 70 | :return: encrypted string 71 | """ 72 | 73 | cipher = '' 74 | 75 | words = normalize('NFKD', words).encode('ascii', 'ignore') # replace national characters to ASCII equivalents 76 | 77 | for word in words.upper(): 78 | for i in range(len(array)): 79 | if word in array[i]: 80 | oy = str(i + 1) 81 | ox = str((array[i].index(word) + 1)) 82 | cipher += oy + ox 83 | 84 | return cipher 85 | 86 | 87 | def decode(numbers, array): 88 | 89 | """ 90 | Polybius square decryption. 91 | 92 | :param numbers: numbers to decrypt 93 | :return: decrypted string 94 | """ 95 | 96 | numbers = re.sub(r'[\D]+', '', numbers) # remove non-digit character 97 | 98 | text = '' 99 | 100 | for number in range(0, len(numbers), 2): 101 | try: 102 | oy = int(numbers[number]) - 1 103 | ox = int(numbers[number + 1]) - 1 104 | text += array[oy][ox] 105 | except IndexError: 106 | pass 107 | continue 108 | 109 | return text 110 | 111 | 112 | if __name__ == '__main__': 113 | parser = optparse.OptionParser(version=__version__, 114 | usage='Usage: %prog [options] [args]', 115 | description='In cryptography the Polybius square is a device for fractionating plaintext characters.') 116 | parser.add_option('-d', dest='decrypt', action='store_true', default=False, 117 | help='tryb deszyfrowania') 118 | parser.add_option('-k', dest='key', action='store', default='', type='string', 119 | help='klucz transformacji szachownicy') 120 | parser.add_option('-f', dest='file', action='store', default=False, 121 | help='wskaz plik z tekstem do (de)szyfrowania') 122 | 123 | (options, args) = parser.parse_args() 124 | 125 | print '' 126 | print 'Szachownica Polibiusza' 127 | print '' 128 | print ' Autor: ' + __author__ 129 | 130 | if options.decrypt: 131 | print ' Tryb: Deszyfrowanie' 132 | else: 133 | print ' Tryb: Szyfrowanie' 134 | 135 | array = generate_array(key=options.key) 136 | 137 | print ' Szachownica:' 138 | display_array(array) 139 | 140 | if options.file: 141 | print '' 142 | print ' IN> ' + options.file 143 | 144 | try: 145 | file_stream = codecs.open(options.file, 'r', 'dbcs') 146 | file_output = codecs.open('_' + options.file, 'w', 'dbcs') 147 | for line in file_stream: 148 | if options.decrypt: 149 | file_output.write(decode(line, array)) 150 | else: 151 | file_output.write(format_cipher(encode(line, array))) 152 | file_stream.close() 153 | file_output.close() 154 | except IOError as e: 155 | print '\nI/O error({0}): {1}'.format(e.errno, e.strerror) 156 | sys.exit(1) 157 | 158 | print 'OUT> ' + '_' + options.file 159 | 160 | else: 161 | while 1: 162 | print '' 163 | try: 164 | text = raw_input(' IN> ').decode(sys.stdin.encoding) 165 | if options.decrypt: 166 | print 'OUT> ' + decode(text, array) 167 | else: 168 | print 'OUT> ' + format_cipher(encode(text, array)) 169 | except (SystemExit, KeyboardInterrupt): 170 | sys.exit(0) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #python-ciphers 2 | Simple ciphers implementation in Python. 3 | 4 | ## AtBash cipher ## 5 | Atbash is a simple substitution cipher for the Hebrew alphabet. 6 | 7 | ### Functions ### 8 | 9 | Different encoding: 10 | 11 | - Diacritical marks conversion to the equivalent characters - if the ciphertext will contain Polish characters, program will convert them to the equivalent 12 | - Based on the Polish alphabet - encryption with 32 characters, other characters ignored 13 | - Based on the English alphabet - encryption using 26 characters, other characters ignored 14 | 15 | Reading and writing ciphertext file. 16 | 17 | ### Examples ### 18 | 19 | Encryption using Polish letters, switch `-l 2` 20 | 21 | IN> gęślą jaźń 22 | OUT> rśęnź ożąk 23 | 24 | Diacritical marks conversion to the equivalent characters (default mode) 25 | 26 | IN> gęślą jaźń 27 | OUT> tvhoz qzam 28 | 29 | IN> gesla jazn 30 | OUT> tvhoz qzam 31 | 32 | Decrypt mode, switch `-d` 33 | 34 | IN> tvhoz qzam 35 | OUT> gesla jaźń 36 | 37 | Load a file to decrypt/encrypt, switch `-f` 38 | 39 | IN> file.txt 40 | OUT> _file.txt 41 | 42 | ##Bacon cipher## 43 | Method of steganography devised by Francis Bacon in 1605. 44 | 45 | ### Functions ### 46 | 47 | 1. Diacritical marks conversion to the equivalent characters - if the ciphertext will contain Polish characters, program will convert them to the equivalent. 48 | 2. Reading and writing ciphertext file. 49 | 50 | ### Examples ### 51 | 52 | Diacritical marks conversion to the equivalent characters (default mode) 53 | 54 | IN> gęślą jaźń 55 | OUT> AABBAAABAABAABAABABBAAAAAABAABAAAAABBAABABBAB 56 | 57 | IN> gesla jazn 58 | OUT> AABBAAABAABAABAABABBAAAAAABAABAAAAABBAABABBAB 59 | 60 | Decrypt mode, switch `-d` 61 | 62 | IN> AABBAAABAABAABAABABBAAAAAABAABAAAAABBAABABBAB 63 | OUT> GESLAJAZN 64 | 65 | Load a file to decrypt/encrypt, switch `-f` 66 | 67 | IN> file.txt 68 | OUT> _file.txt 69 | 70 | ##Bifid (aka Delastelle) cipher## 71 | Bifid cipher is a cipher which combines the Polybius square with transposition, and uses fractionation to achieve diffusion. 72 | 73 | ### Functions ### 74 | 75 | 1. Diacritical marks conversion to the equivalent characters - if the ciphertext will contain Polish characters, program will convert them to the equivalent. 76 | 2. Reading and writing ciphertext file. 77 | 3. Ability to set own transformation key 78 | 4. Ability to set verbose mode showing intermediate states 79 | 80 | ### Examples ### 81 | 82 | Diacritical marks conversion to the equivalent characters (default mode) 83 | 84 | IN> gęślą jaźń 85 | OUT> HOBUCVKY 86 | 87 | IN> gesla jazn 88 | OUT> HOBUCVKY 89 | 90 | Decrypt mode, switch `-d` 91 | 92 | IN> HOBUCVKY 93 | OUT> GESLAJAZN 94 | 95 | Load a file to decrypt/encrypt, switch `-f` 96 | 97 | IN> file.txt 98 | OUT> _file.txt 99 | 100 | Transformation key, switch `-k klucz` 101 | 102 | 1 2 3 4 5 103 | 1 [ K L U C Z ] 104 | 2 [ A B D E F ] 105 | 3 [ G H I M N ] 106 | 4 [ O P Q R S ] 107 | 5 [ T V W X Y ] 108 | 109 | IN> gęślą jaźń 110 | OUT> HOBUCVKY 111 | 112 | Verbose mode, switch `-v` 113 | 114 | IN> gęślą jaźń 115 | 1: 31 24 45 12 21 21 15 35 # after determining coordinates 116 | 2: 32 11 22 41 41 55 13 25 # after horizontal transformation 117 | OUT> HOBUCVKY 118 | 119 | ##Caeser cipher## 120 | In cryptography a Caesar cipher is one of the simplest and most widely known encryption techniques. 121 | 122 | ### Functions ### 123 | 124 | Different encoding: 125 | 126 | - Diacritical marks conversion to the equivalent characters - if the ciphertext will contain Polish characters, program will convert them to the equivalent 127 | - Based on the Polish alphabet - encryption with 32 characters, other characters ignored 128 | - Based on the English alphabet - encryption using 26 characters, other characters ignored 129 | 130 | Reading and writing ciphertext file. 131 | 132 | Set number of shift relative to the first letter of the alphabet. 133 | 134 | ### Examples ### 135 | 136 | Set shift number, switch `-s 13` 137 | 138 | IN> gęślą jaźń 139 | OUT> trfyn wnma 140 | 141 | Diacritical marks conversion to the equivalent characters (default mode) 142 | 143 | IN> gęślą jaźń 144 | OUT> trfyn wnma 145 | 146 | IN> gesla jazn 147 | OUT> trfyn wnma 148 | 149 | Based on the English alphabet, switch `-l 1` 150 | 151 | IN> gęślą jaźń 152 | OUT> tęśyą wnźń 153 | 154 | Decrypt mode, switch `-d` 155 | 156 | IN> trfyn wnma 157 | OUT> GESLAJAZN 158 | 159 | Load a file to decrypt/encrypt, switch `-f` 160 | 161 | IN> file.txt 162 | OUT> _file.txt 163 | 164 | ##Polybius cipher## 165 | In cryptography the Polybius square is a device for fractionating plaintext characters. 166 | 167 | ### Functions ### 168 | 169 | 1. Diacritical marks conversion to the equivalent characters - if the ciphertext will contain Polish characters, program will convert them to the equivalent. 170 | 2. Reading and writing ciphertext file. 171 | 3. Ability to set own transformation key 172 | 4. Representation of the ciphertext does not affect at decryption, e.g. `42aaaa 41 1233 5124 14 32 35 331121ddddsss` is equivalent to `42 41 12 33 51 24 14 32 35 33 11 21` 173 | 174 | ### Examples ### 175 | 176 | Diacritical marks conversion to the equivalent characters (default mode) 177 | 178 | IN> gęślą jaźń 179 | OUT> 31 24 45 12 21 21 15 35 180 | 181 | IN> gesla jazn 182 | OUT> 31 24 45 12 21 21 15 35 183 | 184 | Decrypt mode, switch `-d` 185 | 186 | IN> 31 24 45 12 21 21 15 35 187 | OUT> GESLAJAZN 188 | 189 | Load a file to decrypt/encrypt, switch `-f` 190 | 191 | IN> file.txt 192 | OUT> _file.txt 193 | 194 | Transformation key, switch `-k klucz` 195 | 196 | 1 2 3 4 5 197 | 1 [ K L U C Z ] 198 | 2 [ A B D E F ] 199 | 3 [ G H I M N ] 200 | 4 [ O P Q R S ] 201 | 5 [ T V W X Y ] 202 | 203 | IN> gęślą jaźń 204 | OUT> 31 24 45 12 21 21 15 35 205 | 206 | ##CharFreq## 207 | In cryptanalysis, frequency analysis is the study of the frequency of letters or groups of letters in a ciphertext. 208 | 209 | ### Functions ### 210 | Counting: 211 | 212 | 213 | - All characters or only letters 214 | - Small and big letters. 215 | - Percent of characters in the string 216 | - Replace national characters to ASCII equivalents 217 | - Calculating entropy 218 | - Huffman coding 219 | 220 | ### Usage ### 221 | 222 | --version show program's version number and exit 223 | -h, --help show this help message and exit 224 | -a count all chars 225 | -c case-sensitivity 226 | -n replace national characters to ASCII equivalents 227 | -f FILE text file 228 | 229 | ### Examples ### 230 | 231 | CharFreq.py -f hamlet.txt 232 | Characters Frequency Analysis 233 | Author: Lukasz Banasiak 234 | Count all chars: True 235 | Case-sensitivity: True 236 | Replace national characters to ASCII equivalents: False 237 | 238 | >>> hamlet.txt 239 | Char Count Percent Hi Fi Huffman 240 | ---------------------------------------------------------------------- 241 | 47876 25.565% 1.968 0.511 10 242 | a 9317 4.975% 4.329 0.249 0010 243 | e 14722 7.861% 3.669 0.314 1101 244 | o 10842 5.789% 4.110 0.289 0101 245 | s 8126 4.339% 4.526 0.217 0000 246 | t 11073 5.913% 4.080 0.296 0110 247 | d 4893 2.613% 5.258 0.157 00111 248 | h 7839 4.186% 4.578 0.209 11110 249 | i 7657 4.089% 4.612 0.204 11101 250 | l 5598 2.989% 5.064 0.179 01110 251 | n 8117 4.334% 4.528 0.217 11111 252 | r 7638 4.079% 4.616 0.204 11100 253 | u 4307 2.300% 5.442 0.138 00011 254 | , 3001 1.602% 5.964 0.096 011110 255 | . 3133 1.673% 5.901 0.100 110000 256 | c 2430 1.298% 6.268 0.091 010000 257 | f 2497 1.333% 6.229 0.093 010001 258 | g 2170 1.159% 6.431 0.081 000101 259 | m 4001 2.136% 5.549 0.128 110011 260 | w 2647 1.413% 6.145 0.099 010010 261 | y 3074 1.641% 5.929 0.098 011111 262 | ' 1202 0.642% 7.284 0.051 0011011 263 | b 1568 0.837% 6.900 0.059 1100010 264 | k 1092 0.583% 7.422 0.047 0011000 265 | p 1780 0.950% 6.717 0.067 1100100 266 | v 1189 0.635% 7.299 0.051 0011010 267 | A 633 0.338% 8.209 0.030 01001100 268 | H 892 0.476% 7.714 0.038 11001010 269 | I 854 0.456% 7.777 0.036 11000111 270 | T 790 0.422% 7.889 0.034 01001111 271 | W 485 0.259% 8.593 0.023 00010001 272 | ! 373 0.199% 8.972 0.018 010011100 273 | - 298 0.159% 9.296 0.016 001100110 274 | ; 442 0.236% 8.727 0.021 110001101 275 | ? 452 0.241% 8.695 0.022 110010110 276 | B 262 0.140% 9.481 0.014 001100100 277 | E 238 0.127% 9.620 0.013 000100000 278 | G 250 0.133% 9.549 0.013 000100101 279 | L 249 0.133% 9.555 0.013 000100100 280 | M 252 0.135% 9.537 0.013 000100110 281 | O 376 0.201% 8.960 0.018 010011101 282 | S 253 0.135% 9.532 0.014 000100111 283 | C 176 0.094% 10.055 0.010 0100110100 284 | D 132 0.070% 10.470 0.008 0011001011 285 | F 201 0.107% 9.864 0.011 1100011000 286 | K 180 0.096% 10.023 0.011 0100110110 287 | N 180 0.096% 10.023 0.011 0100110111 288 | P 236 0.126% 9.632 0.013 1100101111 289 | R 139 0.074% 10.396 0.008 0011001110 290 | Y 130 0.069% 10.492 0.008 0011001010 291 | [ 116 0.062% 10.657 0.007 0001000010 292 | x 179 0.096% 10.031 0.011 0100110101 293 | Q 112 0.060% 10.707 0.007 11001011100 294 | ] 112 0.060% 10.707 0.007 11001011101 295 | j 101 0.054% 10.857 0.006 11000110010 296 | q 108 0.058% 10.760 0.006 11000110011 297 | z 72 0.038% 11.345 0.005 00110011110 298 | ( 44 0.023% 12.055 0.003 001100111111 299 | ) 43 0.023% 12.089 0.003 001100111110 300 | : 32 0.017% 12.515 0.002 000100001101 301 | U 36 0.019% 12.345 0.002 000100001111 302 | V 33 0.018% 12.470 0.002 000100001110 303 | J 9 0.005% 14.345 0.001 0001000011000 304 | 1 7 0.004% 14.707 0.001 00010000110011 305 | 0 1 0.001% 17.515 0.000 0001000011001000 306 | 4 1 0.001% 17.515 0.000 0001000011001001 307 | 6 1 0.001% 17.515 0.000 0001000011001010 308 | " 1 0.001% 17.515 0.000 00010000110010110 309 | & 1 0.001% 17.515 0.000 00010000110010111 310 | ---------------------------------------------------------------------- 311 | +: 187271 312 | ====================================================================== 313 | H: 4.3127286523 314 | L: 4.72424988386 315 | -------------------------------------------------------------------------------- /char_freq.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukaszbanasiak/python-ciphers/7ce93e1e950d0ba6bb110d8b12eccb0b62209b3e/char_freq.ico -------------------------------------------------------------------------------- /encryption.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukaszbanasiak/python-ciphers/7ce93e1e950d0ba6bb110d8b12eccb0b62209b3e/encryption.ico -------------------------------------------------------------------------------- /make_exe.bat: -------------------------------------------------------------------------------- 1 | for %%x in (setup_*.py) do python -OO %%x py2exe -------------------------------------------------------------------------------- /setup_atbash.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from distutils.core import setup 3 | import py2exe 4 | import AtBash 5 | 6 | properties = {'script': "AtBash.py", 7 | 'icon_resources': [(0, "encryption.ico")], 8 | 'version': AtBash.__version__, 9 | 'company_name': "labs @ PUT", 10 | 'copyright': "Copyright 2013 Lukasz Banasiak. All rights reserved.", 11 | 'name': "AtBash Cipher demo", 12 | 'description': "Atbash is a simple substitution cipher for the Hebrew alphabet.", 13 | 'author': "Lukasz Banasiak", 14 | 'author_email': "lukasz@banasiak.me", 15 | 'url': "http://banasiak.me", 16 | 'license': "GPL"} 17 | 18 | setup(options={'py2exe': {"compressed": 1, 19 | "optimize": 2, 20 | "bundle_files": 1}}, 21 | 22 | console=[properties], 23 | zipfile=None,) 24 | -------------------------------------------------------------------------------- /setup_bacon.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from distutils.core import setup 3 | import py2exe 4 | import Bacon 5 | 6 | properties = {'script': "Bacon.py", 7 | 'icon_resources': [(0, "encryption.ico")], 8 | 'version': Bacon.__version__, 9 | 'company_name': "labs @ PUT", 10 | 'copyright': "Copyright 2013 Lukasz Banasiak. All rights reserved.", 11 | 'name': "Bacon's cipher demo", 12 | 'description': "Method of steganography devised by Francis Bacon in 1605.", 13 | 'author': "Lukasz Banasiak", 14 | 'author_email': "lukasz@banasiak.me", 15 | 'url': "http://banasiak.me", 16 | 'license': "GPL"} 17 | 18 | setup(options={'py2exe': {"compressed": 1, 19 | "optimize": 2, 20 | "bundle_files": 1}}, 21 | 22 | console=[properties], 23 | zipfile=None,) 24 | -------------------------------------------------------------------------------- /setup_bifid.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from distutils.core import setup 3 | import py2exe 4 | import Bifid 5 | 6 | properties = {'script': "Bifid.py", 7 | 'icon_resources': [(0, "encryption.ico")], 8 | 'version': Bifid.__version__, 9 | 'company_name': "labs @ PUT", 10 | 'copyright': "Copyright 2013 Lukasz Banasiak. All rights reserved.", 11 | 'name': "Bifid cipher demo", 12 | 'description': "Bifid cipher is a cipher which combines the Polybius square with transposition, and uses fractionation to achieve diffusion.", 13 | 'author': "Lukasz Banasiak", 14 | 'author_email': "lukasz@banasiak.me", 15 | 'url': "http://banasiak.me", 16 | 'license': "GPL"} 17 | 18 | setup(options={'py2exe': {"compressed": 1, 19 | "optimize": 2, 20 | "bundle_files": 1}}, 21 | 22 | console=[properties], 23 | zipfile=None,) 24 | -------------------------------------------------------------------------------- /setup_caesar.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from distutils.core import setup 3 | import py2exe 4 | import Caesar 5 | 6 | properties = {'script': "Caesar.py", 7 | 'icon_resources': [(0, "encryption.ico")], 8 | 'version': Caesar.__version__, 9 | 'company_name': "labs @ PUT", 10 | 'copyright': "Copyright 2013 Lukasz Banasiak. All rights reserved.", 11 | 'name': "Caeser Cipher demo", 12 | 'description': "In cryptography a Caesar cipher is one of the simplest and most widely known encryption techniques.", 13 | 'author': "Lukasz Banasiak", 14 | 'author_email': "lukasz@banasiak.me", 15 | 'url': "http://banasiak.me", 16 | 'license': "GPL"} 17 | 18 | setup(options={'py2exe': {"compressed": 1, 19 | "optimize": 2, 20 | "bundle_files": 1}}, 21 | 22 | console=[properties], 23 | zipfile=None,) 24 | -------------------------------------------------------------------------------- /setup_char_freq.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from distutils.core import setup 3 | import py2exe 4 | import CharFreq 5 | 6 | properties = {'script': "CharFreq.py", 7 | 'icon_resources': [(0, "char_freq.ico")], 8 | 'version': CharFreq.__version__, 9 | 'company_name': "labs @ PUT", 10 | 'copyright': "Copyright 2013 Lukasz Banasiak. All rights reserved.", 11 | 'name': "Character frequency analysis demo", 12 | 'description': "In cryptanalysis, frequency analysis is the study of the frequency of letters or groups of letters in a ciphertext.", 13 | 'author': "Lukasz Banasiak", 14 | 'author_email': "lukasz@banasiak.me", 15 | 'url': "http://banasiak.me", 16 | 'license': "GPL"} 17 | 18 | setup(options={'py2exe': {"compressed": 1, 19 | "optimize": 2, 20 | "bundle_files": 1}}, 21 | 22 | console=[properties], 23 | zipfile=None,) 24 | -------------------------------------------------------------------------------- /setup_polybius.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from distutils.core import setup 3 | import py2exe 4 | import Polybius 5 | 6 | properties = {'script': "Polybius.py", 7 | 'icon_resources': [(0, "encryption.ico")], 8 | 'version': Polybius.__version__, 9 | 'company_name': "labs @ PUT", 10 | 'copyright': "Copyright 2013 Lukasz Banasiak. All rights reserved.", 11 | 'name': "Polybius square demo", 12 | 'description': "In cryptography the Polybius square is a device for fractionating plaintext characters.", 13 | 'author': "Lukasz Banasiak", 14 | 'author_email': "lukasz@banasiak.me", 15 | 'url': "http://banasiak.me", 16 | 'license': "GPL"} 17 | 18 | setup(options={'py2exe': {"compressed": 1, 19 | "optimize": 2, 20 | "bundle_files": 1}}, 21 | 22 | console=[properties], 23 | zipfile=None,) 24 | --------------------------------------------------------------------------------