流密钥解密(python)

原理在上一节:https://www.cnblogs.com/cyssmile/p/12829098.html
用python实现xor加密的解密,这个比上次写的c++多了一个,通过比较前后的概率更新key

1.首先读入密文

   我们前面了解到密文是以十六进制存储的,我们这里也观察到每段密文个数是偶数个,所以我打算每两个一组进行简单处理。
每两个一组得到的是字符的ASCLL码的形式。(其实如果可以投机一下,我们可以将所有密文切成,需要解密密文的长度一样大就好了)
import sys
import string

这里为了方便理解整个过程,我就不把读取数据这部分单独定义在函数里面,方便每写一部代码进行测试。

data_lists = []
with open('./ciphertext.txt','r') as f:
    read_data = f.read()
    data_lists = read_data.split(' ')
'''
    将数据转换成ascll码的形式
'''
data_asc = []
for oneCipertext in data_lists:
    num = 0
    new_list = []
    while(True):
        str_list = oneCipertext[num:num+2]
        num = num + 2
        if str_list:
            temp = int(str_list,16)
            new_list.append(temp)
            
        else:
            break
    
    data_asc.append(new_list)

'''
查看处理的数据形式

print(data_asc)
''' 

2、我们下面要将每组数据与其他组的数据进行异或操作

# 定义每一组密文与另外一组密文之间的操作
def XOR(list_a,list_b):
    num = 0;
    xor_result = []
    min_len = min(len(list_a),len(list_b))
    while (num < min_len):
        temp = int(list_a[num]) ^ int(list_b[num])
        xor_result.append(temp)
        num = num + 1
    
    return xor_result     
#每一组密文与其他所有密文进行异或(非自身)
'''
data_asc :开始读入并处理的密文集合 [[],[],[],..]
index: 当前要统计的密文在data_asc中的序号
'''
def oneXorInfo(data_asc,index):
    if index >= len(data_asc):
        return
    
    #处理数据
    ori_ascll = data_asc[index]
    xor_all = []
    count = 0
    for item in data_asc:
        if(count == index):
            count = count +1
            continue
        xor_result = []
        xor_result = XOR(ori_ascll,data_asc[count])
        xor_all.append(xor_result)
        count = count + 1
    
    return xor_all
'''
测试下这部分
ori_asc = data_asc[0]
xor_all = oneXorInfo(list(data_asc),0)
print(xor_all)

'''

3、我们统计下每一组密文可能是空格地方

'''
accL 当前位置为字母的个数
totoL 共统计了多少组
由于xor_all 中长度不一样,所以设置了一个totoL
'''
def oneStatistic(xor_all):
    accL = [] 
    totolL = []
    for item in xor_all:
        count = 0
        for it in item:
            if ((it <= 90 and it >= 65) or (it >= 97 and it <= 122)):
                if count <len(accL):
                    accL[count] = int(accL[count]) + 1
                    totolL[count] = int(totolL[count]) + 1
                else:
                    accL.append(1)
                    totolL.append(1)
            else:
                if count <len(accL):
                    totolL[count] = int(totolL[count]) + 1
                else:
                    accL.append(0)
                    totolL.append(1)
            count = count + 1

    return accL, totolL  
'''
测试这段代码吧
ori_asc = data_asc[0]
xor_all = oneXorInfo(list(data_asc),0)
#print(xor_all)
accL = []
totolL =[]
accL,totolL = oneStatistic(xor_all)
print(accL)
print('')
print(totolL)
'''

4、由一组密文更新秘钥的情况

key 是秘钥的ascll码,maybeK是上一个推断此处为空格的概率,主要用于可能更新上一个推断的秘钥,即是这次概率除了高于threshold
还高于上次可能的概率,这里threshold 设置为0.5

def updateKey(key,maybeK,accL,ori_ascll,totolL):
    count = 0
    threshold = 0.5
    if(len(key)>=len(accL)):
        while(count < len(accL)):
            if accL[count]/totolL[count] >= threshold and accL[count]/totolL[count] > maybeK[count]:
                key[count] = int(ori_ascll[count]) ^ 32
                maybeK[count] = accL[count]/totolL[count]
            
            count = count + 1
            
    # 之前推测的秘钥长度没有当前这组长度长时
    
    if(len(key)< len(accL)):
        while(count < len(key)):
            if accL[count]/totolL[count] >= threshold and accL[count]/totolL[count] > maybeK[count]:
                key[count] = int(ori_ascll[count]) ^ 32
                maybeK[count] = accL[count]/totolL[count]
                
            count = count + 1
            
        #单独处理多余部分
        while(count < len(accL)):
            if accL[count]/totolL[count] >= threshold:
                key.append(int(ori_ascll[count]) ^ 32)
                maybeK.append(accL[count]/totolL[count])
            else:
                key.append(0)
                maybeK.append(0)
                
            count = count + 1
'''
ori_asc = data_asc[0]
xor_all = oneXorInfo(list(data_asc),0)
#print(xor_all)
accL = []
totolL =[]
accL,totolL = oneStatistic(xor_all)
print(accL)
print('')
print(totolL)

key = []
maybeK = []
updateKey(key,maybeK,accL,ori_asc,totolL)
print(key)
print('')
print(maybeK)
'''
def predKey(data_asc,key,maybeK):
    count = 0
    for item in data_asc:
        ori_asc = data_asc[count]
        xor_all = oneXorInfo(list(data_asc),count)
        accL,totolL = oneStatistic(xor_all)
        updateKey(key,maybeK,accL,ori_asc,totolL)
        count = count +1
if __name__ == '__main__':
    data_lists = []
    with open('./ciphertext.txt','r') as f:
        read_data = f.read()
        data_lists = read_data.split(' ')
    
    data_asc = []
    for oneCipertext in data_lists:
        num = 0
        new_list = []
        while(True):
            str_list = oneCipertext[num:num+2]
            num = num + 2
            if str_list:
                temp = int(str_list,16)
                new_list.append(temp) 
            else:
                break
                
        data_asc.append(new_list)
    
    key = []
    maybeK = []
    predKey(data_asc,key,maybeK)
    
    # 我们来解密最后的结果
    result_x = XOR(list(key),data_asc[10])
    str_result = ''
    for item in result_x:
        str_result = str_result + chr(item)
    
    print(str_result)
The secuet message is: Whtn using aastream cipher, never use the key more than once

到这里我们就可以看到我们想要的结果

The secuet message is: Whtn using aastream cipher, never use the key more than once

我们可以推测结果为:

The secure message is: With using a stream cipher, never use the key more once

posted @ 2020-05-12 14:27  cyssmile  阅读(770)  评论(0编辑  收藏  举报