最近在看慕课上一套密码学的视频,觉得老师讲的挺好的,但是吧,讲的大部分全是理论性的知识,有点枯燥O(∩_∩)O哈哈~,就ctf比赛中的密码学知识而言,如果真的手算解题的话,似乎效率也太低了吧,So,我结合理论把某些题型的解题方法使用python实现了一下。这篇博客里面只涉及了一部分,后面的内容以后会更新上。
上面提到的密码学视频链接:https://www.icourse163.org/course/UESTC-1003046001
今天咱们主要看一下古典密码算法中的 “置换密码算法”以及 “代替密码算法”。首先得了解一下原理,然后再上python解题脚本。
1.置换密码介绍
替换密码是指先建立一个替换表,加密时将需要加密的明文依次通过查表,替换为相应的字符,明文字符被逐个替换后,生成无任何意义的字符串,即密文,替代密码的密钥就是其替换表 。
2.代替密码介绍
(1)单表代替密码
收:对就是这,下面是针对单表代换密码的python实现:
要不是我懒得每次做这种题目的时候都要把每个字符转为ASCII码,接着还要算各种差值,各种计算...
啊啊啊O(≧口≦)O头疼,我才不会写这个脚本本呢。脚本写的不够完善的地方还望见谅,小白我要走的路还很长啊。到时候要是有这种题型的话,就直接掏出来用就行了,代码长的一部分原因是为了更好的与我们进行交互,要是觉得冗杂的话,可以自己精简一下,要是有大佬简化了,可以放到评论区,一块学习啊^_^。
单表代替密码--加法密码实现:
(k=3时,就是标准的凯撒加密)
#!/usr/bin/python3
#coding:utf-8
#@Author:醉清风
def alphabet_1():
alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ' #做关于大写字母的代换表(0,1,2...分别对应A,B,..)
alphabet_dict={}
for i in range(0,26):
alphabet_dict[alphabet[i]]=i
return alphabet_dict
def alphabet_2():
alphabet='abcdefghijklmnopqrstuvwxyz' #做关于小写字母的代换表(0,1,2...分别对应a,b,..)
alphabet_dict={}
for i in range(0,26):
alphabet_dict[alphabet[i]]=i
return alphabet_dict
def run1(y,k): #根据x=y-k(mod26)得到对应的明文
m = ''
alphabet_dict = alphabet_1()
for i in y:
x = alphabet_dict[i] - k%26
if(x<0):
x = x + 26
m = m + chr(x+65)
print("k="+str(k)+":"+m)
def run2(y,k): #根据x=y-k(mod26)得到对应的明文
m = ''
alphabet_dict = alphabet_2()
for i in y:
x = alphabet_dict[i] - k%26
if(x<0):
x = x + 26
m = m + chr(x+97)
print("k="+str(k)+":"+m)
def main():
y = input("请输入要解密的内容:")
if(ord(y[0])<97): #判断输入的是大写还是小写
for k in range(0,26):
run1(y,k)
else:
for k in range(0,26):
run2(y,k)
if __name__=="__main__":
main()
单表代替密码--乘法密码实现:
#!/usr/bin/python3
#coding:utf-8
#@Author:醉清风
alphabet_dict={}
plain=[]
def alphabet1(k,y): #做k所有可能下的关于大写字母的字符代换表(明文:A,B,C..分别对应密文:A,J,S..)
pwd={}
for i in range(26):
alphabet_dict[chr(((k*i))%26+63)] = chr(i+63)
return alphabet_dict
def alphabet2(k,y): #做k所有可能下的关于小写字母的字符代换表(明文:a,b,c..分别对应密文:a,j,s..)
pwd={}
for i in range(26):
alphabet_dict[chr(((k*i))%26+97)] = chr(i+97)
return alphabet_dict
def run1(y,key): #从代换表中取回密文对应的明文
for k in key:
alphabet_dic = alphabet1(k,y)
for i in y:
plain.append(alphabet_dict[i])
tmp="".join(plain)
k=0
m=len(tmp)
n=int(len(tmp)/12)
for i in range(0,m,n):
print ("k="+str(key[k])+":")
print (tmp[i:i+n])
k=k+1
def run2(y,key): #从代换表中取回密文对应的明文
for k in key:
alphabet_dic = alphabet2(k,y)
for i in y:
plain.append(alphabet_dict[i])
tmp="".join(plain)
k=0
m=len(tmp)
n=int(len(tmp)/12)
for i in range(0,m,n):
print ("k="+str(key[k])+":")
print (tmp[i:i+n])
k=k+1
def main():
y = input("请输入密文:")
key = [1,3,5,7,9,11,15,17,19,21,23,25] #因为(k,26)=1,故取这些值
if(ord(y[0])<97): #判断输入的是大写还是小写
run1(y,key)
else:
run2(y,key)
if __name__=="__main__":
main()
脚本中提到key的取值只有12个,即满足(k,26)=1,也就是满足“小于且k与26互素,下面通过python2计算k可以取得值。
#!/usr/bin/python2
#coding:utf-8
#@Author:醉清风
def gcd(a,b): #判断来两个数是否互素,辗转相除法
if(b==0):
return a
else:
return gcd(b,a%b)
def main():
y = 26
for x in range(0,26):
if gcd(x,y)==1: #如果两个数的最大公约数是1,那么两数互素。
print x,y
if __name__=="__main__":
main()
单表代替密码--仿射密码实现:
#!/usr/bin/python3
#coding:utf-8
#@Author:醉清风
alphabet_dict={}
plain=[]
def run1(a,b):
pwd={}
for i in range(26): #做关于大写字母的代换表
alphabet_dict[chr(((a*i+b))%26+63)] = chr(i+63)
return alphabet_dict
def run2(a,b):
pwd={}
for i in range(26): #做关于小写字母的代换表
alphabet_dict[chr(((a*i+b))%26+97)] = chr(i+97)
return alphabet_dict
def main():
y = input("请输入密文:")
print("仿射密码格式:y=ax+b")
a = int(input("请输入a的值:"))
b = int(input("请输入b的值:"))
if(ord(y[0])<97):
alphabet_dict = run1(a,b)
else:
alphabet_dict = run2(a,b)
for i in y:
plain.append(alphabet_dict[i])
print("Flag is : "+"".join(plain))
if __name__=="__main__":
main()
(2)多表代替密码
改天再补上这个的python实现^_^。