先从简单的单表代替开始说起:要知道,在CTF题中,有很多很多都是单表代替的题,比如说:
BH=CWG=EO=IEI=;DEDEDEY
所有数据长成这样,神TM能够认识对吧,但是要注意,这可是CTF的比赛!所以得分模式很套路:
最后的答案一般都是flag{}或者FLAG{}什么的对吧
那么,计算一下:
ord(‘Y’)-ord(‘}’)= - 36
那么,再试试:ord(‘B’)+36 = ord(‘f’)
所以,直接尝试一发,所以的都是36的偏移就好了,对吧
很简单的kaisamima对吧,本质上是个ascii码表的偏移对应,或者是自己定义的某些字符的循环对应
在数据文本字符情况下足够的情况下,统计英文字频即可简单破解:因为英文中的每个字符的出现概率是有固定的比例的(不是所有的都一定按照顺序,但是大概已经可以基本对应了)
那么,来谈谈什么是Virginia密码:因为单表对应很容易破解,那么换成多表呢?
所以我们确定一种对应的方法:Virginia
这种方法需要密钥,密钥的长度是单表的数量(其实是不同的字符个数)
其实,多个单表的对应关系是这样,可以一个一个算,但是,根据多个单表的思想来理解会更简单
用python代码举例会更简单吧:
import string
s = string.printable[36:62]
word = 'TOBEORNOTTOBETHATISTHEQUESTION'
cipher = 'RELATIONS'
info = ''
for i in range(0,len(word)):
info += s[(s.find(word[i])+s.find(cipher[i%len(cipher)]))%26]
print info
flag = ''
for i in range(0,len(info)):
flag += s[(s.find(info[i])+26-s.find(cipher[i%len(cipher)]))%26]
print flag
当然,在实际应用中并不会有这么的简单:我们不可能知道密钥是什么,甚至连密钥的长度我们也无从知道
那么,就只能根据方法来暴力测试:
kasiski测试法,来测得密钥的长度,理论是:当字符数目足够多的话,那么有可能出现,相同的字符串被相同的偏移串加密,那么得到的结果是相同的,我们把这些所有的可能全部统计下来,可以得到这些偏移值之间的相对距离。取他们的公共因子,就可能是密钥的长度
暴力的python代码如下:
def get_len(s):
val = []
length = len(s)
const = 4
for i in range(0,length-const):
for j in range(i+1,length):
if s[i:i+const] == s[j:j+const]:
val.append(j-i)
print val
其中的const越大,说明出现的概率越低,数量会越少;const越小,出现的概率越大,数量越多
我们需要取得一个适中的值,让val里大概有个10个数字左右,然后大概看下他们的公因数,一一分析,或者结合其他的方法来进行密钥长度的判断以及下一步计算
接下来就是确定密钥
这里给出两个CTF样例题,可以解释说明得很明白:
https://findneo.tech/171005NuptVigenereWP/#%E5%8F%82%E8%80%83%E9%93%BE%E6%8E%A5