密码学—Kasiski测试法Python程序

Kasiski测试法用于辅助破解使用Vigenere密码的密钥长度,通过查找和分析相同密文段,计算最大公因数来推测密钥周期。该方法依赖于找到重复的密文片段,通过对这些片段位置的下标求最大公因数来估计密钥长度。在Python中,利用内置函数find可以高效实现这一过程,但其有效性受限于密文中重复片段的出现和文章长度。找到可能的密钥长度后,还需结合其他方法如重合指数来进一步验证。

Kasiski

Kasiski是辅助破解Vigenere的前提工作,Kasiski是猜测加密者使用Vigenere密码体系的密钥的长度,Kasiski只是猜测长度而已,所以说是辅助破解Vigenere

若密文中出现两个相同的密文段(密文段的长度m>2),则它们对应的明文(及密钥)将以很大的概率相同(后文有一个该概率的计算)。
针对多表密码,首要的是得到秘钥字的长度,进一步判断密钥字的长度是否为:m=gcd(d1,d2,…,di) d:为密文片段直接的距离。
我们可以猜测秘钥字的长度m可能是d1,d2,…,di 最大公因子。
这就是Kasiski测试法。
——出自我的密码学老师PPT原文

  • 我的理解
    Kasiski的主要功劳即使帮助破解Vigenere密码找到密钥长度,具体如何找的

    • 找相同的密文片段(片段当然是两个以上才算,这个具体找多少个自己写算法的时候自己确认,或者设置一个参数手动输入)
    • 记录相同片段出现的位置(记录的是片段第一个字母出现的位置作为整个片段出现的位置)
    • 当然考虑到的肯定就是出现次数最多的了(这个算法实现还是比较费脑子)
    • 当然在找的过程中还要记录下每个出现的位置,然后用这个位置求最大公因数,那么这个最大公因数就是最有可能的密钥长度
  • 为什么最大公因数就是有可能是密钥长度
    因为在Vigenere加密中,使用的是多表加密,每一个表都是凯撒密码,使用的都是同一个字母加密,不同表只是在密钥串中的不同字母加密而已。所以假如说有相同的片段出现,就可以推断出相同密钥字母出现的周期,然后周期就是这个密钥的长度,因为Vigenere就是周期性的使用密钥对明文进行加密,下面我密码学老师的PPT对这个说法有一个很好的解释,一眼就看出是周期性的时候密钥加密。
    在这里插入图片描述
    这也很明显的点名了为啥Vigenere中要分组加密,因为分好组之后每一组第一个字母使用的都是同一个密钥加密,所以也就所谓的单表对应凯撒密码加密,Vigenere使用多个凯撒加密表。

找到出现相同片段

  • 算法实现
    • 困难:如何找到出现次数最多的片段(字母串)?
      Python真是帮了很大的一个忙了,因为有find内置函数省了我很多工作,因为只要用好下标就能够找到所有出现过的单词
    • 我的想法
      首先是传入一个字符串,然后a参数代表找的最短连续出现的片段长度,b代表最长的出现片段长度。
      为什么要这么做呢:因为如果不设置一个参数人为的介入这个程序会无限制的找下去,直到整个字符串都会find一遍,这样式毫无意义的,还很浪费性能与时间。
      由于find内置函数返回的值就是要找的片段第一个字母出现的下标,因此我甚至省去写如何找下标的步骤(在此特地感谢Python开发者们)
      • 找到下标之后我将其存进一个字典,字典的键是字符片段,值就是该片段在文本中出现的位置的各个下标,然后如果要记录出现此处就计算该列表的长度就是出现的次数了。
      • 这里我配合find内置函数采用了切片的方式进行找同片段,从给出的a参数最短的片段作为开头,那么在文本中开头0~a长度的就不用找,以此为第一个单词,然后用这个单词在后面find如果find到了表示OK找到的,存find函数返回的出现的下标,全部找完之后,使用a长度跨越a个步数,意思是这个片段已经全部找到了,往后的就是该片段之后的要重复上述操作。
      • 这里我当时想了一个我自认为很妙的方法:我遍历的是传入的ab参数,因为是人为介入的,所以我应该是从a长度的开始找,这里我的目的是给出一个步长变量step,为的就是让第二层遍历在找完某个step长的单词片段之后跨越step长度继续往后找,然后这个step还给当找到一个之后继续往后找的时候就从找到的片段的下标再加一个step然后就可以将其继续往后找,这里我认为是减少了再次遍历的次数,我个人是觉得优化了一下
      • index = mess.find(mess[i:i + step], index + 1)解读
        这个一个就是我认为写的很好的一点,mess是全部文本,首先mess[i:i+step]是表示当前要找的片段,由于是while是确保了后面会有相同片段的,然后index+1代表找第二次的时候,index已经记录第一次找到的下标,这里第二次找就是从已经找到的片段的后面找起。
def findSameWords(self, mess, a, b):
    # 找出现次数最多的字符,返回他所有下标和字符本身

    dit_wordCount = {
   
   }  # 保存不同长度的字符出现次数最多的,键:'字符',值:[出现的次数, [每次出现的下标]]

    for step in range(a, b + 1):
        for i in range(len(mess) - step)
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

竹等寒

谢过道友支持,在下就却之不恭了

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值