密码学实战
维吉尼亚密码
以一道作业题为例子
思路
1.确定m,利用重合指数法,首先猜测m的长度,然后按m将密文分组,取每组的第1,2….n,分别放在一起,形成新的文本,以字典形式表示,key = 组号 ,value = 字符串。
2.计算重合指数,因为key是变化的,每一组需要多右移动一次,因此每一个字符串并非是简单的平移,而是后一个字符要多平移一个,因此需要变换字符串为正常情况来进行重合指数的分析,(就是把每个字符串的字符按索引平移回去)。
3.重合指数的计算,遍历m,分别计算平均重合指数,然后取平均值在0.6以上的(则表明非随机)。
4.确定key,再次利用重合指数法,算出每一个组的每个字符出现的频率,然后利用有意义字符的频率,来进行重合指数的计算(最多尝试26次,即可确定key),注意解出来的并非是key,而是key的逆,也就是说key-26。
5.通过4计算而得的key,平移每个组的字符串,再将其按照一的方式组合回去,即可得到明文。
实现
1.文本预处理
这一步删除掉密文的换行之类,并统一大小写
def pretreatment(): |
2.遍历寻找m
这一步需要两步骤:
1.按m长度的key对密文进行分组,并猜测m的长度
def guess_len_key(crypt): |
其中比较重要的一个点是重合指数的计算,这里面在计算重合指数之前,需要将每一个子字符串每个字符平移,平移数目为索引。(具体原因在思路已经介绍)
def coincidence_index(text): |
经过上述过程已经得到按固定组长分割好的特定的子字符串,而每一组相对应为key中的一个字符,且是一个另类的单表循环,只不过排在后面的要多循环一位。经过下属过程处理可以将其转换为一般的单表循环,基本上和
shift_text_left
函数的道理是一样的
def single(b): |
结果展示:
|
2.寻找key
遍历每一个字串,然后从0-25给每个字符加偏移量,作为newstr,利用newstr和frequency频率分布表去计算重合指数,找到0.6左右的,那么偏移量则是正确的偏移量,但是这个是解密的偏移量,和key的字符的距离a的距离之后整好为26,因此要是算key需要进一步变换。
frequency = [0.082,0.015,0.028,0.043,0.127,0.022,0.02,0.061,0.07,0.002,0.008,0.04,0.024,0.06,0.075,0.019,0.001,0.06,0.063,0.091,0.028,0.01,0.023,0.001,0.02,0.001] |
可以得出解密密钥为:
当前字串为: ihdndxilhadwidwsdtxllwsslhunptwgdpnthdvvrttrthxihh |
3.恢复文本
此步骤比较简单,通过密钥恢复相应文本,然后再把每一个组融合在一起,完事
def de(dic, key): |