项目使用python和tkinter实现,能够实现对明文/密文的加解密,或对文本进行base64、url编码/解码。
实现多种常见的ctf加密/解密(编码/解码)方法,选择相应加密/解密(编码/解码)算法后,输入明文/密文,可以给出结果。算法包括凯撒密码、仿射密码、维吉尼亚密码、RSA密码、base64编码、纵栏式移项密码、url编码。
理解常用的加密/解密(编码/解码)原理,用编程语言实现基本的算法功能,最后在实现图形化界面。
用python实现基本的算法功能。
用tkinter实现图形化。
# 实现图形化,用户的输入口
import tkinter as tk
import tkinter.messagebox
import CaeCode
import AffiCode
import VigCode
import RSACode
import Base64
import DisCode
import URL
def coChoose():
# 凯撒加密
if codeVar.get() == 0:
text = enText.get('1.0', tk.END)
text = text.strip()
key = enKey.get('1.0', tk.END)
key = key.strip()
prin = CaeCode.Cae(1, text, key)
buT.config(text=prin)
# 仿射加密
elif codeVar.get() == 1:
text = enText.get('1.0', tk.END)
text = text.strip()
a = enKey.get('1.0', '1.0 lineend')
a = a.strip()
b = enKey.get('2.0', '2.0 lineend')
b = b.strip()
prin = AffiCode.Aff(1, text, a, b)
buT.config(text=prin)
# 维吉尼亚加密
elif codeVar.get() == 2:
text = enText.get('1.0', tk.END)
text = text.strip()
key = enKey.get('1.0', tk.END)
key = key.strip()
prin = VigCode.Vig(1, text, key)
buT.config(text=prin)
# RSA加密
elif codeVar.get() == 3:
text = enText.get('1.0', tk.END)
text = text.strip()
p = enKey.get('1.0', '1.0 lineend')
p = p.strip()
q = enKey.get('2.0', '2.0 lineend')
q = q.strip()
e = enKey.get('3.0', '3.0 lineend')
e = e.strip()
prin = RSACode.RSA(1, text, p, q, e)
buT.config(text=prin)
# Base64编码
elif codeVar.get() == 4:
text = enText.get('1.0', tk.END)
text = text.strip()
prin = Base64.Base(1, text)
buT.config(text=prin)
# 纵栏式移项加密
elif codeVar.get() == 5:
text = enText.get('1.0', tk.END)
text = text.strip()
key = enKey.get('1.0', tk.END)
key = key.strip()
prin = DisCode.Dis(1, text, key)
buT.config(text=prin)
# url编码
elif codeVar.get() == 6:
text = enText.get('1.0', tk.END)
text = text.strip()
prin = URL.url(1, text)
buT.config(text=prin)
def deChoose():
# 凯撒解密
if codeVar.get() == 0:
text = enText.get('1.0', tk.END)
text = text.strip()
key = enKey.get('1.0', tk.END)
key = key.strip()
prin = CaeCode.Cae(2, text, key)
buT.config(text=prin)
# 仿射解密
elif codeVar.get() == 1:
text = enText.get('1.0', tk.END)
text = text.strip()
a = enKey.get('1.0', '1.0 lineend')
a = a.strip()
b = enKey.get('2.0', '2.0 lineend')
b = b.strip()
prin = AffiCode.Aff(2, text, a, b)
buT.config(text=prin)
# 维吉尼亚解密
elif codeVar.get() == 2:
text = enText.get('1.0', tk.END)
text = text.strip()
key = enKey.get('1.0', tk.END)
key = key.strip()
prin = VigCode.Vig(2, text, key)
buT.config(text=prin)
# RSA解密
elif codeVar.get() == 3:
text = enText.get('1.0', tk.END)
text = text.strip()
p = enKey.get('1.0', '1.0 lineend')
p = p.strip()
q = enKey.get('2.0', '2.0 lineend')
q = q.strip()
e = enKey.get('3.0', '3.0 lineend')
e = e.strip()
prin = RSACode.RSA(2, text, p, q, e)
buT.config(text=prin)
# Base64编码
elif codeVar.get() == 4:
text = enText.get('1.0', tk.END)
text = text.strip()
prin = Base64.Base(2, text)
buT.config(text=prin)
# 纵栏式移项解密
elif codeVar.get() == 5:
text = enText.get('1.0', tk.END)
text = text.strip()
key = enKey.get('1.0', tk.END)
key = key.strip()
prin = DisCode.Dis(2, text, key)
buT.config(text=prin)
# url解码
elif codeVar.get() == 6:
text = enText.get('1.0', tk.END)
text = text.strip()
prin = URL.url(2, text)
buT.config(text=prin)
def helpCommand():
tk.messagebox.showinfo('帮助(H)', '使用仿射密码时,密钥从上往下分别输入a,b\n'
+ '使用RSA密码时,从上往下分别为p,q,e')
# 主窗口及格式
window = tk.Tk()
window.title('加解密工具')
window.configure(background='White')
width = 800
height = 600
screenwidth = window.winfo_screenwidth()
screenheight = window.winfo_screenheight()
size_geo = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
window.geometry(size_geo)
window.resizable(width=False, height=False)
# 密码编码选项框架
coFrame = tk.Frame(window, bg='white')
coFrame.grid(padx=15, pady=10, row=0, column=0, rowspan=3)
codeVar = tk.IntVar()
code1 = tk.Radiobutton(coFrame, text="凯撒密码", bg='white', variable=codeVar, value=0)
code1.grid(ipadx=20, ipady=15, row=0, column=0)
code2 = tk.Radiobutton(coFrame, text="仿射密码", bg='white', variable=codeVar, value=1)
code2.grid(ipadx=20, ipady=15, row=1, column=0)
code3 = tk.Radiobutton(coFrame, text="维吉尼亚密码", bg='white', variable=codeVar, value=2)
code3.grid(ipadx=20, ipady=15, row=2, column=0)
code4 = tk.Radiobutton(coFrame, text="RSA密码", bg='white', variable=codeVar, value=3)
code4.grid(ipadx=20, ipady=15, row=3, column=0)
code5 = tk.Radiobutton(coFrame, text="Base64", bg='white', variable=codeVar, value=4)
code5.grid(ipadx=20, ipady=15, row=4, column=0)
code6 = tk.Radiobutton(coFrame, text="纵栏式移项密码", bg='white', variable=codeVar, value=5)
code6.grid(ipadx=20, ipady=15, row=5, column=0)
code7 = tk.Radiobutton(coFrame, text="url编码", bg='white', variable=codeVar, value=6)
code7.grid(ipadx=20, ipady=15, row=6, column=0)
# 输入输出框架
entry = tk.Frame(window, bg='white')
entry.grid(padx=15, pady=10, row=0, column=3)
enLabel = tk.Label(entry, text='请输入文本:', bg='white')
enLabel.grid(ipadx=20, ipady=15, row=0, column=0)
enText = tk.Text(entry, width=30, height=7)
enText.grid(ipadx=20, ipady=15, row=1, column=0)
enLabel = tk.Label(entry, text='请输入密钥:', bg='white')
enLabel.grid(ipadx=20, ipady=15, row=2, column=0)
enKey = tk.Text(entry, width=30, height=7)
enKey.grid(ipadx=20, ipady=15, row=3, column=0)
# 加密解密选项
edVar = tk.IntVar()
en = tk.Button(window, text='加密(编码)', bg='white', command=coChoose)
en.grid(padx=10, pady=5, row=0, column=4)
de = tk.Button(window, text='解密(解码)', bg='white', command=deChoose)
de.grid(padx=10, pady=5, row=1, column=4)
# 输出结果
buT = tk.Label(window, text='')
buT.grid(row=5, column=3)
# 菜单
mainmenu = tk.Menu(window)
mainmenu.add_command (label="文件")
mainmenu.add_command (label="编辑")
mainmenu.add_command (label="格式")
mainmenu.add_command (label="查看")
mainmenu.add_command (label="帮助",command=helpCommand)
# 显示菜单
window.config (menu=mainmenu)
window.mainloop()
# 实现凯撒密码
# 小写字典
lowDict = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
# 大写字典
capDict = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
# 将字母转换成数字
def switch(ele):
flag = 0
if ele.isalpha():
if ele in lowDict:
ele = lowDict.index(ele)
elif ele in capDict:
ele = capDict.index(ele)
flag = 1
return [int(ele), flag]
# beState 处理前 afState 处理后
# 加解密算法
def algo(choose, beState, key):
afState = ''
# key返回的flag值是没用的
[k, flag] = switch(key)
for i in beState:
[be, flag] = switch(i)
# 加密
if choose == 1:
af = (be + k) % 26
# 解密
if choose == 2:
af = (be - k) % 26
if flag == 0:
afState += lowDict[af]
else:
afState += capDict[af]
return afState
def Cae(choose, text, key):
# 加密
if choose == 1:
plai = text
return algo(choose, plai, key)
# 解密
elif choose == 2:
ciph = text
return algo(choose, ciph, key)
# 实现仿射密码
import math
# 小写字典
lowDict = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
# 大写字典
capDict = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
def switch(ele): # 将字母转换成数字
flag = 0
if ele.isalpha():
if ele in lowDict:
ele = lowDict.index(ele)
elif ele in capDict:
ele = capDict.index(ele)
flag = 1
return [int(ele), flag]
# beState 处理前 afState 处理后
def algo(choose, beState, a, b): # 加解密算法
afState = ''
[a, flag] = switch(a)
[b, flag] = switch(b)
if math.gcd(a, 26) != 1 or b < 0 or b >= 26: # 判断输入的密钥格式
print('你输入的密钥不符合算法格式')
return False
else:
for i in beState:
[be, flag] = switch(i)
# 加密
if choose == 1:
af = (a * be + b) % 26
# 解密
elif choose == 2:
inva = int(math.pow(a, 11))
af = inva * (be - b) % 26
if flag == 0:
afState += lowDict[af]
else:
afState += capDict[af]
return afState
def Aff(choose, text, a, b):
if choose == 1:
plai = text
ciph = algo(choose, plai, a, b)
if ciph is False:
return '你输入的密钥不符合算法格式(a应与26互素)'
else:
return ciph
elif choose == 2:
ciph = text
plai = algo(choose, ciph, a, b)
if plai is False:
return '你输入的密钥不符合算法格式(a应与26互素)'
else:
return plai
# 实现维吉尼亚密码
# 小写字典
lowDict = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
# 大写字典
capDict = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
# 将字母转换成数字
def switch(ele):
flag = 0
if ele in lowDict:
ele = lowDict.index(ele)
elif ele in capDict:
ele = capDict.index(ele)
flag = 1
return [int(ele), flag]
# beState 处理前 afState 处理后
# 加解密算法
def algo(choose, beState, key):
# 判断密钥格式
for i in key:
if not i.isalpha():
print('密钥格式应为英文字母')
return False
afState = ''
# 用来补齐key和遍历ciph
i = 0
# 用来遍历key
j = 0
# 补齐key
lenBeState = len(beState)
lenKey = len(key)
while lenKey < lenBeState:
key += key[i]
lenKey = len(key)
i += 1
# 加解密算法
for i in beState:
# 遍历key
[k, flag] = switch(key[j])
j += 1
[be, flag] = switch(i)
# 加密
if choose == 1:
af = (be + k) % 26
# 解密
elif choose == 2:
af = (be - k) % 26
if flag == 0:
afState += lowDict[af]
else:
afState += capDict[af]
return afState
# 主函数
def Vig(choose, text, key):
# 加密
if choose == 1:
plai = text
ciph = algo(choose, plai, key)
if ciph is False:
return '你输入的密钥不符合算法格式(密钥格式应为英文字母)'
else:
return ciph
# 解密
elif choose == 2:
ciph = text
plai = algo(choose, ciph, key)
if plai is False:
return '你输入的密钥不符合算法格式(密钥格式应为英文字母)'
else:
return plai
# 实现RSA密码
import math
# 判断是否为素数
def isPrime(num):
for i in range(2, num):
if num % i == 0:
return False
return True
def RSA(choose, text, p, q, e):
text = int(text)
p = int(p)
q = int(q)
e = int(e)
# 加密
if choose == 1:
if not isPrime(p):
return '你输入的p不是素数'
if not isPrime(q):
return '你输入的q不是素数'
n = p * q
phiN = (p - 1) * (q - 1)
# 判断e与φ(n)是否互素
if math.gcd(e, phiN) != 1:
falE = '你输入的e与φ(n)不互素\n' \
+ 'n = ' + str(n) + '\n' \
+ 'φ(n) = ' + str(phiN)
return falE
# 计算e的逆元d
k = 1
while (k * phiN + 1) % e != 0:
k += 1
d = int((k * phiN + 1) / e)
plai = text
ciph = pow(plai, e, n)
tru = 'n = ' + str(n) + '\n' \
+ 'φ(n) = ' + str(phiN) + '\n' \
+ 'd = ' + str(d) + '\n' \
+ '密文是' + str(ciph)
return tru
# 解密
elif choose == 2:
if not isPrime(p):
return '你输入的p不是素数'
if not isPrime(q):
return '你输入的q不是素数'
n = p * q
phiN = (p - 1) * (q - 1)
# 判断e与φ(n)是否互素
if math.gcd(e, phiN) != 1:
falE = '你输入的e与φ(n)不互素\n' \
+ 'n = ' + str(n) + '\n' \
+ 'φ(n) = ' + str(phiN)
return falE
# 计算e的逆元d
k = 1
while (k * phiN + 1) % e != 0:
k += 1
d = int((k * phiN + 1) / e)
ciph = text
plai = pow(ciph, d, n)
tru = 'n = ' + str(n) + '\n' \
+ 'φ(n) = ' + str(phiN) + '\n' \
+ 'd = ' + str(d) + '\n' \
+ '明文是' + str(plai)
return tru
# 实现Base64编码
# A - Z: 65 - 90 a - z: 97 - 122
# Base64索引表 + '='
Base64 = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '=']
def Base(choose, text):
if choose == 1:
tru = ''
# 二进制形式
binary = []
# 将文本转换成对应的ASCII编码,再转换成二进制位
for i in text:
num = ord(i)
# div: 除数 re: 余数 ele: 单个字母二进制元素
div = 1
ele = []
while div != 0:
div = num // 2
re = num % 2
num = div
ele.append(re)
# 单个字节补齐8位
while len(ele) < 8:
ele.append(0)
ele.reverse()
binary += ele
# 每3个字节补齐24位
while len(binary) % 24 != 0:
binary.append(0)
# 每6位二进制数为一个Base64编码索引
while binary != []:
flag = 0
num = ''
while flag < 6:
num += str(binary.pop(0))
flag += 1
index = int(num, 2)
# 判断全0索引是'A'还是'='
if index == 0 and 1 not in binary:
index = 64
tru += Base64[index]
tru += ''
return tru
# 解码
elif choose == 2:
tru = ''
coding = text
binary = []
for i in coding:
index = Base64.index(i)
if index != 64:
div = 1
ele = []
while div != 0:
div = index // 2
re = index % 2
index = div
ele.append(re)
# 单个字节补齐6位
while len(ele) < 6:
ele.append(0)
ele.reverse()
else:
ele = [0, 0, 0, 0, 0, 0]
binary += ele
while binary != []:
flag = 0
num = ''
while flag < 8:
num += str(binary.pop(0))
flag += 1
index = int(num, 2)
# 判断全0索引是'A'还是'='
if index == 0 and 1 not in binary:
break
tru += chr(index)
tru += ''
return tru
# 实现纵栏式移项密码
# 小写字典
lowDict = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
# 大写字典
capDict = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
# 将字母转换成数字
def switch(ele):
flag = 0
if ele in lowDict:
ele = lowDict.index(ele)
elif ele in capDict:
ele = capDict.index(ele)
flag = 1
return [int(ele), flag]
def Dis(choose, text, key):
dict = {}
lis = ''
text = list(text)
# 加密
if choose == 1:
while text != []:
for i in key:
[ele, flag] = switch(i)
# 添加字典
dict.setdefault(ele, '')
if text == []:
break
# 置换
else:
temp = dict[ele] + text.pop(0)
dict[ele] = temp
# 排序
while dict != {}:
minindex = min(dict.keys())
lis += dict[minindex]
dict.pop(minindex)
return lis
# 解密
elif choose == 2:
textNum = len(text)
keyNum = len(key)
# num用于计算每个数组的个数
num = textNum // keyNum
# re用于计算多余的字符
re = textNum % keyNum
while text != []:
for i in key:
[ele, flag] = switch(i)
dict.setdefault(ele, '')
# 置换
if re != 0:
dict[ele] = text[0:num+1]
re -= 1
for j in range(0, num+1):
text.pop(0)
else:
dict[ele] = text[0:num]
for j in range(0, num):
text.pop(0)
# 排序
tempList = sorted(dict.keys())
tempLen = len(tempList)
while tempLen > 0:
for i in tempList:
if dict[i] == []:
tempLen -= 1
elif dict[i] != []:
lis += dict[i][0]
dict[i] = dict[i][1:]
return lis
注:url解码部分有问题
# 实现url编码
# 保留字符的编码字典
endict = {'!': '%21', '#': '%23', '$': '%24', '&': '%26', "'": '%27', '(': '%28',
')': '%29', '*': '%2A', '+': '%2B', ',': '%2C', '/': '%2F', ':': '%3A',
';': '%3B', '=': '%3D', '?': '%3F', '@': '%40', '[': '%5B', ']': '%5D'}
# 反编码字典
dedict = {'21': '!', '23': '#', '24': '$', '26': '&', '27': "'", '28': '(',
'29': ')', '2A': '*', '2B': '+', '2C': ',', '2F': '/', '3A': ':',
'3B': ';', '3D': '=', '3F': '?', '40': '@', '5B': '[', '5D': ']'}
def url(choose, text):
list = ''
# 编码
if choose == 1:
for i in text:
word = i
if i in endict.keys():
word = endict[i]
list += word
return list
# 反编码
elif choose == 2:
text = text.split('%')
for i in text:
if i in dedict.keys():
list += dedict[i]
elif text.index(i) == 0:
list += i
else:
list += '%'
list += i
return list
GUI部分做得很烂,实现图形化是我的一生之敌。部分算法本来不需要做得很复杂,例如凯撒密码,但为了统一输入输出,就稍微改多了一点(也是为了蹭代码行数),url解码部分因为时间紧急,做得不是很好。