流密钥解密(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