美文网首页
简化版的DES加密Python实现

简化版的DES加密Python实现

作者: redexpress | 来源:发表于2018-03-03 08:23 被阅读503次

    简化版的DES(S-DES,https://en.wikipedia.org/wiki/Data_Encryption_Standard#Simplified_DES)是用来是用来教学的加密算法,可为理解DES、AES等加密算法打下基础。

    本文通过Python实现S-DES加密算法。
    在写程序的时候为了和资料上的函数名称一致,便于理解,有些函数、变量的命名不是很符合编程规范,也没有异常处理,主要用来加深理解S-DES算法。

    算法说明

    简化版DES(S-DES)的过程图示


    S-DES加解密图示

    加密过程


    S-DES加密
    简书书写公式不方便,上述公式用字符表示如下

    秘文 = IPinv(fK(SW(fK(IP(明文)))))

    设计

    输入

    1. 等待加密的文字,以十六进制字符串输入
    2. 10位秘钥,以列表输入

    输出

    加密的字符,以十六进制字符表示

    接口设计

    # 加密
    ciphertext = sdesEncrypt('59616e67', [0,1,0,1,1,1,1,1,0,1])
    # 解密
    plaintext = sdesDecrypt(ciphertext, [0,1,0,1,1,1,1,1,0,1])
    

    实现

    秘钥(key)变换

    S-DES需要一个10位(bit)的秘钥。每位表述为k1,k2,k3,k4,k5,k6,k7,k8,k9,k10。
    用到Shift、P10和P8三个函数

    P10:对10位秘钥重排
    P8:选取其中8位排列
    Shift:循环左移1位

    P10函数如下
    P10(k1,k2,k3,k4,k5,k6,k7,k8,k9,k10) = (k3,k5,k2,k7,k4,k10,k1,k9,k8,k6)

    P10函数实现

    def P10(key):
        k = [None] + key
        return [k[3],k[5],k[2],k[7],k[4],k[10],k[1],k[9],k[8],k[6]]
    

    编程语言的列表索引是从0开始,这里表述行位操作时,索引0存放无用值None,仅仅作占位用。从索引1开始存放数据。比如4位二进制1011存放到在长度为5的列表[None, 1, 0, 1, 1]中。这样的好处是代码的位索引和文本说明次序一致,后面代码有类似思路。

    P8和Shift函数的实现

    def P8(key):
        k = [None] + key
        return [k[6],k[3],k[7],k[4],k[8],k[5],k[10],k[9]]
    
    def Shift(value):
        return value[1:] + value[0:1]
    

    S-DES 加解密1个字节

    IP和 IPinv 函数

    IP和IPinv互相为反函数,即:IPinv(IP(X)) = X,IP(IPinv(X)) = X

    def IP(value):
        v = [None] + value
        return [k[2],k[6],k[3],k[1],k[4],k[8],k[5],k[7]]
    
    def IPinv(value):
        v = [None] + value
        return [k[4],k[1],k[3],k[5],k[7],k[2],k[8],k[6]]
    

    SW 函数

    SW函数交换左边和右边的4位

    def SW(value):
        return value[4:] + value[:4]
    

    fK函数

    fK操作8位二进制,最左边的4位记作L,最右边的4位记作作R,表示如下

    fK(L,R) = (L⊕F(R,K), R)

    ⊕是异或运算
    K表示子秘钥K1或者K2
    F函数是新引入的函数,可通过下面的两个步骤求出:

    1. 创建一个2行4列的表格P
      对输入的4的位数字(n1,n2,n3,n4)
      对输入K(k11,k12,k13,k14,k15,k16,k17,k18)
      表格P的值如下
    P(0,0) = n4 ⊕ k11 P(0,1) = n1 ⊕ k12 P(0,2) = n2 ⊕ k13 P(0,3) = n3 ⊕ n14
    P(1,0) = n2 ⊕ k15 P(1,1) = n3 ⊕ k16 P(1,2) = n4 ⊕ k17 P(1,3) = n1 ⊕ k18
    1. 在盒中查找

    有两个盒子S0和S1,值如下

    S0 = [[1, 0, 3, 2],
         [3, 2, 1, 0],
         [0, 2, 1, 3],
         [3, 1, 3, 2]]
    
    S1 = [[0, 1, 2, 3],
         [2, 0, 1, 3],
         [3, 0, 1, 0],
         [2, 1, 0, 3]]
    

    P(0,0)和P(0,1)组合成二进制的值row0,比如P(0,0) = 1, P(0,1) = 0,则row0 = 二进制10 = 2

    P(0,2)和P(0,3)组合成二进制的值col0

    P(1,0)和P(1,1)组合成二进制的值row1

    P(1,2)和P(1,3)组合成二进制的值col1

    S0的第row0行col0列的值S0(row0,col0)表示成两位二进制v1,v2,类似地S1(row1,col1)表示成两位二进制v3,v4

    (v2,v4,v3,v1)组合成的二进制的值便是F函数的值

    fK函数和F函数实现

    def F(value, key):
        val = lambda x, y: x * 2 + y
        highLow = lambda x: (1 if x & 0b10 > 0 else 0), (x & 0b01)
        P = [[0, 0, 0, 0],
             [0, 0, 0, 0]]
        n = [None] + value
        k = [None] * 11 + key  # 这里前面空11无用的值None
        P[0][0] = n[4] ^ k[11]
        P[0][1] = n[1] ^ k[12]
        P[0][2] = n[2] ^ k[13]
        P[0][3] = n[3] ^ k[14]
        P[1][0] = n[2] ^ k[15]
        P[1][1] = n[3] ^ k[16]
        P[1][2] = n[4] ^ k[17]
        P[1][3] = n[1] ^ k[18]
        row0 = val(P[0][0], P[0][1])
        col0 = val(P[0][2], P[0][3])
        row1 = val(P[1][0], P[1][1])
        col1 = val(P[1][2], P[1][3])
        v1, v2 = highLow(S0[row0][col0])
        v3, v4 = highLow(S1[row1][col1])
        return [v2, v4, v3, v1]
    
    def fK(value, key):
        L = value[:4]
        R = value[4:]
        return list(map(lambda x:x[0]^x[1], zip(L, F(R))) + R
    

    加密单字节函数 sdesEncryptByte
    用上文出现过的公式:秘文 = IPinv(fK(SW(fK(IP(明文)))))
    代码实现

    def sdesEncryptByte(value, key):
        K1 = P8(Shift(P10(key)))
        K2 = P8(Shift(Shift(P10(key))))
        fK1Value = fK(IP(value), K1)
        swValue = SW(fK1Value)
        fK2Value = fK(swValue, K2)
        return IPinv(fK2Value)
    

    解密单字节函数 sdesDecryptByte
    代码实现

    def sdesDecryptByte(value, key):
        K1 = P8(Shift(P10(key)))
        K2 = P8(Shift(Shift(P10(key))))
        fK2Value = fK(IPinv(value), K2)
        swValue = SW(fK2Value)
        fK1Value = fK(swValue, K1)
        return IP(fK1Value)
    

    S-DES加密

    使用了一个辅助函数makeByteList,把十六进制文本转化成字节数组,每个字节又是一个数组。

    def makeByteList(hextext):
        l = list(hextext)
        arr = []
        for i in range(len(l) // 2):
            arr += [ l[2*i] + l[2*i+1] ]
        binaryList = []
        for value in arr:
            text = list(bin(int(value, 16))[2:].zfill(8))
            binaryList += [text]
            
    def sdesEncrypt(hextext, key):
        encryptedString  = ''
        for value in makeByteList(hextext)
            encryptedByte = sdesEncryptByte(value, key)
            encryptedString += encryptedByte
    
    def sdesDecrypt(hextext, key):
        encryptedString  = ''
        for value in makeByteList(hextext)
            encryptedByte = sdesDecryptByte(value, key)
            encryptedString += encryptedByte
    

    相关文章

    密码学基础系列

    参考文献

    William Stallings. "Appendix G: Simplified DES"

    相关文章

      网友评论

          本文标题:简化版的DES加密Python实现

          本文链接:https://www.haomeiwen.com/subject/wlttfftx.html