最近在看慕課上一套密碼學的視頻,覺得老師講的挺好的,但是吧,講的大部分全是理論性的知識,有點枯燥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實現^_^。