# 维吉尼亚密码加解密过程 import string from itertools import cycle # 代码写在这里 defencrypt(message, key): tmp_text = '' keylen = len(key) tmp_key = key.upper() i = 0 for c in message: ifnot c.isalpha(): tmp_text += c else: if c.isupper(): a = 'A' else: a = 'a' tmp_text += chr(ord(a)+((ord(c)-ord(a)) + (ord(tmp_key[i])-ord('A')))% 26) i += 1 if i == keylen: i = 0 return tmp_text
defdecrypt(message, key): tmp_text = '' keylen = len(key) tmp_key = key.upper() i = 0 for c in message: ifnot c.isalpha(): tmp_text += c else: if c.isupper(): a = 'A' else: a = 'a' tmp_text += chr(ord(a)+((ord(c)-ord(a)) - (ord(tmp_key[i])-ord('A')))% 26) i += 1 if i == keylen: i = 0 return tmp_text
# 测试 defmain(): message = 'Common sense is not so common.' key = 'PIZZA'
deffind_repeat_sequences_spacings(message): """ 参数:message,是一个字符串 功能:遍历message,找到3到5个字母长度的重复序列 返回值:一个字典,键是序列,值是序列间隔列表(重复序列之间间隔的字母数) """ # 代码如下 # 预处理字符串 tmp_text = pre_treatment(message) # 生成重复序列间隔字典 dic = dict() # 查找3-5位字母长度的重复序列 for strlen inrange(3,6): for i inrange(0,len(tmp_text)-2*strlen+1): tmp_str = tmp_text[i:i+strlen] tmp_count = tmp_text.count(tmp_str) if tmp_count > 1: if tmp_str notin dic.keys(): last = tmp_text.find(tmp_str) find_list = [last] for j inrange(1,tmp_count): now = tmp_text.find(tmp_str,last+strlen) find_list.append(now) last = now spacing_list = [] listlen = len(find_list) for j inrange(0,listlen-1): for k inrange(j+1,listlen): spacing_list.append(find_list[k]-find_list[j]) dic[tmp_str] = spacing_list
return(dic)
1 2 3
# 测试 ciphertext = "Ppqca xqvekg ybnkmazu ybngbal jon i tszm jyim. Vrag voht vrau c tksg. Ddwuo xitlazu vavv raz c vkb qp iwpou." print(find_repeat_sequences_spacings(ciphertext))
1
{'YBN': [8], 'AZU': [48], 'VRA': [8, 32, 24]}
找到间隔之间的因数
8的因数是2,4,8
24的因数是2,3,4,6,8,12,24
32的因数是2,4,8,16,32
48的因数是2,3,4,6,8,12,16,24,48
次数出现最多的几个因数极有可能就是密钥字符串的长度,即2,4,8,3,6,12
1 2 3 4 5 6 7 8 9 10 11 12
defget_useful_factors(num): """返回num的因子列表""" factors_list = [] for i inrange(2,math.isqrt(num)+1): if num % i == 0: factors_list.append(i) j = num//i if i != j: factors_list.append(j) factors_list.sort()
return(factors_list)
1 2
# 测试 print(get_useful_factors(24))
1
[2, 3, 4, 6, 8, 12]
编程计算每个因子出现的次数,按照出现次数从大到小排序,得到一个因子列表,这些因子就是可能的密钥长度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# 编程找到可能的密钥长度 defget_possible_keylen(message): tmp_dic = find_repeat_sequences_spacings(message) dic_fac = dict() for i in tmp_dic: for j in tmp_dic[i]: tmp_fac = get_useful_factors(j) for k in tmp_fac: if k notin dic_fac: dic_fac[k] = 1 else: dic_fac[k] += 1 list_fac = [] for i insorted(dic_fac.items(), key=lambda x:(-x[1],x[0])): # print(i) list_fac.append(i[0])
return(list_fac)
1 2 3
# 测试 ciphertext = 'Ppqca xqvekg ybnkmazu ybngbal jon i tszm jyim. Vrag voht vrau c tksg. Ddwuo xitlazu vavv raz c vkb qp iwpou.' print(get_possible_keylen(ciphertext))
defget_nth_subkeys_letters(n,key_length,message): """将message按照key_length长度分组,每个分组中第n个字母拿出来 getNthSubkeysLetters(1, 3, 'ABCABCABC') returns 'AAA' getNthSubkeysLetters(2, 3, 'ABCABCABC') returns 'BBB' getNthSubkeysLetters(3, 3, 'ABCABCABC') returns 'CCC' getNthSubkeysLetters(1, 5, 'ABCDEFGHI') returns 'AF' """ # 预处理字符串 tmp_text = pre_treatment(message) tmp_str = '' i = 0 for c in tmp_text: if i % key_length == n-1: tmp_str += c i += 1
return(tmp_str)
1 2 3 4
# 测试 ciphertext = "Ppqca xqvekg ybnkmazu ybngbal jon i tszm jyim. Vrag voht vrau ctksg. Ddwuo xitlazu vavv raz c vkb qp iwpou." for i inrange(1,5): print(get_nth_subkeys_letters(i,4,ciphertext))
一段密文如下:“I rc ascwuiluhnviwuetnh,osgaa ice tipeeeee slnatsfietgi tittynecenisl. e fo f fnc isltn sn o a yrs sd onisli ,l erglei trhfmwfrogotn,l stcofiit.aea wesn,lnc ee w,l eIh eeehoer ros iol er snh nl oahsts ilasvih tvfeh rtira id thatnie.im ei-dlmf i thszonsisehroe, aiehcdsanahiec gv gyedsB affcahiecesd d lee onsdihsoc nin cethiTitx eRneahgin r e teom fbiotd n ntacscwevhtdhnhpiwru”
# 英语字母频率 deffreq_match_score(message): """ 将message中字符按照频数从高到低排序, 然后查看出现频数最高的前6个字符和出现频数最低的后6个字符 是否与英语字母频数表(ETAOIN)中的字符相匹配。 若匹配,match_score加1 """ ETAOIN = 'ETAOINSHRDLCUMWFGYPBVKJXQZ' match_score = 0 tmp_text = pre_treatment(message) # 初始化计数字典并计数 # base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' # 上面这行注释绝妙,无意间解决了ETAOIN排序问题 dic_letter_freq = dict() for c in ETAOIN: dic_letter_freq[c] = 0 for c in tmp_text: dic_letter_freq[c] += 1 # 生成频数字母列表字典 dic_freq_letter = dict() for i in dic_letter_freq.items(): if i[1] notin dic_freq_letter.keys(): dic_freq_letter[i[1]] = [i[0]] else: dic_freq_letter[i[1]].append(i[0]) # 频数字典排序生成匹配串 freq_string = '' for f insorted(dic_freq_letter.items(),key=lambda x:(-x[0])): for c in f[1]: freq_string += c # 累计频率匹配分数 for c in freq_string[:6]: if c in ETAOIN[:6]: match_score += 1 for c in freq_string[-6:]: if c in ETAOIN[-6:]: match_score += 1
return(match_score)
1 2 3
# 测试示例中的密文 message = "I rc ascwuiluhnviwuetnh,osgaa ice tipeeeee slnatsfietgi tittynecenisl. e fo f fnc isltn sn o a yrs sd onisli ,l erglei trhfmwfrogotn,l stcofiit.aea wesn,lnc ee w,l eIh eeehoer ros iol er snh nl oahsts ilasvih tvfeh rtira id thatnie.im ei-dlmf i thszonsisehroe, aiehcdsanahiec gv gyedsB affcahiecesd d lee onsdihsoc nin cethiTitx eRneahgin r e teom fbiotd n ntacscwevhtdhnhpiwru" print(freq_match_score(message))
Adiz Avtzqeci Tmzubb wsa m Pmilqev halpqavtakuoi, lgouqdaf, kdmktsvmztsl, izr xoexghzr kkusitaaf. Vz wsa twbhdg ubalmmzhdad qz hce vmhsgohuqbo ox kaakulmd gxiwvos, krgdurdny i rcmmstugvtawz ca tzm ocicwxfg jf "stscmilpy" oid "uwydptsbuci" wabt hce Lcdwig eiovdnw. Bgfdny qe kddwtk qjnkqpsmev ba pz tzm roohwz at xoexghzr kkusicw izr vrlqrwxist uboedtuuznum. Pimifo Icmlv Emf DI, Lcdwig owdyzd xwd hce Ywhsmnemzh Xovm mby Cqxtsm Supacg (GUKE) oo Bdmfqclwg Bomk, Tzuhvif'a ocyetzqofifo ositjm. Rcm a lqys ce oie vzav wr Vpt 8, lpq gzclqab mekxabnittq tjr Ymdavn fihog cjgbhvnstkgds. Zm psqikmp o iuejqf jf lmoviiicqg aoj jdsvkavs Uzreiz qdpzmdg, dnutgrdny bts helpar jf lpq pjmtm, mb zlwkffjmwktoiiuix avczqzs ohsb ocplv nuby swbfwigk naf ohw Mzwbms umqcifm. Mtoej bts raj pq kjrcmp oo tzm Zooigvmz Khqauqvl Dincmalwdm, rhwzq vz cjmmhzd gvq ca tzm rwmsl lqgdgfa rcm a kbafzd-hzaumae kaakulmd, hce SKQ. Wi 1948 Tmzubb jgqzsy Msf Zsrmsv'e Qjmhcfwig Dincmalwdm vt Eizqcekbqf Pnadqfnilg, ivzrw pq onsaafsy if bts yenmxckmwvf ca tzm Yoiczmehzr uwydptwze oid tmoohe avfsmekbqr dn eifvzmsbuqvl tqazjgq. Pq kmolm m dvpwz ab ohw ktshiuix pvsaa at hojxtcbefmewn, afl bfzdakfsy okkuzgalqzu xhwuuqvl jmmqoigve gpcz ie hce Tmxcpsgd-Lvvbgbubnkq zqoxtawz, kciup isme xqdgo otaqfqev qz hce 1960k. Bgfdny'a tchokmjivlabk fzsmtfsy if i ofdmavmz krgaqqptawz wi 1952, wzmz vjmgaqlpad iohn wwzq goidt uzgeyix wi tzm Gbdtwl Wwigvwy. Vz aukqdoev bdsvtemzh rilp rshadm tcmmgvqg (xhwuuqvl uiehmalqab) vs sv mzoejvmhdvw ba dmikwz. Hpravs rdev qz 1954, xpsl whsm tow iszkk jqtjrw pug 42id tqdhcdsg, rfjm ugmbddw xawnofqzu. Vn avcizsl lqhzreqzsy tzif vds vmmhc wsa eidcalq; vds ewfvzr svp gjmw wfvzrk jqzdenmp vds vmmhc wsa mqxivmzhvl. Gv 10 Esktwunsm 2009, fgtxcrifo mb Dnlmdbzt uiydviyv, Nfdtaat Dmiem Ywiikbqf Bojlab Wrgez avdw iz cafakuog pmjxwx ahwxcby gv nscadn at ohw Jdwoikp scqejvysit xwd "hce sxboglavs kvy zm ion tjmmhzd." Sa at Haq 2012 i bfdvsbq azmtmd'g widt ion bwnafz tzm Tcpsw wr Zjrva ivdcz eaigd yzmbo Tmzubb a kbmhptgzk dvrvwz wa efiohzd. keylen = 3 0 1 ('A', 5.125612431444254) 0 2 ('M', 5.112906764168203) 0 3 ('Z', 4.292806215722134) 1 1 ('O', 5.333315018315032) 1 2 ('S', 5.273826007326018) 1 3 ('D', 4.486067765567781) 2 1 ('I', 5.830117216117233) 2 2 ('V', 5.392289377289392) 2 3 ('E', 4.267117216117228) {0: 'AMZ', 1: 'OSD', 2: 'IVE'} keylen = 2 0 1 ('I', 4.810197560975626) 0 2 ('O', 4.562274390243913) 0 3 ('A', 4.415186585365871) 1 1 ('M', 4.557256410256414) 1 2 ('V', 4.542681318681341) 1 3 ('I', 4.338537240537258) {0: 'IOA', 1: 'MVI'} keylen = 6 0 1 ('A', 6.367591240875909) 0 2 ('P', 5.041430656934308) 0 3 ('E', 4.885160583941612) 1 1 ('S', 6.245344322344322) 1 2 ('H', 4.7055934065934135) 1 3 ('W', 4.369351648351649) 2 1 ('I', 6.8673223443223455) 2 2 ('T', 4.873608058608065) 2 3 ('E', 4.650586080586077) 3 1 ('M', 6.306934065934067) 3 2 ('Z', 4.561073260073258) 3 3 ('Q', 4.492465201465203) 4 1 ('O', 6.575586080586089) 4 2 ('D', 4.607542124542126) 4 3 ('Z', 4.570794871794874) 5 1 ('V', 6.368021978021977) 5 2 ('I', 4.7929120879120966) 5 3 ('Z', 4.592890109890112) {0: 'APE', 1: 'SHW', 2: 'ITE', 3: 'MZQ', 4: 'ODZ', 5: 'VIZ'} Alan Mathison Turing was a British mathematician, logician, cryptanalyst, and computer scientist. He was highly influential in the development of computer science, providing a formalisation of the concepts of "algorithm" and "computation" with the Turing machine. Turing is widely considered to be the father of computer science and artificial intelligence. During World War II, Turing worked for the Government Code and Cypher School (GCCS) at Bletchley Park, Britain's codebreaking centre. For a time he was head of Hut 8, the section responsible for German naval cryptanalysis. He devised a number of techniques for breaking German ciphers, including the method of the bombe, an electromechanical machine that could find settings for the Enigma machine. After the war he worked at the National Physical Laboratory, where he created one of the first designs for a stored-program computer, the ACE. In 1948 Turing joined Max Newman's Computing Laboratory at Manchester University, where he assisted in the development of the Manchester computers and became interested in mathematical biology. He wrote a paper on the chemical basis of morphogenesis, and predicted oscillating chemical reactions such as the Belousov-Zhabotinsky reaction, which were first observed in the 1960s. Turing's homosexuality resulted in a criminal prosecution in 1952, when homosexual acts were still illegal in the United Kingdom. He accepted treatment with female hormones (chemical castration) as an alternative to prison. Turing died in 1954, just over two weeks before his 42nd birthday, from cyanide poisoning. An inquest determined that his death was suicide; his mother and some others believed his death was accidental. On 10 September 2009, following an Internet campaign, British Prime Minister Gordon Brown made an official public apology on behalf of the British government for "the appalling way he was treated." As of May 2012 a private member's bill was before the House of Lords which would grant Turing a statutory pardon if enacted. key = ASIMOV