几种古典密码代码实现

最近在备考软考信息安全工程师,学习到密码学部分,为了记忆更加深刻,将已经掌握并且觉得比较有趣的密码算法用Python来实现,简单记录一下。

古典密码接触到置换密码、代替密码和代数密码三种,其中置换密码相对简单,靠眼睛就可以完成加解密,所以没有必要实现了,代替密码主要有加法密码、乘法密码和仿射密码,仿射密码研究的是Vigenre密码,该密码是16世纪法国密码学家Vigenre使用过的密码,代数密码研究的是Vernam密码,该密码是美国电话电报公司的Gillbert Vernam在1917年为电报通信设计的一种非常方便的密码(我最喜欢这组密码)。

加法密码

# coding:utf-8
# 加法密码实现
# 当前仅支持大写字符串加解密
# 秋风木叶 2019-3-10

# 字符串转单字符列表,再转为数字序列便于计算
def stoc(str):
    ch_list = []
    for i in str:
        ch_list.append(i) 
    return [ord(i)-65 for i in ch_list]

# Int to Chr
# 将数字序列还原成大写字母序列
def itoc(list_int):
    A = [chr(i+65) for i in list_int]
    ch = ""
    for i in A:
        ch += i
    return ch

# 计算密文序列
def Encrypt(Message,k,n):
    print('>>>使用加法密码算法进行加密(k={}, n={})'.format(k,n))
    return itoc([i+k%n for i in stoc(Message)])

# 计算明文序列
def Decrypt(Ciphertext,k,n):
    # 解密方式1:通过构建密码表进行查表解密
    # 解密方式2:通过加密逆运算计算明文
    DecryptionType = 2
    if(DecryptionType == 1):
        print('>>>构建密码表:')
        A = [i for i in range(0,n)]
        print('>>>明文字母表:{}'.format(itoc(A)))
        B = Encrypt(itoc(A),k,n)
        print('>>>密文字母表:{}'.format(B))
        CiphertextTables = dict(zip(B,A))
        print('>>>构建密码表进行查表解密')
        return itoc([CiphertextTables[i] for i in Ciphertext])
    else:
        print('>>>通过加密逆运算进行解密(k的逆元为:{})'.format(-k))
        return itoc([c-k+n %n for c in stoc(Ciphertext)])

if __name__=='__main__':
    # 当前仅支持大写字母串
    A = ('ABCDEF')
    print('输入的明文字符串为:{}'.format(A))
    B = Encrypt(A,7,26)
    print('加密后的密文:{}'.format(B))
    C = Decrypt(B,7,26)
    print('解密后的明文:{}'.format(C))

以上代码的执行结果:

输入的明文字符串为:ABCDEF
>>>使用加法密码算法进行加密(k=7, n=26)
加密后的密文:HIJKLM
>>>通过加密逆运算进行解密(k的逆元为:-7)
解密后的明文:ABCDEF

加法密码比较简单,加解密过程既可以通过公式计算实现,也可以使用查表的方式获得,代码中解密过程就分别使用了加密逆运算和查表两种思路来实现。

乘法密码

# coding:utf-8
# 乘法密码计算实现代码
# 当前仅支持大写字符串加解密,参数k和n必须互质整数
# 秋风木叶 2019-3-9

# 字符串转单字符列表,再转为数字序列便于计算
def stoc(str):
    ch_list = []
    for i in str:
        ch_list.append(i) 
    return [ord(i)-65 for i in ch_list]

# Int to Chr
# 将数字序列还原成大写字母序列
def itoc(list_int):
    A = [chr(i+65) for i in list_int]
    ch = ""
    for i in A:
        ch += i
    return ch

# 计算密文序列
def Encrypt(Message,k,n):
    print('>>>使用乘法密码算法进行加密(k={}, n={})'.format(k,n))
    return itoc([i*k%n for i in stoc(Message)])

# 计算明文序列
def Decrypt(Ciphertext,k,n):
    # 解密方式1:通过构建密码表进行查表解密
    # 解密方式2:通过加密逆运算计算明文
    DecryptionType = 2
    if(DecryptionType == 1):
        print('>>>构建密码表:')
        A = [i for i in range(0,n)]
        print('>>>明文字母表:{}'.format(itoc(A)))
        B = Encrypt(itoc(A),k,n)
        print('>>>密文字母表:{}'.format(B))
        CiphertextTables = dict(zip(B,A))
        print('>>>构建密码表进行查表解密')
        return itoc([CiphertextTables[i] for i in Ciphertext])
    else:
        for k1 in range(0, n):
            if(k1 * k % n == 1):
                break
        print('>>>通过加密逆运算进行解密(k的逆元为:{})'.format(k1))
        return itoc([c*k1%n for c in stoc(Ciphertext)])

if __name__=='__main__':
    # 当前仅支持大写字母串
    A = ('ABCDEF')
    print('输入的明文字符串为:{}'.format(A))
    B = Encrypt(A,7,26)
    print('加密后的密文:{}'.format(B))
    C = Decrypt(B,7,26)
    print('解密后的明文:{}'.format(C))

以上代码的执行结果:

输入的明文字符串为:ABCDEF
>>>使用乘法密码算法进行加密(k=7, n=26)
加密后的密文:AHOVCJ
>>>通过加密逆运算进行解密(k的逆元为:15)
解密后的明文:ABCDEF

乘法密码要求k和n互质,否则不能正确求解,代码整体结构跟加法密码相同,区别在于核心算法更加复杂。

仿射密码之Vigenre密码

仿射密码用到多个密文字母表,也成为多表代替密码。
最著名的多表代替密码要算16世纪法国学者Vigenre使用过的Vigenre密码,我也正是通过Vigenre密码来学习仿射密码的。

# coding:utf-8
# Vigenre密码实现代码
# 当前仅支持大写字符串加解密
# 秋风木叶 2019-3-10

# 字符串转单字符列表
def stoc(str):
    ch_list = []
    for i in str:
        i = i.strip()
        if(i != ''):
            ch_list.append(i) 
    return [i for i in ch_list]

# 字符列表转换为字符串
def ctoc(list_ch):
    ch = ""
    for i in list_ch:
        ch += i
    return ch

# 构建密码字典
def GetM_C():
    A = []
    B = []
    C = []
    for i in range(0,26):
        A.append(chr(i+65))
        B.append([chr(i+65)])
        for j in range(1,26):
            B[i].append((chr((i+j)%26+65)))
    for i in A:
        C.append(dict(zip(A,B[ord(i)-65])))
    return C

# 计算密文序列
def Encrypt(Message,K):
    M_C = GetM_C()
    C = ''
    for i,k in zip(stoc(Message),stoc(K)):
        #print(i,k)
        C += M_C[ord(i)-65][k]
    print('>>>使用Vigenre密码算法进行加密')
    return C

# 通过查密码表计算明文序列
def Decrypt(Ciphertext,K):
    M_C = GetM_C()
    M = ''
    for c,k in zip(stoc(Ciphertext),stoc(K)):
        M_Dict = M_C[ord(k)-65]
        #print(M_Dict)
        for m in M_Dict.keys():
            if(M_Dict[m] == c):
                M += m
                #print(m)
    print('>>>使用Vigenre密码算法进行解密')
    return M

if __name__=='__main__':
    # 当前仅支持大写字母串
    M = ('MING CHEN WU DIAN FA DONG FAN GONG')
    K = ('XING CHUI PING YE KUO YUE YONG DA JIANG LIU')
    print('输入的明文字符串为:{}'.format(M))
    print('输入的密钥字符串为:{}'.format(K))
    C = Encrypt(M, K)
    print('加密后的密文:{}'.format(C))
    M1 = Decrypt(C, K)
    print('解密后的明文:{}'.format(M1))

以上代码的执行效果:

输入的明文字符串为:MING CHEN WU DIAN FA DONG FAN GONG
输入的密钥字符串为:XING CHUI PING YE KUO YUE YONG DA JIANG LIU
>>>使用Vigenre密码算法进行加密
加密后的密文:JQAMEOYVLCQOYRPURMHKDOAMRNP
>>>使用Vigenre密码算法进行解密
解密后的明文:MINGCHENWUDIANFADONGFANGONG

暂时仅通过构建密码表的方式来实现,加解密都通过查表来进行,密文和明文长度相等,密钥尤为关键,密钥长度必须大于明文,否则多出来的明文无法加密,同样如果密钥长度小于密文长度部分密文也无法解密。

代数密码之Vernam密码

Vernam密码可谓是截至目前我觉得最有意思的密码了,它通过对二进制序列的异或运算来实现加解密,真是太神奇了,花时间用python对它进行了实现,虽然这组密码的代码实现和前几组一样都是我自己花时间敲出来的,但是跟上面三种密码的实现相比,我觉得这组密码要更加高明一些。

# coding:utf-8
# 代数密码(Vernam)实现代码
# 当前仅支持大写字符串加解密
# 秋风木叶 2019-3-11

# 字符转二进制
def CtoB(ch):
    OrdCh = ord(ch)
    BinarySequence = ''
    while(True):
        if(OrdCh % 2 == 0):
            BinarySequence += '0'
        else:
            BinarySequence += '1'
        OrdCh = OrdCh // 2
        if(OrdCh == 1):
            break
        #print(OrdCh,BinarySequence)
    BinarySequence += '1'
    # 补齐8位
    length = 8 - len(BinarySequence)
    while(length):
        BinarySequence += '0'
        length -= 1
    #print('BinarySequence:{}'.format(BinarySequence))
    return BinarySequence[::-1]

# 二进制转字符
def BtoC(Bin):
    St = ''
    OrdCh = 0
    length = 8
    for i in Bin:
        length -= 1
        OrdCh += (ord(i)-ord('0'))*(2**length)
        #print(length,i,OrdCh)
        if(length == 0):
            St += chr(OrdCh)
            length = 8
            OrdCh = 0
    return St

# 核心算法:二进制异或运算(加解密通用)
def Execute_Unit(m_c, k):
    result_unit = ''
    for i,j in zip(m_c, k):
        #print(i,j)
        if(i == j):
            result_unit += '0'
        else:
            result_unit += '1'
    #print('result_unit:{}'.format(result_unit))
    return result_unit

# 调用Vernam算法进行加密
def Encrypt(Message,K):
    print('>>>调用Vernam算法进行加密')
    result = ''
    for m,k in zip(Message, K):
        result += Execute_Unit(CtoB(m),CtoB(k))
    return result

# 调用Vernam算法进行解密
def Decrypt(Ciphertext,K):
    print('>>>调用Vernam算法进行解密')
    # Bk存放二进制K值序列
    BK = ''
    for k in K:
        BK += CtoB(k)
    # BM存放二进制明文序列
    BM = Execute_Unit(Ciphertext, BK[:len(Ciphertext)])
    print('>>>二进制密钥序列:{}'.format(BK))
    print('>>>二进制明文序列:{}'.format(BM))
    return BtoC(BM)

if __name__=='__main__':
    # 当前仅支持大写字母串
    M = ('MING CHEN WU DIAN FA DONG FAN GONG')
    K = ('XING CHUI PING YE KUO YUE YONG DA JIANG LIU')
    print('输入的明文字符串为:{}'.format(M))
    print('输入的密钥字符串为:{}'.format(K))
    C = Encrypt(M, K)
    print('加密后的密文:{}'.format(C))
    M1 = Decrypt(C, K)
    print('解密后的明文:{}'.format(M1))

代码的运行效果如下:

输入的明文字符串为:MING CHEN WU DIAN FA DONG FAN GONG
输入的密钥字符串为:XING CHUI PING YE KUO YUE YONG DA JIANG LIU
>>>调用Vernam算法进行加密
加密后的密文:00010101000000000000000000000000000000000000000000000000000100000000011100000000000001110001110001101110000000110110100100011000000010110000000000001101000101000110111101100100000101100001101100000010000000000001111100001110000000000110011101100111000010110000111101100111
>>>调用Vernam算法进行解密
>>>二进制密钥序列: 01011000010010010100111001000111001000000100001101001000010101010100100100100000010100000100100101001110010001110010000001011001010001010010000001001011010101010100111100100000010110010101010101000101001000000101100101001111010011100100011100100000010001000100000100100000010010100100100101000001010011100100011100100000010011000100100101010101
>>>二进制明文序列: 01001101010010010100111001000111001000000100001101001000010001010100111000100000010101110101010100100000010001000100100101000001010011100010000001000110010000010010000001000100010011110100111001000111001000000100011001000001010011100010000001000111010011110100111001000111
解密后的明文:MING CHEN WU DIAN FA DONG FAN GONG

作者:秋风木叶(frank1901s)
email: [email protected]
原文地址:https://tacgib.club/archives/276
不足之处望多多不吝赐教,转载请注明出处并告知作者,谢谢!

你可能感兴趣的:(算法)