1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
| from pycipher import Affine import string
table = string.ascii_lowercase
englishExpectedFrequencies = { 'a': 0.08167, 'b': 0.01492, 'c': 0.02782, 'd': 0.04253, 'e': 0.12702, 'f': 0.02228, 'g': 0.02015, 'h': 0.06094, 'i': 0.06966, 'j': 0.00153, 'k': 0.00772, 'l': 0.04025, 'm': 0.02406, 'n': 0.06749, 'o': 0.07507, 'p': 0.01929, 'q': 0.00095, 'r': 0.05987, 's': 0.06327, 't': 0.09056, 'u': 0.02758, 'v': 0.00978, 'w': 0.02361, 'x': 0.00150, 'y': 0.01974, 'z': 0.00074 }
dic = {1: 1, 3: 9, 5: 21, 7: 15, 9: 3, 11: 19, 15: 7, 17: 23, 19: 11, 21: 5, 23: 17, 25: 25}
def decryptFirstStage(toDecrypt): min_len = 3 max_len = 15 toDecrypt = toDecrypt.lower()
best_len = 0 best_aver = 0
best_rate = 0.65 min_rate = 100
for i in range(0, len(toDecrypt)): lengthOfKey = i + 1 averageIC = 0.0 sequenceDictionary = {} hadZeroError = False
for index in range(0, len(toDecrypt)): sequenceNumber = index % lengthOfKey if sequenceNumber in sequenceDictionary: sequenceDictionary[sequenceNumber] += toDecrypt[index] else: sequenceDictionary[sequenceNumber] = toDecrypt[index]
for stringSequence in sequenceDictionary.values(): try: averageIC += calculateIC(stringSequence) except ZeroDivisionError: hadZeroError = True break
if hadZeroError == True: averageIC = 0 else: averageIC /= len(sequenceDictionary.keys())
rate = abs(1 - (averageIC / best_rate))
if (min_len <= lengthOfKey <= max_len) and (rate < min_rate): min_rate = rate best_len = lengthOfKey\
return best_len
def calculateIC(inputText): inputText = "".join(inputText.lower().split()) frequency = getFrequencyOfText(inputText) ic = 0.0
for letter in table: if letter in frequency: ic += frequency[letter] * (frequency[letter] - 1)
ic /= len(inputText) * (len(inputText) - 1) return ic
def getFrequencyOfText(inputText): frequency = {} for letter in inputText: if letter in frequency: frequency[letter] += 1 else: frequency[letter] = 1 return frequency
def getGroups(raw, block): groups = [] for i in range(block): k = i part = "" while True: try: part += raw[k] k += block except: break groups.append(part) return groups
def getEnglishScore(inputText): """计算英文字符串的“评分”,计算方法为: Score = (字符串中各个字母的数量 * 其对应的字母频率)的总和 / 字符串去掉空格后的长度
:param inputText: 英文字符串 string :return: 评分 int """ inputText = inputText.lower().replace(" ", "") score = sum([englishExpectedFrequencies.get(char, 0) for char in inputText]) / len(inputText)
return score
def crack(cipher): fitness = float("-inf") bestResult = "" key_a = None key_b = None for i in dic.keys(): for j in range(0, 26): af = Affine(a=i, b=j) result = af.decipher(cipher) bestFitness = getEnglishScore(result) if bestFitness > fitness: key_a = i key_b = j fitness = bestFitness bestResult = result
return bestResult, key_a, key_b
en = "ltpflwfkqnyfmbjbchqnadkaykyhgpzaezjfrfkdonetcvcrkaaronhdnvghmyzwshrhefgqjfbrphqmgvglgvlfonzzqngxqfsessrhphupnvlfxsxotmzccnqfvmfdlhujqvezonbhsnsgykffzmbhefxtrrfjqsxywnolschammigsuetynevesboxmolrirbzhnhtynalodsgnyhxahlrifjqyijphgaqrlrclrhpattjcegcviubmztdvysstskrqelgfzjmjqhjmnmqkhcumftngxltgebfossacnvscaosixddmzcuqdyxciqaugqzoatgxnhmvczlrrfezzhlqalpogfejetmqfthtojfxeuxmqmushcbwsqtmdfdovtulzhlqccnobdshiqascgqxuyjwegbqdfrogrrgxhwfqpqqayooeoxanrunprzsigmatptaxjfavmaaqazoirructbmffenahsjxyahuajtomfsfnavgbcvsysxsjqkggjvlfreqoxaqlwflfzmipxyqiqaxfgoskauczogsdbaurejccjfoxgnknehlpnkyyjauowhymqfsceosbrydlkofyesrdzakazkbrzcxyastfsnymcarhjmtvgvbtrueoxmlljvhfljqgcmqtcrzjjscrahdtgfozonxvrigqunlrcrilnngvkfsmzwroxmlljvhfljqgcmhlgczvztenqnmpcvocuafoxmqpkkfclpsgafetgcfoezqoajpveuegywqoajitraltjssjedczjvessyevjmsycykypjijensqocbfftehhgltcqocpjijepscsfogjwhvncnbemzospqolhgedcfzsyijwnaoubzjymfnaynpnqogepzdlvgcooftfwsksytpdymjoxcdnnugwysrvhnhtynalodsgnyhlvsacyspwweuxanvusssseetnyfncvkvetsozqtbetyysixyagcgkoky" length = decryptFirstStage(en) print "Length is: %d" % length gp = getGroups(en, length) key1 = "" key2 = "" for p in gp: res, a, b = crack(p) key1 += table[a] key2 += table[b] print key1 + '\n' + key2
|