密码学:古典密码算法

    最近在看慕课上一套密码学的视频,觉得老师讲的挺好的,但是吧,讲的大部分全是理论性的知识,有点枯燥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实现^_^。

猜你喜欢

转载自blog.51cto.com/13400543/2413156