最近在学信息安全技术这门课,老师布置了一个课程作业,作业大概如下:
已知一段仿射密码加密的密文(空格标点等没有加密):
Pu yfo of oin hvy ufa hrpkpyb, jlar ph hopkk py oin hvy oinan, svo jnjpkk klvbi rfan zfyupgnyo zlkr; pu ovayng of ufvyg iph fjy hilgfj, lmmafmaplon nhzlmn, oin hvy jpkk sn oiafvbi oin inlao,jlar nlzi mklzn snipyg oin zfayna; pu ly fvohoanozing mlkr zlyyfo ulkk svoonaukx, oiny zknyzing jlcpyb larh, bpcny mfjna; pu P zly'o ilcn sapbio hrpkn, po jpkk ulzn of oin hvyhipyn, lyg hvyhipyn hrpkn ofbnoina, py uvkk skffr.
试根据所学知识,对其进行破解。
看到题目,当然没有懵啦,因为上课是认真听了滴(呵呵)。马上将老师PPT找出来看,研究了一下午,终于完成了。
破解思路
人们在用英语表示信息时,字母的出现是有规律的。美国密码学家W.F.Friedman在调查了大量英文资料后,得出英文字母的普遍使用规律。
我们可以根据这个规律来破解仿射密码。我们先统计出密文的字母出现频率:
{'a': 18, 'c': 3, 'b': 7, 'g': 8, 'f': 19, 'i': 23, 'h': 17, 'k': 22, 'j': 10, 'm': 7, 'l': 21, 'o': 30, 'n': 37, 'p': 26, 's': 6, 'r': 10, 'u': 11, 'v': 13, 'y': 27, 'x': 1, 'z': 12}
['n', 'o', 'y', 'p', 'i', 'k', 'l', 'f', 'a', 'h', 'v', 'z', 'u', 'r', 'j', 'g', 'm', 'b', 's', 'c', 'x']
由上表可以看到字母n出现次数最多:37次,其次是字母o出现次数30。根据规律呢,字母n是字母e加密后的可能性很大,字母o是字母t加密后的可能性很大,我们根据这个规律算出k1,k2。具体加解密方式看各种百科。(C= Ek(m)=(k1m+k2) mod n)
如果 gcd(k1,26)等于1,那么表示当前假设下,k1,k2是一个合法的密钥。此时,只是可用的密钥。
需要根据k1,k2解出明文,如果刚好明文表示是有意义,那么破解就成功了。
破解过程
其实就是Python代码,因为写起方便
# coding:utf8
# 密文
Cs = r"Pu yfo of oin hvy ufa hrpkpyb, jlar ph hopkk py oin hvy oinan, svo jnjpkk klvbi rfan zfyupgnyo zlkr; pu ovayng of ufvyg iph fjy hilgfj, lmmafmaplon nhzlmn, oin hvy jpkk sn oiafvbi oin inlao,jlar nlzi mklzn snipyg oin zfayna; pu ly fvohoanozing mlkr zlyyfo ulkk svoonaukx, oiny zknyzing jlcpyb larh, bpcny mfjna; pu P zly'o ilcn sapbio hrpkn, po jpkk ulzn of oin hvyhipyn, lyg hvyhipyn hrpkn ofbnoina, py uvkk skffr."
charTable = [ chr(c) for c in range(97,123)]
frequencyTable = [4, 19, 14, 0, 13, 8, 17, 18, 7, 3, 11, 2, 20, 12, 15, 24, 22, 6, 1, 21, 10, 23, 9, 16, 25]
# 删除预留的标点
def del_point(c):
if c in [' ', ',', '.', ';', '\'', '?', '!']:
return False
return True
def get_int_by_char(c):
return charTable.index(c)
def get_char_by_int(i):
return charTable[i]
# 最大公约数
def gcd(a, b):
if a < b:
a, b = b, a
while b != 0:
temp = a % b
a = b
b = temp
return a
# 排序
def sort_by_value(d):
items = d.items()
backitems = [ [v[1],v[0]] for v in items ]
backitems = sorted(backitems, reverse = True)
return [ backitems[i][1] for i in range(0,len(backitems))]
# 获取k3
def get_k3(k1, k2):
for k3 in range(0,26):
if k3 * k1 % 26 == 1:
return k3
# 判断一个数是否是整数
def is_int(n):
int_n = int(n)
return n * n == int_n * int_n
# 仿射解密过程
def FsJM(c, k1, k2):
k3 = get_k3(k1, k2)
Ms = ""
for x in c:
Ms = Ms + get_char_by_int( k3 * (get_int_by_char(x) - k2) % 26 )
return Ms
# 根据a,b,c,d获取密钥K1
def get_k1(a, b, c, d):
i = 0
while True:
k1 = ( float(a - d - 26 * i) / float(b - c) )
if k1 < -26 or k1 > 26:
return None
if is_int(k1):
return int(k1)
i = i + 1
Cs = filter( del_point, Cs.lower() )
count = {}
for v in Cs:
count[v] = count[v] + 1 if count.has_key(v) else 1
sortCs = map(get_int_by_char,sort_by_value(count))
# 精度
prec = 4
result = []
for a in sortCs[0:len(sortCs)/prec]:
for b in frequencyTable[0:len(frequencyTable)/prec]:
for c in frequencyTable[frequencyTable.index(b) + 1:len(frequencyTable)/prec]:
for d in sortCs[sortCs.index(a)+1:len(sortCs)/prec]:
k1 = get_k1(a, b, c, d)
if k1 is None or gcd(k1, 26) != 1:
break
k2 = int(d - c * k1) % 26
result.append( (k1, k2, FsJM(Cs, k1, k2)) )
for val in result:
print val
最后输出:
(7, 11, 'ifnottothesunforsmilingwarmisstillinthesuntherebutwewilllaughmoreconfidentcalmifturnedtofoundhisownshadowappropriateescapethesunwillbethroughtheheartwarmeachplacebehindthecornerifanoutstretchedpalmcannotfallbutterflythenclenchedwavingarmsgivenpowerificanthavebrightsmileitwillfacetothesunshineandsunshinesmiletogetherinfullbloom')
(25, 17, 'cxtmddmdjekwtxmrkachctqigrackkdchhctdjekwtdjerezwdieichhhgwqjamresmtxcletdsghacxdwrteldmxmwtljckmitkjglmigffrmfrcgdeeksgfedjekwtichhzedjrmwqjdjejegrdigraegsjfhgsezejctldjesmrtercxgtmwdkdredsjelfghasgttmdxghhzwdderxhudjetshetsjeligpctqgrakqcpetfmiercxcsgtdjgpezrcqjdkachecdichhxgsedmdjekwtkjctegtlkwtkjctekachedmqedjerctxwhhzhmma')
(3, 1, 'wpzknnknlecyzpkrcowdwzaumrowccnwddwznlecyznlerexynueuwdddmyalokreikzpwteznimdowpnyrzetnkpkyztlwckuzclmtkumvvrkvrwmneecimvenlecyzuwddxenlrkyalnlelemrnumroemilvdmiexelwztnleikrzerwpmzkyncnreniletvmdoimzzknpmddxynnerpdqnlezideziletumjwzamrocawjezvkuerwpwimznlmjexrwalncowdewnuwddpmienknlecyzclwzemztcyzclwzecowdenkaenlerwzpyddxdkko')
(7, 11, 'ifnottothesunforsmilingwarmisstillinthesuntherebutwewilllaughmoreconfidentcalmifturnedtofoundhisownshadowappropriateescapethesunwillbethroughtheheartwarmeachplacebehindthecornerifanoutstretchedpalmcannotfallbutterflythenclenchedwavingarmsgivenpowerificanthavebrightsmileitwillfacetothesunshineandsunshinesmiletogetherinfullbloom')
(9, 4, 'hwideedembjziwdojnhshirpvonhjjehsshiembjziembobqzepbphsssvzrmndobldiwhgbielvsnhwezoibgedwdzigmhjdpijmvgdpvyyodyohvebbjlvybembjziphssqbemodzrmembmbvoepvonbvlmysvlbqbmhigembldoibohwvidzejeobelmbgyvsnlviidewvssqzeebowsfembilsbilmbgpvuhirvonjrhubiydpbohwhlviemvubqohrmejnhsbhephsswvlbedembjzijmhibvigjzijmhibjnhsbedrbembohiwzssqsddn')
(11, 14, 'tkilaalaqhxdikluxftctinjvuftxxatcctiaqhxdiaqhuhydajhjtcccvdnqfluhbliktehiabvcftkaduihealkldieqtxljixqveljvoouloutvahhxbvohaqhxdijtccyhaquldnqaqhqhvuajvufhvbqocvbhyhqtieaqhbluihutkvildaxauhabqheovcfbviilakvccydaahukcpaqhibchibqhejvgtinvufxntghioljhutktbviaqvghyutnqaxftchtajtcckvbhalaqhxdixqtihviexdixqtihxftchalnhaqhutikdccycllf')
(15, 16, 'tcebmmbmwfpjecbsphtktezdrshtppmtkktemwfpjemwfsfojmdfdtkkkrjzwhbsflbectifemlrkhtcmjsefimbcbjeiwtpbdepwribdryysbystrmffplryfmwfpjedtkkofmwsbjzwmwfwfrsmdrshfrlwykrlfofwteimwflbsefstcrebjmpmsfmlwfiyrkhlreebmcrkkojmmfsckxmwfelkfelwfidrgtezrshpztgfeybdfstctlremwrgfostzwmphtkftmdtkkcrlfmbmwfpjepwtefreipjepwtefphtkfmbzfmwfstecjkkokbbh')
(9, 2, 'ncojkkjkshpfocjuptnynoxvbutnppknyynokshpfokshuhwfkvhvnyyybfxstjuhrjocnmhokrbytnckfuohmkjcjfomsnpjvopsbmjvbeeujeunbkhhprbehkshpfovnyywhksujfxskshshbukvbuthbrseybrhwhsnomkshrjuohuncbojfkpkuhkrshmebytrboojkcbyywfkkhucylkshoryhorshmvbanoxbutpxnahoejvhuncnrboksbahwunxskptnyhnkvnyycbrhkjkshpfopsnohbompfopsnohptnyhkjxhkshunocfyywyjjt')
(3, 3, 'exhsvvsvtmkghxszkwelehicuzwekkvellehvtmkghvtmzmfgvcmcelllugitwszmqshxebmhvqulwexvgzhmbvsxsghbtekschktubscuddzsdzeuvmmkqudmvtmkghcellfmvtzsgitvtmtmuzvcuzwmuqtdluqmfmtehbvtmqszhmzexuhsgvkvzmvqtmbdulwquhhsvxullfgvvmzxlyvtmhqlmhqtmbcurehiuzwkiermhdscmzexequhvturmfzeitvkwelmevcellxuqmvsvtmkghktehmuhbkghktehmkwelmvsimvtmzehxgllflssw')
(5, 21, 'eflcjjcjnosalfcbsuedelwiybuessjeddeljnosaljnobopajioiedddyawnucbogclfexoljgyduefjabloxjcfcalxnescilsnyxciyttbctbeyjoosgytojnosalieddpojnbcawnjnonoybjiybuoygntdygoponelxjnogcblobefylcajsjbojgnoxtydugyllcjfyddpajjobfdqjnolgdolgnoxiyrelwybusweroltciobefegyljnyropbewnjsuedoejieddfygojcjnosalsneloylxsalsnelosuedojcwojnobelfaddpdccu')
(7, 21, 'oltuzzuznkyatluxysorotmcgxsoyyzorrotznkyatznkxkhazckcorrrgamnsuxkiutlojktzigrsolzaxtkjzuluatjnoyuctyngjucgvvxuvxogzkkyigvkznkyatcorrhkznxuamnznknkgxzcgxskginvrgikhknotjznkiuxtkxolgtuazyzxkzinkjvgrsigttuzlgrrhazzkxlreznktirktinkjcgbotmgxsymobktvuckxoloigtzngbkhxomnzysorkozcorrlgikzuznkyatynotkgtjyatynotkysorkzumkznkxotlarrhruus')
可以看到:
(7, 11, 'ifnottothesunforsmilingwarmisstillinthesuntherebutwewilllaughmoreconfidentcalmifturnedtofoundhisownshadowappropriateescapethesunwillbethroughtheheartwarmeachplacebehindthecornerifanoutstretchedpalmcannotfallbutterflythenclenchedwavingarmsgivenpowerificanthavebrightsmileitwillfacetothesunshineandsunshinesmiletogetherinfullbloom')
这段字符有意义,所以应该是原文。
翻译原文
翻译过来就是(网上找的):
如果不向太阳索取微笑,温暖仍在太阳那里,但我们会笑得更加自信从容;如果转过身去发现了自己的影子,适当的躲让,阳光便可穿越心灵,温暖每一处身后的角落;如果摊开的掌心不能点落蝴蝶,那就紧握成拳挥动臂膀,给予力量;如果我不能够微笑得灿烂,那就将脸投向灿烂的阳光,与阳光一起微笑,烂漫.
还是一段温暖的句子呢!