# -*- coding: utf-8 -*-
"""
"""
# !/usr/bin/env python
import string
import pprint
a_z = string.ascii_lowercase
A_Z = string.ascii_uppercase
# 生成维吉尼亚表
def produce(location):
s = ""
s += A_Z[location:] + A_Z[0:location]
return s
def produce_table():
dic = {}
for i in range(0, 26):
dic[a_z[i]] = produce(i)
return dic
# 生成表
table = produce_table()
#pprint.pprint(table)
def filter_claer(clear):
result = ""
clear = clear.lower()
for i in clear:
if 97 <= ord(i) <= 122:
result += i
return result
# 加密
def encrypt(clear_content, key):
clear_content = get_trim_text(clear_content)
result = ""
length = len(key)
loca = 0
for i in clear_content:
result += table[i][a_z.index(key[loca])] # table[i]代表明文字符所在列,a_z[index](key[loca])表示秘钥字符
loca += 1
loca = loca % length
return result.lower()
#解密
def decrypt(cipher, key):
result = ""
length = len(key)
loca = 0
for i in cipher.upper():
result += a_z[table[key[loca]].index(i)]
# table[key[loca]]表示秘钥字符串所在行,index(i)表示明文字符的索引,查找a_z
loca += 1
loca = loca % length
return result
def get_trim_text(text):
result = ""
clear = text.lower()
for i in clear:
if 97 <= ord(i) <= 122:
result += i
return result
# 求秘钥长度
def get_key_length(text):
length = len(text)
List_word_chance = {}
for m in range(1, 18):
List_avgCipher = []
for time in range(0, m):
temp = text[time::m]
List_avgCipher.append(temp)
# print(List_avgCipher)
lis = []
for i in List_avgCipher:
all_word = set(i)
chance = 0
for j in all_word:
chance += i.count(j) * (i.count(j) - 1)
lis.append(chance / ((len(i) * len(i) - 1)))
List_word_chance[m] = sum(lis) / m
result = []
for i, v in List_word_chance.items():
result.append([i, v, abs(v - 0.065)])
result = sorted(result, key=lambda s: s[2])
return result
# 获取密钥长度
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 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(float(count) / len(lis))
return li
# 根据密钥长度将密文分组
def textToList(text, length):
text = get_trim_text(text)
textMatrix = []
row = []
index = 0
for ch in text:
row.append(ch)
index += 1
if index % length == 0:
textMatrix.append(row)
row = []
textMatrix.append(row)
return textMatrix
# 获取密钥
def getKey(text, length):
text = get_trim_text(text)
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 if len(row) > i] # 获取每组密文
if length == 6 and i == 0:
print('**********************************')
print(w)
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] # 循环移位
if length == 6 and i == 0:
print('**********************************')
print(powLi)
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
if __name__ == '__main__':
prompt = """选择
(e)加密
(d)解密
(c)爆破
(q)退出
请输入你的选择:
"""
while (True):
choice = input(prompt)
if choice == 'e':
p = input("请输入明文 ")
k = input("输入加密秘钥 ")
print("密文为: %s" % (encrypt(p, k)))
elif choice == 'd':
c = input("请输入密文: ")
k = input("请输入解密秘钥: ")
print("明文为: %s" % (decrypt(c, k)))
elif choice == 'q':
break
elif choice == 'c':
key_lengths = []
c = input("please enter ciphertext: ")
key_lengths = getKeyLen(c)
print("使用Kasiski得到的秘钥长度为:" + str(key_lengths))
print("使用重合指数得到的分组概率从大到小为\n"
"[分组数,平均重合指数,绝对值(平均-0.065]\n")
key_lengths_chonghe = get_key_length(c)
for i in key_lengths_chonghe:
print(i)
if key_lengths_chonghe[0][0]==key_lengths:
print("秘钥长度为%d"%key_lengths)
key = ""
for i in getKey(c, key_lengths_chonghe[0][0]):
key += i
print("明文是 %s,\n 密钥是 %s\n" \
% (decrypt(c, key), key))
else:
print("尝试前面3组秘钥长度:")
for j in range(0,3):
key = ""
for i in getKey(c, key_lengths_chonghe[j][0]):
key += i
print("明文是 %s,\n 密钥是 %s\n" \
% (decrypt(c, key), key))
else:
print("不合理的输入,请重新输入")