密碼學:古典密碼算法

    最近在看慕課上一套密碼學的視頻,覺得老師講的挺好的,但是吧,講的大部分全是理論性的知識,有點枯燥O(∩_∩)O哈哈~,就ctf比賽中的密碼學知識而言,如果真的手算解題的話,似乎效率也太低了吧,So,我結合理論把某些題型的解題方法使用python實現了一下。這篇博客裏面只涉及了一部分,後面的內容以後會更新上。
    上面提到的密碼學視頻鏈接:https://www.icourse163.org/course/UESTC-1003046001
    今天咱們主要看一下古典密碼算法中的 “置換密碼算法”以及 “代替密碼算法”。首先得了解一下原理,然後再上python解題腳本。
00
1.置換密碼介紹
01
替換密碼是指先建立一個替換表,加密時將需要加密的明文依次通過查表,替換爲相應的字符,明文字符被逐個替換後,生成無任何意義的字符串,即密文,替代密碼的密鑰就是其替換表 。
02
03
04
2.代替密碼介紹
05
06
(1)單表代替密碼
07
08
09
收:對就是這,下面是針對單表代換密碼的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)多表代替密碼
10
11
12
13
14
改天再補上這個的python實現^_^。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章