密码学导论第一章作业维吉尼亚密码唯密文攻击

加密模块

key =input("请输入密钥:")
#储存密钥
ls = []         
for i in key:
    ls.append(ord(i)-97)
length = len(ls)

#打开明文并处理,将明文存入text
file = open('plaintext.txt','rt')
text=''
for line in file:                                                   #读取每行明文
    line = line.strip("\n")                                        #去除每行的换行符
    for j in line:
        if j in ['!','~','`','@','#','$','%','^','&',' ',\
                '*','(',')','_','+','=','?','.',',',';',':']:       #去除标点符号
            line = line.replace(j,'')                                     
    text +=line.lower()
file.close()

#对明文加密
k=0
outpath = 'cipher.txt'           #密文输出路径
output = open(outpath,'wt')
for char in text:
    char = ord(char)-97
    char = (char + ls[k]) %26
    k = (k+1)%length                                            #每次将k加1并模密钥的长度,实现对全文加密
    char = chr(char+97)
    output.write(char)
print('加密成功,输出文件{}'.format(outpath))
output.close()
input("输入回车关闭窗口")

将要加密的内容存放在plaintext.txt文件钟,运行后首先输入密钥,然后会生成加密后的文件cipher.txt。

解密模块

key =input("请输入密钥:")

#储存密钥
ls = []         
for i in key:
    ls.append(ord(i)-97)
length = len(ls)

#打开密文并处理,将明文存入text
file = open('cipher.txt','rt')
text=''
for line in file:                                                   #读取每行密文
    line = line.strip(" \n")                                        #去除每行的换行符
    text +=line
file.close()

#对密文解密
k=0
outpath = 'decode.txt'           #密文输出路径
output = open(outpath,'wt')
for char in text:
    char = ord(char)-97
    char = (char - ls[k]) %26
    k = (k+1)%length                                            #每次将k加1并模密钥的长度,实现对全文加密
    char = chr(char+97)
    output.write(char)
print('解密成功,输出文件{}'.format(outpath))
output.close()
input("输入回车关闭窗口")

运行后输入密钥,将密文解密后的明文存在decode.txt中。

破解密钥

import math
f = open('cipher.txt','rt')             #读取密文
ciphertext = f.read()
f.close()

length = len(ciphertext)
#字母出现频率
Beker_Piper = {'a':0.0804,'b':0.0148,'c':0.0334,'d':0.0382,'e':0.1249,'f':0.0240,'g':0.0187,'h':0.0505,'i':0.0757,'j':0.0016,'k':0.0054,'l':0.0407,'m':0.0251,'n':0.0723,'o':0.0764,'p':0.0214,'q':0.0012,'r':0.0628,'s':0.0651,'t':0.0928,'u':0.0273,'v':0.0105,'w':0.0168,'x':0.0023,'y':0.0166,'z':0.0009}
#储存重复子串及其出现的位置
dic = {}
sublen = 3                                         #子串的长度  
for i in range(len(ciphertext)-(sublen-1)):          #寻找重复子串
    substring = ciphertext[i:i+sublen]           #substring为片段
    if substring in ciphertext[i+sublen:]:
        dic[substring] = dic.get(substring,str(ciphertext.index(substring))+',') + str(ciphertext[i+sublen:].index(substring)+sublen+ i) + ","        
    else:
        dic[substring] = dic.get(substring,str(ciphertext.index(substring))+',')
frequent = 8                               #子串出现次数
KEY = {}        #密钥的集合
for substring in dic.values():              #遍历重复子串
    if len(substring) > frequent:
        #print("子串---------------------------------------------------------")
        index=substring.split(',')[:-1]         #计算子串间隔
        gap = []
        for i in range(1,len(index)):
            gap.append(int(index[i])-int(index[0]))
        
        #计算最大公约数
        gcd = gap[0]
        for num in gap[1:]:
            gcd = math.gcd(gcd, num)
        #print(gcd)
        sectionlen = length // gcd              #分段
        Iclist = []
        
        if gcd > 1:
            M = []
            for j in range(gcd):
                s=''                        #储存每一段的字符串
                for i in range(j,len(ciphertext),gcd):
                    s +=ciphertext[i]
                sum1 = 0
                for p in range(26):
                    sum1 += (  s.count(chr(p+97))  *  (s.count(chr(p+97))-1)  )
                Iclist.append(sum1/(len(s) * (len(s)-1)))           #计算重合指数
                if sum1/(len(s) * (len(s)-1)) <0.05:                #重合指数小于0.05的排除
                    break
                #如果符合条件,计算密钥
                #猜测g
                for g in range(25):                
                    sum2 = 0
                    for a in range(25):
                        sum2 +=Beker_Piper[str(chr(a+97))]*s.count(chr((a+g)%26+97))
                    if sum2/len(s) > 0.055:
                        M.append(chr(g + 97))
            key = ''.join(M)
            if key != '':
                KEY[key] = KEY.get(key,0) + 1           #将可能的密钥添加到字典
#对所有可能的密钥进行排序
items = list(KEY.items())
items.sort(key=lambda x:x[1], reverse=True)
print('密钥按概率从大到小可能为:')
for i in range(5):
    print('{}、'.format(i),items[i][0])
input("输入回车关闭窗口")

运行该程序后会将概率最高的5个密钥打印出来。

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
维吉尼亚密码是一种基于多个凯撒密码组合而成的加密方式,攻击者需要猜测密钥的长度,并使用统计分析和频率分析等方法进行破解。以下是一个简单的密文攻击破译演示: 1. 首先,选取一段加密文本(密文),假设为“LHJABHJWLNCR”,并且不知道密钥的长度和内容。 2. 接下来,使用Kasiski检测法来猜测密钥的长度。该方法的基本思想是找到加密文本中重复的三元组(三个字符组成的序列),并计算它们之间的距离。如果这些距离的最大公因数是2、3或其他较小的质数,那么很可能密钥的长度是这些距离的最大公因数。在本例中,我们可以找到两个重复的三元组“HJ”,它们之间的距离为6。因此,密钥的长度可能是6的倍数。 3. 接着,对于每个可能的密钥长度,使用频率分析来猜测密钥的内容。首先,将加密文本按照密钥长度进行分组,例如,将“LHJABHJWLNCR”按照密钥长度为6进行分组,得到: ``` LHJABH JWLNC R ``` 4. 对于每个分组,计算每个字符出现的频率,并和英文字母表的频率进行比较。由于维吉尼亚密码是基于多个凯撒密码组合而成的,因此每个分组的加密方式可能是凯撒密码。对于每个分组,找到偏移量使得加密后的字符频率最接近英文字母表的频率。例如,在第一个分组中,如果将每个字符都向右偏移2个位置,则加密后的字符频率最接近英文字母表的频率。因此,偏移量为2,密钥的第一个字符可能是B。 5. 对于每个分组,重复步骤4,找到偏移量和密钥的下一个字符,直到所有的密钥字符都被猜测出来。在本例中,偏移量和密钥的字符依次为: ``` LHJABH: BACDEF JWLNC: GHIJK R: LMNOPQRSTUVWXY ``` 6. 最后,使用猜测出的密钥对加密文本进行解密,得到明文“HELLOWORLD”。 这是一个简单的密文攻击破译演示,实际上,维吉尼亚密码可以通过更复杂的方法进行加密和破解,例如,使用多个密钥,或者使用改进的频率分析方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值