Python 仿射密码破解

最近在学信息安全技术这门课,老师布置了一个课程作业,作业大概如下:


已知一段仿射密码加密的密文(空格标点等没有加密):

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')

这段字符有意义,所以应该是原文。

翻译原文

翻译过来就是(网上找的):

如果不向太阳索取微笑,温暖仍在太阳那里,但我们会笑得更加自信从容;如果转过身去发现了自己的影子,适当的躲让,阳光便可穿越心灵,温暖每一处身后的角落;如果摊开的掌心不能点落蝴蝶,那就紧握成拳挥动臂膀,给予力量;如果我不能够微笑得灿烂,那就将脸投向灿烂的阳光,与阳光一起微笑,烂漫.

还是一段温暖的句子呢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容

  • CTF中那些脑洞大开的编码和加密 0x00 前言 正文开始之前先闲扯几句吧,玩CTF的小伙伴也许会遇到类似这样的问...
    查无此人asdasd阅读 5,767评论 0 19
  • 0x01 目录 常见编码: ASCII编码 Base64/32/16编码 shellcode编码 Quoted-p...
    H0f_9阅读 12,221评论 2 17
  • 我有个爸爸,他有个外号叫小"盘古",为什么起这个名字呢?因为它像盘古开天辟地一样,建成了我们的家,又像盘古顶天立地...
    可爱小怪物阅读 224评论 0 1
  • 我朋友小薇最近处于神秘状态,周末约她喝茶,她都是各种推脱。大家颇有微词,于是我受命去问个究竟。 小薇只是默默的坐着...
    若愚123阅读 1,290评论 0 2
  • 走廊似暗黑的涵洞 我听到锁扣的机关挣脱固缝 你拔出钥匙 昏暗的灯下映衬出久远的面孔 我久远不见,这久远的面孔 温暖...
    幻夕风阅读 368评论 2 4