python实现维吉尼亚加密解密以及利用拟重合指数法爆破

# -*- 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(“不合理的输入,请重新输入”)

    原文作者:维吉尼亚加密问题
    原文地址: https://blog.csdn.net/RememberMePlease/article/details/79701967
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞