维吉尼亚密码是一种多表替换密码。这种替换法是循环使用有限个字母来实现替换的一种方法。这种加密的加密表是以字母表移位为基础把26个英文字母进行循环移位,排列在一起,形成26*26的方正。采用的算法为:
f(pi)=(pi+ki)mod 26
0x01 加密过程
以密钥字母选择行,以明文选择列,两者的交点就是加密生成的密文
加密双方必须同时握有上表所示的表格,另外还必须商议出一把共同秘钥,这里必须强调的是表并非秘钥的一部分,也就是说,即使表被公开,也不影响系统的安全性
比如说:使用秘钥CRYPTOGRAPHY对明文STRIKE WHILE THE IRON IS HOT加密
-
将秘钥重复地写在明文的上方
CR YP TO GR AP HY CR YP TO GR AP H
ST RI KE WH IL ET HE IR ON IS HO T -
上下两个字母去查表
比如第一个字母对为(C,S),查表为U,依次查询下去 -
得到结果
UKPXDSCYIAIRJVGGHBOJHDA
0x02 解密过程
以秘钥字母选择行,从中找到密文字母,密文字母所在列的列名就是明文字母
- 将秘钥重复地写在明文的上方
- 根据秘钥所在的行,找到密文,取列名
0x03数学描述
设密钥K=(k1,k2,…,kd),明文M=(m1,m2,…,mn),密文C=(c1,c2,…,cn);
加密变换为:ci=Eki(mi)=mi+ki(mod 26)
解密变换为:mi=Dki(ci)=ci-ki(mod 26)
通常通过查询维吉尼亚表进行加解密。
0x04 加密算法
"""
实现维吉尼亚的加密解密
"""
def VigenereEncode(message,key):
pLen=len(message)
kLen=len(key)
message=message.upper()
key=key.upper()
raw = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" # 明文空间
out=""
for i in range(0,pLen):
j=i%kLen
if message[i] not in raw:
out+=message[i]
continue
encodechr=chr((ord(message[i])-ord('A')+ord(key[j])-ord('A'))%26+ord('A'))
out+=encodechr
return out
if __name__ == "__main__":
P="strikewhiletheironishot"
key="cryptography"
out=VigenereEncode(P,key)
print("加密后的密文是:")
print(out)
0x05 解密算法
"""
实现维吉尼亚的加密解密
"""
def VigenereEncode(message,key):
pLen=len(message)
kLen=len(key)
message=message.upper()
key=key.upper()
raw = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" # 明文空间
out=""
for i in range(0,pLen):
j=i%kLen
if message[i] not in raw:
out+=message[i]
continue
encodechr=chr((ord(message[i])-ord('A')+ord(key[j])-ord('A'))%26+ord('A'))
out+=encodechr
return out
def VigenereDecode(message,key):
"""
解密
:param message: 密文
:param key: 密钥
:return: 明文
"""
CLen=len(message)
kLen=len(key)
key=key.upper()
raw = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" # 密文空间
plaintext=""
for i in range(0,CLen):
j=i%kLen
if message[i] not in raw:
plaintext+=message[i]
continue
decodechr=chr((ord(message[i])-ord('A')-ord(key[j])-ord('A'))%26+ord('A'))
plaintext+=decodechr
return plaintext
if __name__ == "__main__":
P="strikewhiletheironishot"
key="cryptography"
encode=VigenereEncode(P,key)
decode=VigenereDecode(encode,key)
#print("加密后的密文是:")
print(decode)
0x06 维吉尼亚分析目标
- 加密:ek(x1,x2,…,xm)=(x1+k1,x2+k2,…,xm+km)
- 解密:dk(y1,y2,…,ym)=(y1-k1,y2-k2,…,ym-km)
- 秘钥:k=(k1,k2,km),所有的运算都是在模26下进行的
- x,y是26个字母下标,a=0,b=1,…,z=25
我们分析一个维吉尼亚密码的目标是求出k1,k2,km,方法有:
- Kasiski method(1863,Friedrich kasiski)
- 重合指数法(1920,William Friedman)
kasiski测试法:
寻找密文中相同的片段对,计算每对相同片段对之间的距离,不妨记为d1,d2,…,di,若令秘钥字的长度为m,则m=gcd(d1,d2,…,di),gcd是求d1,d2,…,di的最大公约数。
若两个相同的明文片段之间的距离是秘钥片段的倍数,则这两个明文片段对应的密文一定相同。
若密文中出现两个相同的秘文段(密文段的长度m>2),则它们对应的明文将以很大的概率相同(99%)
我们用CAP分析一个例子:
已知一个密文:zicvtwqngrzgvtwavzhcqyglmgj
测试过程
- 1、在密文中找到重复的字符串:vtm
- 2、两个字符串的起始位置分别为4和13
- 3、其距离为9
- 4、9的因数有3和9
- 5、根据步骤4的因数,秘钥的长度可能为3或9
所以接下来我们要判断密钥的长度到底为多少,当我们面对一篇密文时,若要分辨其为单表代换法还是多表代换法,可用重合指数。
设X=x1x2…xn是一个长度为n的英文字母串,则x中任意选取两个字母相同的概率定义为重合指数,用Ic(x)
当n趁近为无穷大时
- IC为重合指数
- 单表替换加密的密文IC=0.065
- 多表替换加密IC=0.038
我们来举个例子来计算IC:
密文:HLUBNWFSFKIGIHMGBSIMMBSEJMAFUTQECIILJSUBBAXMAJCWXCMBSGZGGSMKBHUQBETVUSMLMERCFDTWUBASWERFIELOMVYSIMMYYEDDMMSGZANCOFYYTIHLJRYOHKLOFHIEFKQOFAAIZGIEJHAKNZJSQRUQXDKWHSNNFAOUMOROFAAIZPIQYHQFYSWEFKILDPQGIXUEADFWNNFVYOTRXRGQKRUSHVYHAGYONTTZISIEPUOFXAZRNZTSQKBGIISMIMIISMIMXHAHUFZNMFGWIMMBQWQLTSMZTUXRBSAEMFGWIHUAMWQFFVCKNSMTIJYYRCOJRASBOEYHQAIKYPAKYJKUXVUFIGGBCFYHQKIJQDFVULBOGZXTQOIMIMWHQOXUQEMBIXKYAIBSAEFCUKPYAILKJLRRIQTURSYDQUOYSOJLXRIQTUBIHC
我们用CAP分析,就不手算了,计算量太大
我们将密文粘贴到Ciphertext,在basic tools有个IC点击
点击run,出来0.04319,和0.038很近,猜测为多表代换
重合指数确定秘钥长度
根据Kasiski测试方法得到的m,可以将密文按照下列形式排列
每一行都是单表代换,若m确实是秘钥的长度,则上述矩阵中的每一行都是由同一个密钥ki加密得到,这说明每一行即是一个单表代替,这时计算每一行的重合指数,应该更接近0.065;
若m不是密钥的长度,则上述矩阵中的每一行不是由同一个密钥ki加密得到,这说明每一行是一个等概随机的字母串(对密文的要求),这时计算每一行的重合指数,应该更接近0.038。
密文:
CHREEVOAHMAERATBIAXXWTNXBEEOPHBSBQMQEQERBWRVXUOAKXAOSXXWEAHBWGJMMQMNKGRFVGXWTRZXWIAKLXFPSKAUTEMNDCMGTSXMXBTUIADNGMGPSRELXNJELXVRVPRTULHDNQWTWDTYGBPHXTFALJHASVBFXNGLLCHRZBWELEKMSJIKNBHWRJGNMGJSGLXFEYPHAGNRBIEQJTAMRVLCRREMNDGLXRRIMGNSNRWCHRQHAEYEVTAQEBBIPEEWEVKAKOEWADREMXMTBHHCHRTKDNVRZCHRCLQOHPWQAIIWXNRMGWOIIFKEE
CAP分析Kasiski:
因数出现最多次数是5,即密码长度最有可能为5,需要进一步确定
接下来我们计算IC,将密文排列
计算每一行的IC,都接近0.065,因此可以推断,密钥的长度m=5
接下来就是确定密钥了。
思路
- 利用频率分析方法分析,对上面排成的矩阵,每一行都是循环移位密码,参考凯撒密码的分析方法。单表替换不改变字母的统计规律