index koincidence pro kratke zpravy
[krypto.git] / krypto.py
1 #!/usr/bin/env python
2
3 """CL rozhrani pro sadu kryptoanalytickych nastroju."""
4
5 import sys
6 import pickle
7 import argparse
8
9 from ocesavac import ocesat
10 import jakobsen
11 from jakobsen import reference
12 import koincidence
13 import posuny
14 from spolecne import ABECEDA
15 import vigenere
16
17 def analyza(zprava, opsny):
18     analyza = []
19
20     # Prepinani spacemodu
21     mod_m = False
22     mod_x = False
23     if 'X' in opsny:
24         mod_x = True
25     if 'M' in opsny:
26         mod_m = True
27     if 'A' in opsny:
28         mod_x = True
29         mod_m = True
30     if not mod_m and not mod_x:
31         if ' ' in ocesat(zprava, True)[1:-1]:
32             mod_m = True
33             analyza.append("Automaticky zvolena analyza s mezerami.")
34         else:
35             mod_x = True
36             analyza.append("Automaticky zvolena analyza bez mezer.")
37         
38     # Zakladni udaje
39     analyza.append("\nZakladni udaje:")
40     if mod_m:
41         analyza.append("Delka zpravy (vcetne mezer a zvlastnich znaku: " +
42             str(len(zprava)))
43     analyza.append("Delka zpravy (bez mezer a zvlastnich znaku): " +
44         str(len(ocesat(zprava, False))))
45
46     # Prumerna delka slova
47     if mod_m:
48         analyza.append("\nPrumerna delka slova:")
49         slova = ocesat(zprava, True).split()
50         analyza.append('{0:.3}'.format(float(sum([len(word) for word in slova]))/len(slova)))
51
52     # Frekvence znaku 
53     analyza.append("\nFrekvencni analyza:")
54     freq = dict()
55     for char in ABECEDA:
56         freq[char] = 0
57     for char in zprava:
58         if char in freq:
59             freq[char] += 1
60     celkem = sum(freq.values())
61     for char in sorted(freq, key=freq.get, reverse=True):
62         analyza.append('{0} {1:>3} {2:>6.2%}'.format(char, freq[char],
63                        float(freq[char])/celkem))
64
65     # Index koincidence
66     if mod_m:
67         analyza.append("\nIndex koincidence (s mezerami):")
68         analyza.append('{0:.2%}'.format(
69                        koincidence.index_koincidence(zprava, True)))
70     if mod_x:
71         #TODO tady by se spravne mela porovnavat delka ocesane zpravy
72         analyza.append("\nIndexy koincidence (bez mezer):")
73         analyza.append(koincidence.tabulka_indexu(zprava))
74
75
76     # Vigenere
77     if 'V' in opsny:
78         analyza.append("\nHeslo k Vigenerovi (" + opsny[-1] + "):")
79         vig_heslo, vig_text = vigenere.vsechno(zprava, int(opsny[-1]))
80         analyza.append(vig_heslo)
81         analyza.append(vig_text)
82
83     # Jakobsen
84     if mod_m:
85         analyza.append("\nJakobsen (s mezerami):")
86         analyza.append(jakobsen.desifruj(zprava))
87     if mod_x:
88         analyza.append("\nJakobsen (bez mezer):")
89         analyza.append(jakobsen.desifruj(zprava, False))
90
91     # Posuny v abecede
92     (posun, posunuty_text) = posuny.nejlepsi(zprava)
93     if 'P' in opsny or 'A' in opsny:
94         analyza.append("\nPosuny v abecede (nejlepsi posun {0}):".format(posun))
95         analyza.append("\n".join("{0:>2} {1}".format(
96                        i + 1, posuny.vsechny(zprava)[i]) for i in range(26)))
97     else:
98         analyza.append("\nNejlepsi posun ({0}):".format(posun))
99         analyza.append(posunuty_text)
100
101     # Bigramy
102     if 'B' in opsny or 'A' in opsny:
103         analyza.append("\nBigramy podle cetnosti:")
104         bigramy = dict()
105         for i in ABECEDA:
106             for j in ABECEDA:
107                 bigramy[i+j] = 0
108         for i in range(0, len(zprava)-1):
109             if zprava[i:i+2] in bigramy:
110                 bigramy[zprava[i:i+2]] += 1
111         celkem = sum(bigramy.values())
112         for char in sorted(bigramy, key=bigramy.get, reverse=True):
113             if bigramy[char] == 0:
114                 break
115             analyza.append('{0} {1:>3} {2:>6.2%}'.format(char, bigramy[char],
116                            float(bigramy[char])/celkem))
117     return '\n'.join(analyza)
118
119 if __name__ == '__main__':
120     if len(sys.argv) > 1:
121         opsny = sys.argv[1]
122     else:
123         opsny = ''
124
125     telo = sys.stdin.read()
126     zprava = telo.strip().upper()
127     print(analyza(zprava, opsny))
128