维吉尼亚密码-CTFwp2


something:要考试了,原谅窝再水一个wp(! - !)

一、维吉尼亚密码简介

注:在同学那里搜罗来了一个维吉尼亚密码的解密网站,不过我还没用过,SL姐姐布置的作业,全靠python水过去了。
维吉尼亚密码是古典密码的一种,从凯撒密码演变而来,用多个凯撒密码组成,是多表密码的简单实现。简单说,就是按照这张表来实现:

Alt
差不多就是,原文abc,如果秘钥是xyz,那么加密后得到的是 xzb。如果不了解凯撒的话,百度一下,很好理解的。

二、题目:

数据如下
faprepeapmsstwmcxdfwfaprepeapmsstwmcxdfwfaprepeapmsstwmcxdfwfaprepeapmsstwmcxdfwfaprepeapmsstwmcxdfwdteprdxcrsnlwtghealcegnzyahzeleutgircdgebpawxhpidtogidiqjxaqecixektglhispdwanhavokxoisiwpylixxetthzgctgpbptgtinrttwucrzrtgdwpaqapxodqtkogyfwthxxtlnheypxseleqpwpaahzlahxewfpcdpiztprgapyhsspgmdqtnohpbmythdqeriwpcsttxxowpgibttysuicfqbtgphbnrcmtxrdedxslwspndxhtqlplheweswtoaiiwrslsrzpogxykihffmtthtqpaneleqtdxagdfrdetcgecixsrtpngugpeitwpyxhtqlpljhphaiucenrtelaczdxobtemcjazysitdxicvmcsrxprtxhewicvpvmpcjxhtizrgjteaihitrgcpeyrtdqmthrzrttcewcdcqmrbhelaiisiwdgwhcjemelawlwcdbpeldcraanucsmiwppepisirpcopartdzagxpxyiwlxwphnsmbdyesgtniniajesiwpwtwtqivtgysvphdicgteedxslwspndmsxidvasxnelantqpgdgidhnyxaritgfdpxensjymqjtvriiiphrphnleaulfrxrrmvtcelaiismsxhdypeddididxektisibpawjahipvacsavokxoitwtqvetztgkhepgipatwthatoeqtnohpbhmtwbzveedhirxixeycdefehjctrxhtrgiwlxgdpwoetepvsaxvibjuqsnpgpynwpatyhelmnvdlpkttairetovordyxrtglwspxoxhtqlmlprewsiglrgtajahxaphacxdlkttairiwzqahhzvechprasbtxttsrpodbtpyiwlxiilzylsecsbpqwcrthfptxcxsrthaicipnylpgrsaahlwavdlpkttairndflakteslxkpaiiweleupnxtwpexhtbloeghnvepipfaaadjogisibtcpjiidqwtgxvirhwpwaxsmifdgppepktrgrdainwprinudcwojisoogtlfuidfxfxtwhpapjirhwlzepadswtxrlesxyaiiwnviixnmsbblryhpjmnvisibpawmsidzpivweensisirtuzvewpchtdrzrtgdwmthqtkacstxsidzpivwenaepywjxytrelhlkecrjuudiphbgpkmlxpyjogllvdtstpsdclwspntrgtpcpitgelihbzrtwlsmltheviztcvikpwhohpthiihzertsesoupcahtcvmcztonojgyelxhewaiisimpxytrthdgeciciicnzoowpxehpkpfetcrmvtcelerwlrctizxrndfxtwtqivtgysvpucsmiwptecpwxyhezxwxisxhtptqouwtxtxcrwptrtelipckeihtrtwtrsaahzjagupahpkpfetclfltizwcdgpqogtelacutzedjesfityeliwzygwismsbpjlaktwmtiapxosdhmtwisiqjpwmtndqxhtqlplejedasbtxsiwlxtwtmelaxdsniwppivwewistzjfxulwtdvcemlttkhigpuuxgpqecimythpjwiixdroqxrkegisenegpzidjdfaaadxhtrzrtgdgirhnzzegisibpawelhdsespczjfexeghsxxinhxzricsfwtgntrsxspvshpjmtbpjfecdnsicrthecrpxhpiapantcwfgdxfrpotpsedywogtofypsthahgtzaactoewpgibttyemdcrxhtqlplhbzwtkdnmftgzysrgtxirhelehpximxvsxgduzvtwtavaxhphihwphojiqsriwpfaaamcbtrvlabdyiouisimpxytlpnpvsjhphtdecsmdipedxslwefjttmtce

解密过程1:找出秘钥长度

Kasiski测试法::

若用给定的密钥表,周期地对明文加密,则当明文中的相同字母,如果被相同的秘钥字母加密,则会得到相同的密文字母,但是如果只考虑单个字母被加密的情况,可能就过于普遍了。

理解起来其实很简单,在加密后的文本中,出现的重复单词,很可能就是由相同的原文,通过相同的秘钥段加密得到的,而这些重复单词的间距,是秘钥长度的倍数,多个间距的gcd大概率就是秘钥长度。可以找出所有长度超过3的重复单词,统计他们间距的gcd,然后看一看哪一个最合适当公钥长度。只要文本量足够大,就可以提取出足够多的有效信息。

话不多说,上代码(python3):

def Kasiski(data): #搜索相同的3个字符,在文本中出现的位置偏移量,并求得他们的gcd,
    dict={}
    t=0
    for i in range(len(data) - 2): #其实是穷举了所有出现在4次以上的3个连续字符,
        if t > 1000000:      #这个break条件不加无所谓,数据量非常大可以加一加
            break
        item = data[i:i + 3]
        if item in dict.keys():  #如果这次的3个字符已经统计过了,就continue
            continue
        if data.count(item) >= 4: #只统计出现超过4次的,只出现一两次,基本是没意义的
            dict[item] = []
            t = t + 1
            # print(item,i)
            j = i + 3
            while j <= len(data) - 2:
                pos = data.find(item, j)
                # print(pos)
                if pos > 0:
                    dict[item].append(pos - i)  #统计的是,第pos次出现的位置和第一次出现位置的差值。这些差值很可能是秘钥长度的倍数。
                    j = pos + 3            #小细节,防止无效统计
                else:
                    break
    keylen=[]
    for item in dict.keys():
        x=math.gcd(dict[item][0],dict[item][1]) #算一个gcd
        for i in dict[item][2:]:
            x=math.gcd(x,i)
        if x>2:
            keylen.append(x)
    print(keylen)  #打印出来,一般就很明显了。

原始data进过Kasiski检测,打印出来是:[20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 10, 20, 20, 20, 20, 20, 20, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5],很明显了,秘钥长度是5,而且说明这数据有很多重复。

解密过程2:求得秘钥的每个字母

求得秘钥的关键在于,确定了秘钥长度 k k k 之后,可以把密文的第 1 1 1个,第 k + 1 k+1 k+1个,第 2 k + 1 2k+1 2k+1个…密文字母提取出来组成一个新的文本,这个抽取出来的文本,都是由秘钥的第一个字符加密得到的,就相当于一个凯撒密码。然后利用重合指数法,这个网上有很多说明,也很好理解。我们就把这一串提取出来的文本反向凯撒回去,26个字母一个个试,只要他给的原文文本是有意义的,符合英文文本的正常规律(字母出现的大数据频率)就可以了。

代码(python3):

def divstr(str, i, n):   #分割函数,知道列表切片就很好懂
    c = str[i::n]
    return c
    
def getkey(data,n):
    p = [0.08167, 0.01492, 0.02782, 0.04253, 0.12702, 0.02228, 0.02015, 0.06094, 0.06966, 0.00153, 0.00772, 0.04025,
         0.02406, 0.06749, 0.07507, 0.01929, 0.00095, 0.05987, 0.06327, 0.09056, 0.02758, 0.00978, 0.02360, 0.00150,
         0.01974, 0.00074]
    key=''
    for i in range(n):
        str = divstr(data, i, n).lower()
        Mi = []
        for i in range(26):
            r = []
            sum_m = 0
            for y in range(0, 26):
                r.append(str.count(chr(97 + (y + i) % 26)))  
                # 统计字串中a-z 偏移i位后得到的字符在每组中的数量,
            for x in range(0, 26):
                f = (r[x] * p[x]) / len(str) 
                #当偏移i位后 得到的字符所做拟合指数(sum_m)最接近0.065(最大)
                sum_m = sum_m + f
            Mi.append(sum_m)
        key += chr(97 + Mi.index(max(Mi)))
    return key

运行结果:

请选择秘钥长度:5
apple

解密过程3:按照秘钥和表进行解密

然后就是,按照维吉尼亚表进行替换,解密一下,这个也还算好写,转ascii再转char,中间注意mod一下26。

代码(python3):

def decrypt(miwen,key,keylen):
    mingwen=''
    for i in range(len(miwen)):
        # mingwen+=chr(65+(ord(miwen[i])+ord(key[i%keylen])-130)%26)#加密
        mingwen+=chr(65 + ((ord(miwen[i])) - ord(key[i%keylen]) + 26) % 26)#解密

    print(mingwen.lower())
    return mingwen

运行结果:
lrgmgvvrkoyjkroiouaylrgmgvvrkoyjkroiouaylrgmgvvrkoyjkroiouaylrgmgvvrkoyjkroiouaylrgmgvvrkoyjkroiouayjkvktjotmutcnoinvrgekxeuagyqznklkbkxtubghgrrzngzyvuxzykwaovsktzsgqkxgjojgyygeyvxubojkyznkarzosgzkyuiikxkdvkxoktikoyatiutzxurrghrkzuuhomuxpayzyosvreyzavojznkhgrrgryungyozylgtyroqkktmrgtjyjgbojhkiqngshazyulgxznkeykkszungbkhkktuaztashkxkjheixozoiygjojgyygeyznkhgrryvrgynkjcoznmurjiuruxotmoywaozkyosvreznkhkyzgxuatjvkxiktzsuxkgiiaxgzkzngtznkhgrraykjgzlxgtikzngtqyzuskzoiaruayzkyzotmheyioktzoyzyotmkxsgteznkzutmakzcoyzotmtgzaxkulozyiutzktzyiutloxsyzngzznkcuxrjiavhgrrngyiuskgrutmcgelxusznkrkgznkxgtjrgikybgxokzezngzcgyiussutgyxkiktzregyznkyznklkbkxtubgyykixkzgjojgyygeyoyozyxgjoigrreosvxubkjyetzgizoilugsgtjatowakqtozzkjxgyinkrlghxoimobktzngzznoyoyyavvuykjzusgqkznkhgrrlgyzkxgtjvxubojkznklxkkqoiqyvkiogroyzyroqkhkiqngscoznsuxkvuckxozsgetuzhkyaxvxoyotmzngzmugrqkkvkxyroqkhallutgxkatngvveyvgotmugrqkkvkxvkjxuiutzxkxgyygojznkhgorgizyyzxgtmkrecnorkjgtoynqkkvkxznusgyyuxktyktgjsozzkjmruusorezngzozcuarjvxuhghrexkyarzotsuxkyvkizgiargxmugrygygmugrqkkvkxeuangbkzurobkcoznznklgizzngzznksgqkxyixkgzkhgrryluxznkhktklozulyzxoqkxynkygojhkluxkrkgbotmiuvktngmktluxyuaznquxkghazuazlokrjvrgekxyngbkgryuckomnkjotcoznixozoioyssgteygeotmznkhgrroyzuuromnzgtjznkxkluxkngxjzuiutzxurozyhomgtjozyzuuromnzpgvgtypopotkcygmktiewauzkjhxgforogtluxcgxjkjoryutgyygeotmkgxrokxznoysutzncnorkyzxoqkxxobgrjuygojozyugxkjzuulgxcnktqoiqkjpuaxtgroyzygzznksgotvxkyyiktzxkoteuqungsgngbkhkktmobktznkingtikzuzxeuazznklkbkxtubglxusznkvktgrzeyvuzcoznznkgosulnozzotmyvkiogrzgxmkzyotznkmugryulgxlkcngbkhkktghrkzuyiuxksuxkzngtlobkuazulzktgrznuamnznoysgengbkrozzrkzujucoznznkwagrozeulznkhgrrvazfgjsozyzngzznkhgrroyutznkromnzyojkullolgyzumxgsckomnzxkwaoxksktzhazygeyozoytuhommkxzngtvxkbouayhgrryznkiutzxubkxyeubkxznkhgrrgryungygtullvozinjosktyoutotjayzxeotyojkxyygeozsgehktuiuotiojktikzngzvrgekxylxushxgforyvutyuxkjhegjojgyxobgrtoqkngbkhkktgsutmznkhgrrysuyzbuiolkxuayixozoiyznkygsksomnzmuluxznkvxgoykjoynkjuazluxznkhgrrhehkiqngsutkulznksgotvrgekxyaykjzuvxusuzkgjojgykwaovsktz

发现啥也看不出来,不过仔细观察一下,很容易看出前面有重复字符lrgmgvvrkoyjkroiouay出现,后面就不在重复了,可惜我并没有产生敏感,这其实就是flag。
不过我面对这堆字符,没办法,就想是不是加密了不只一遍(其实是维吉尼亚基本只能加密一遍,因为再加密的时候,是无意义的密文再加密,不符合英文的基本分布规律。)
我又跑了几遍发现:
[20, 20, 20, 20, 20, 20, 20, 4, 20, 20, 20, 20, 20, 20, 4, 4, 3, 6]
请选择秘钥长度:2
gg
请输入秘钥

[20, 20, 20, 20, 20, 20, 20, 4, 20, 20, 20, 20, 20, 20, 4, 4, 3, 6]
请选择秘钥长度:4
gggg
请输入秘钥

然后可以确定是经过凯撒过的东西,于是直接把这一段lrgmgvvrkoyjkroiouay跑个26个凯撒。

代码(python3):

data='lrgmgvvrkoyjkroiouay'
for k in range(97,123):
    mingwen=''
    for i in data:
        mingwen+=chr(97+(ord(i)+k-194)%26)
    print(mingwen)

结果:
lrgmgvvrkoyjkroiouay
mshnhwwslpzklspjpvbz
ntioixxtmqalmtqkqwca
oujpjyyunrbmnurlrxdb
pvkqkzzvoscnovsmsyec
qwlrlaawptdopwtntzfd
rxmsmbbxquepqxuouage
syntnccyrvfqryvpvbhf
tzouoddzswgrszwqwcig
uapvpeeatxhstaxrxdjh
vbqwqffbuyitubysyeki
wcrxrggcvzjuvcztzflj
xdsyshhdwakvwdauagmk
yetztiiexblwxebvbhnl
zfuaujjfycmxyfcwciom
agvbvkkgzdnyzgdxdjpn
bhwcwllhaeozaheyekqo
cixdxmmibfpabifzflrp
djyeynnjcgqbcjgagmsq
ekzfzookdhrcdkhbhntr
flagappleisdelicious
gmbhbqqmfjtefmjdjpvt
hncicrrngkufgnkekqwu
iodjdssohlvgholflrxv
jpekettpimwhipmgmsyw
kqflfuuqjnxijqnhntzx

根据提示整理 flag{apple_is_delicious}

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值