具体数学原理。。。我也没不太知道怎么解释。。。直接贴别人的理解也不太好,但是脚本写出来啦,就直接贴脚本咯~
import re, math
def openfile(fileName):
file = open(fileName,'r')
text = file.read()
file.close();
text = text.replace('\n','')
return text
def charOffset(char, offset):
if(offset < 0):
offset += 26
if char.islower():
return chr((ord(char) - 97 + offset) % 26 + 97)
else:
return chr((ord(char) - 65 + offset) % 26 + 65)
def Vigenere(strIn, key, encode):
strOut = ""
j = 0
for c in strIn:
if c.isalpha():
offset = ord(key[j % len(key)]) - 97
j += 1
if encode == False:
offset = -offset
strOut += charOffset(c, offset)
else:
strOut += c
return strOut
def deVigenereAuto(ciphertext):
best_key = ""
count = []
cipherMin = ciphertext.lower()
cipherMin = re.sub('[^a-z]', '', ciphertext.lower())
freq = [8.167, 1.492, 2.782, 4.253, 12.702, 2.228, 2.015, 6.094, 6.966, 0.153, 0.772, 4.025, 2.406, 6.749, 7.507, 1.929, 0.095, 5.987, 6.327, 9.056, 2.758, 0.978, 2.360, 0.150, 1.974, 0.074];
for best_len in range(3, 13):
sum = 0
for j in range(0, best_len):
for i in range(0, 26):
count.append(0)
i = j
while i < len(cipherMin):
count[ord(cipherMin[i]) - 97] += 1
i += best_len
ic = 0
num = len(cipherMin)/best_len
for i in range(0, len(count)):
ic += math.pow(count[i]/num, 2)
sum += ic
if sum/best_len > 0.065:
break
for j in range(0, best_len):
for i in range(0, 26):
count[i] = 0
i = j
while i < len(cipherMin):
count[ord(cipherMin[i]) - 97] += 1
i += best_len
max_dp = -1000000
best_i = 0
for i in range(0, 26):
cur_dp = 0.0
for k in range(0, 26):
cur_dp += freq[k] * count[(k + i) % 26]
if cur_dp > max_dp:
max_dp = cur_dp
best_i = i
best_key += chr(best_i + 97)
print "best_key : " + best_key
print "plaintext : " + Vigenere(ciphertext, best_key, False)
if __name__ == '__main__':
ciphertext = openfile('ciphertext2.txt')
a = raw_input("did you have key?(Y/N)")
a = a.upper()
if a == 'N':
deVigenereAuto(ciphertext)
if a == 'Y':
key = raw_input("key?")
print "plaintext : " + Vigenere(ciphertext, key, False)