Python实现Vigenère密码无密钥自动解密详解
本文详细介绍使用Python实现Vigenère(维吉尼亚)密码无密钥解密的全过程。内容涵盖通过重复间隔统计法确定密钥长度,利用重合指数法(Index of Coincidence)破解具体密钥字符,以及最终还原明文。代码包含获取密钥长度、分组统计及完整解密函数,适用于密码学学习与算法实践。
本文分享一段使用Python编写的Vigenère(维吉尼亚)密码无密钥解密示例代码,供读者参考学习。
Vigenère加密原理与Python实现
加密部分
Vigenère加密属于多表替换加密算法,其核心优势在于能有效抵御针对单表替换加密的字母频率分析攻击。该算法的安全性高度依赖于密钥的选择与保密,一旦密钥泄露,加密即失效。基于Vigenère加密原理,下文提供Python实现代码。
plainText = "whenigotthethemeithoughtofgooglesartificialintelligencealphagothisprogramoverthebestofhumanplayeriwanttoaskwhenscienceandtechnologycontinuetodevelopwehumanbeingswillbewhatpositionweshouldrealizethatthedevelopmentofscienceandtechnologyisirreversibleanditconstituteaprimaryprductiveforcebutmanmustkeeppacewiththetimestoenhancetheablitytocontrol" # 密文
alphabet = "abcdefghijklmnopqrstuvwxyz" # 26个字母
cipherText = "";
key = "helloworld" # 密钥
keyLen = len(key)
plainTextLen = len(plainText)
j = 0
for i in range(0,plainTextLen):
j = i%keyLen
keyNum = alphabet.index(key[j])
plainNum = alphabet.index(plainText[i])
plainTemp = alphabet[(keyNum*plainNum)%26] # 密钥对明文作用
cipherText += plainTemp
print(cipherText)
Vigenère密码解密核心步骤
解密部分
解密过程主要包含三个关键步骤:首先确定密钥长度,其次根据密钥长度推导密钥内容,最后利用密钥还原明文。
密钥长度的暴力破解方法
确定密钥长度
采用暴力破解法确定密钥长度,即遍历所有可能的密钥长度值。在每次循环中,统计密文中相隔距离等于当前假设密钥长度的重复字符对数量。理论上,重复次数最多的长度即为真实密钥长度的概率最高,尤其在密文足够长时,该结论更为可靠。以下是获取密钥长度的Python函数代码:
def getKeyLen(cipherText): # 获取密钥长度
keylength = 1
maxCount = 0
for step in range(3,18): # 循环密钥长度
count = 0
for i in range(step,len(cipherText)-step):
if cipherText[i] == cipherText[i+step]:
count += 1
if count>maxCount: # 每次保存最大次数的密钥长度
maxCount = count
keylength = step
return keylength # 返回密钥长度
基于重合指数法的密钥推导
确定密钥内容
在已知密钥长度的基础上,将密文按密钥长度进行分组,每组内的字符均由同一个密钥字符加密,因此每组内部表现为单表替换加密。针对每组密文,利用重合指数法(Index of Coincidence)来破解对应的密钥字符。以下是获取密钥的Python函数代码:
def getKey(text,length): # 获取密钥
key = [] # 定义空白列表用来存密钥
alphaRate =[0.08167,0.01492,0.02782,0.04253,0.12705,0.02228,0.02015,0.06094,0.06996,0.00153,0.00772,0.04025,0.02406,0.06749,0.07507,0.01929,0.0009,0.05987,0.06327,0.09056,0.02758,0.00978,0.02360,0.0015,0.01974,0.00074]
matrix =textToList(text,length)
for i in range(length):
w = [row[i] for row in matrix] #获取每组密文
li = countList(w)
powLi = [] #算乘积
for j in range(26):
Sum = 0.0
for k in range(26):
Sum += alphaRate[k]*li[k]
powLi.append(Sum)
li = li[1:]+li[:1]#循环移位
Abs = 100
ch = ''
for j in range(len(powLi)):
if abs(powLi[j] -0.065546)<Abs: # 找出最接近英文字母重合指数的项
Abs = abs(powLi[j] -0.065546) # 保存最接近的距离,作为下次比较的基准
ch = chr(j+97)
key.append(ch)
return key
明文还原与完整代码示例
还原明文
在已知密钥和密文的情况下,通过逆向运算即可轻松还原明文。以下是Python解密代码:
def virginiaCrack(cipherText): # 解密函数
length = getKeyLen(cipherText) #得到密钥长度
key = getKey(cipherText,length) #找到密钥
keyStr = ''
for k in key:
keyStr+=k
print('the Key is:',keyStr)
plainText = ''
index = 0
for ch in cipherText:
c = chr((ord(ch)-ord(key[index%length]))%26+97)
plainText += c
index+=1
return plainText # 返回明文
完整代码
上述为解密部分的完整代码。请注意,运行前需自行指定密文文件的路径。
def virginiaCrack(cipherText): # 解密函数
length = getKeyLen(cipherText) #得到密钥长度
key = getKey(cipherText,length) #找到密钥
keyStr = ''
for k in key:
keyStr+=k
print('the key:',keyStr)
plainText = ''
index = 0
for ch in cipherText:
c = chr((ord(ch)-ord(key[index%length]))%26+97)
plainText += c
index+=1
return plainText
def openfile(fileName): # 读文件
file = open(fileName,'r')
text = file.read()
file.close();
text = text.replace('\n','')
return text
def getKeyLen(cipherText): # 获取密钥长度
keylength = 1
maxCount = 0
for step in range(3,18): # 循环密钥长度
count = 0
for i in range(step,len(cipherText)-step):
if cipherText[i] == cipherText[i+step]:
count += 1
if count>maxCount:
maxCount = count
keylength = step
return keylength
def getKey(text,length): # 获取密钥
key = [] # 定义空白列表用来存密钥
alphaRate =[0.08167,0.01492,0.02782,0.04253,0.12705,0.02228,0.02015,0.06094,0.06996,0.00153,0.00772,0.04025,0.02406,0.06749,0.07507,0.01929,0.0009,0.05987,0.06327,0.09056,0.02758,0.00978,0.02360,0.0015,0.01974,0.00074]
matrix =textToList(text,length)
for i in range(length):
w = [row[i] for row in matrix] #获取每组密文
li = countList(w)
powLi = [] #算乘积
for j in range(26):
Sum = 0.0
for k in range(26):
Sum += alphaRate[k]*li[k]
powLi.append(Sum)
li = li[1:]+li[:1]#循环移位
Abs = 100
ch = ''
for j in range(len(powLi)):
if abs(powLi[j] -0.065546)<Abs: # 找出最接近英文字母重合指数的项
Abs = abs(powLi[j] -0.065546) # 保存最接近的距离,作为下次比较的基准
ch = chr(j+97)
key.append(ch)
return key
def countList(lis): # 统计字母频度
li = []
alphabet = [chr(i) for i in range(97,123)]
for c in alphabet:
count = 0
for ch in lis:
if ch == c:
count+=1
li.append(count/len(lis))
return li
def textToList(text,length): # 根据密钥长度将密文分组
textMatrix = []
row = []
index = 0
for ch in text:
row.append(ch)
index += 1
if index % length ==0:
textMatrix.append(row)
row = []
return textMatrix
if __name__ == '__main__':
cipherText = openfile(r'') # 这里要根据文档目录的不同而改变
plainText= virginiaCrack(cipherText)
print('the plainText:\n',plainText)
以上就是本文的全部内容,希望对读者的学习有所帮助,欢迎继续支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









