上一篇文章介绍了维吉尼亚密码的加解密过程,下面针对解密问题附上完整代码。(由于在程序运行过程中我是分步进行以便查看结果,因此代码段会涉及多次调用密文文档文件,当然,也可以将几个代码块融合在一起形成一个完整的代码文件)
计算密钥长度
#-*- coding:utf-8 –*-
def c_alpha(cipher): # 去掉非字母后的密文
cipher_alpha = ''
for i in range(len(cipher)):
if (cipher[i].isalpha()):
cipher_alpha += cipher[i]
return cipher_alpha
# 计算cipher的重合指数
def count_CI(cipher):
N = [0.0 for i in range(26)]
cipher = c_alpha(cipher)
L = len(cipher)
if cipher == '':
return 0
else:
for i in range(L): #计算所有字母的频数,存在数组N当中
if (cipher[i].islower()):
N[ord(cipher[i]) - ord('a')] += 1
else:
N[ord(cipher[i]) - ord('A')] += 1
CI_1 = 0
for i in range(26):
CI_1 += ((N[i] / L) * ((N[i]-1) / (L-1)))
return CI_1
# 计算秘钥长度为 key_len 的重合指数
def count_key_len_CI(cipher,key_len):
un_cip = ['' for i in range(key_len)] # un_cip 是分组
aver_CI = 0.0
count = 0
for i in range(len(cipher_alpha)):
z = i % key_len
un_cip[z] += cipher_alpha[i]
for i in range(key_len):
un_cip[i]= count_CI(un_cip[i])
aver_CI += un_cip[i]
aver_CI = aver_CI/len(un_cip)
return aver_CI
## 找出最可能的前十个秘钥长度
def pre_10(cipher):
M = [(1,count_CI(cipher))]+[(0,0.0) for i in range(49)]
for i in range(2,50):
M[i] = (i,abs(0.065 - count_key_len_CI(cipher,i)))
M = sorted(M,key = lambda x:x[1]) #按照数组第二个元素排序
for i in range(1,10):
print (M[i])
F = [
0.0651738, 0.0124248, 0.0217339,
0.0349835, 0.1041442, 0.0197881,
0.0158610, 0.0492888, 0.0558094,
0.0009033, 0.0050529, 0.0331490,
0.0202124, 0.0564513, 0.0596302,
0.0137645, 0.0008606, 0.0497563,
0.0515760, 0.0729357, 0.0225134,
0.0082903, 0.0171272, 0.0013692,
0.0145984, 0.0007836
] # 英文字符频率。
fp = open("F:\CTF\CTF资料\i春秋\代码\Crypto\Vigenere\Vigenere.txt","r")
cipher = ''
for i in fp.readlines():
cipher = cipher + i
fp.close()
cipher_alpha = c_alpha(cipher)
print ("秘钥长度为:")
pre_10(cipher)
计算密钥
#-*- coding:utf-8 –*-
def c_alpha(cipher): # 去掉非字母后的密文
cipher_alpha = ''
for i in range(len(cipher)):
if (cipher[i].isalpha()):
cipher_alpha += cipher[i]
return cipher_alpha
# 计算cipher的重合指数
def count_CI(cipher):
N = [0.0 for i in range(26)]
cipher = c_alpha(cipher)
L = len(cipher)
if cipher == '':
return 0
else:
for i in range(L): #计算所有字母的频数,存在数组N当中
if (cipher[i].islower()):
N[ord(cipher[i]) - ord('a')] += 1
else:
N[ord(cipher[i]) - ord('A')] += 1
CI_1 = 0
for i in range(26):
CI_1 += ((N[i] / L) * ((N[i]-1) / (L-1)))
return CI_1
# 计算秘钥长度为 key_len 的重合指数
def count_key_len_CI(cipher,key_len):
un_cip = ['' for i in range(key_len)] # un_cip 是分组
aver_CI = 0.0
count = 0
for i in range(len(cipher_alpha)):
z = i % key_len
un_cip[z] += cipher_alpha[i]
for i in range(key_len):
un_cip[i]= count_CI(un_cip[i])
aver_CI += un_cip[i]
aver_CI = aver_CI/len(un_cip)
return aver_CI
## 找出最可能的前十个秘钥长度
def pre_10(cipher):
M = [(1,count_CI(cipher))]+[(0,0.0) for i in range(49)]
for i in range(2,50):
M[i] = (i,abs(0.065 - count_key_len_CI(cipher,i)))
M = sorted(M,key = lambda x:x[1]) #按照数组第二个元素排序
for i in range(1,10):
print (M[i])
F = [
0.0651738, 0.0124248, 0.0217339,
0.0349835, 0.1041442, 0.0197881,
0.0158610, 0.0492888, 0.0558094,
0.0009033, 0.0050529, 0.0331490,
0.0202124, 0.0564513, 0.0596302,
0.0137645, 0.0008606, 0.0497563,
0.0515760, 0.0729357, 0.0225134,
0.0082903, 0.0171272, 0.0013692,
0.0145984, 0.0007836
] # 英文字符频率。
# 猜测单个秘钥得到的重合指数
def count_CI2(cipher,n): # n 代表我们猜测的秘钥,也即偏移量
N = [0.0 for i in range(26)]
cipher = c_alpha(cipher)
L = len(cipher)
for i in range(L): #计算所有字母的频数,存在数组N当中
if (cipher[i].islower()):
N[(ord(cipher[i]) - ord('a') - n)%26] += 1
else:
N[(ord(cipher[i]) - ord('A') - n)%26] += 1
CI_2 = 0
for i in range(26):
CI_2 += ((N[i] / L) * F[i])
return CI_2
def one_key(cipher,key_len):
un_cip = ['' for i in range(key_len)]
cipher_alpha = c_alpha(cipher)
for i in range(len(cipher_alpha)): # 完成分组工作
z = i % key_len
un_cip[z] += cipher_alpha[i]
for i in range(key_len):
print (i)
pre_5_key(un_cip[i]) ####这里应该将5个分组的秘钥猜测全部打印出来
## 找出前5个最可能的单个秘钥
def pre_5_key(cipher):
M = [(0,0.0) for i in range(26)]
for i in range(26):
M[i] = (chr(ord('a')+i),abs(0.065 - count_CI2(cipher,i)))
M = sorted(M,key = lambda x:x[1]) #按照数组第二个元素排序
for i in range(10):
print (M[i])
key_len = 8 #输入猜测的秘钥长度
fp = open("F:\CTF\CTF资料\i春秋\代码\Crypto\Vigenere\Vigenere.txt","r")
cipher = ''
for i in fp.readlines():
cipher = cipher + i
fp.close()
one_key(cipher,key_len)
破译密文
def decrypto (miwen,key):
mingwen = [0]*(len(miwen))
count = 0
for i in range (len(miwen)):
if(miwen[i].isalpha()):
if(miwen[i].isupper()):
offset1 = ord(key[(i-count)%len(key)])-ord('a')
mingwen[i] = chr(((ord(miwen[i])+ord('A'))-offset1)%26+ord('A'))
else:
offset2 = ord(key[(i-count)%len(key)])-ord('a')
mingwen[i] = chr(((ord(miwen[i])-ord('a'))-offset2)%26+ord('a'))
else:
mingwen[i]=miwen[i]
count = count + 1
return mingwen
fp = open("F:\CTF\CTF资料\i春秋\代码\Crypto\Vigenere\Vigenere.txt","r")
cipher = ''
for i in fp.readlines():
cipher = cipher + i
fp.close()
mingwen = decrypto(cipher,'asterism')
mingwen = [str(i) for i in mingwen]
mingwen = ''.join(mingwen)
print(mingwen)
网友评论