S-DES python实现

简化DES, S-DES, 一种对称加密算法

一次网络安全的练手作业…

class S_DES:
    """
    简化DES, S-DES, 一种对称加密算法
    可使用两个8位密钥,或由一个10位密钥生成两个8位密钥
    明文和密文限制为8位

    @author ZJH
    2021/10/6
    """

    def IP(self, text: str) -> str:
        orderIP = '15203746'
        return ''.join([text[int(i)] for i in orderIP])

    def IP_RE(self, text: str) -> str:
        orderIP_RE = '30246175'
        return ''.join([text[int(i)] for i in orderIP_RE])

    def SW(self, text: str) -> str:
        return text[4:] + text[:4]

    def generateKey(self, P10: str) -> tuple:
        """
        用10位密钥产生两位8位密钥

        :param P10: 10位密钥, str
        :return: 2个8位密钥, tuple, (K1,K2)
        """

        # 置换P10
        order10 = '2416390875'
        P10 = ''.join([P10[int(i)] for i in order10])

        # 左移
        P10 = P10[1:5] + P10[0] + P10[6:] + P10[5]

        # 产生8位K1
        order8 = '52637498'
        self.K1 = ''.join([P10[int(i)] for i in order8])

        # 左移2次
        P10 = P10[1:5] + P10[0] + P10[6:] + P10[5]
        P10 = P10[1:5] + P10[0] + P10[6:] + P10[5]

        # 产生8位K2
        self.K2 = ''.join([P10[int(i)] for i in order8])

        print('KEY1:\t{}\nKEY2:\t{}'.format(self.K1, self.K2))

        return (self.K1, self.K2)

    def funK(self, text: str, key: str) -> str:
        # 分半
        L, R = text[:4], text[4:]

        # 拓展/置换
        ep1 = R[3] + R[:3]
        ep2 = R[1:] + R[0]

        # 异或
        ep1 = [str(int(a) ^ int(b)) for a, b in zip(ep1, key[:4])]
        ep2 = [str(int(a) ^ int(b)) for a, b in zip(ep2, key[4:])]

        # 映射
        S1 = ('1032', '3210', '0213', '3132')
        S2 = ('0123', '2013', '3010', '2103')

        ep1 = S1[int(ep1[0] + ep1[3], 2)][int(ep1[1] + ep1[2], 2)]
        ep1 = '{0:02b}'.format(int(ep1))

        ep2 = S2[int(ep2[0] + ep2[3], 2)][int(ep2[1] + ep2[2], 2)]
        ep2 = '{0:02b}'.format(int(ep2))

        mappingF = ep1[1] + ep2[::-1] + ep1[0]

        # 映射结果异或
        L = int(mappingF, 2) ^ int(L, 2)
        L = '{0:04b}'.format(int(L))

        # 组合得到结果
        res = L + R

        # print('RES:\t'+res)

        return res

    def initKey(self, key1, key2=''):
        """
        自动初始化密钥
        eg:
            initKey(self,10位密钥)
            or
            initKey(self,8位密钥1)
            or
            initKey(self,8位密钥1, 8位密钥1)
            or
            initKey(self,8位密钥1, 8位密钥2)

        :param key1: 密钥1 8或10位,str
        :param key2: 密钥2 8位 密钥1为10位时不需要传入, str, ''
        :return:
        """
        assert len(key1) in (8, 10), '密钥1长度不合法, 应该为8或10位str:' + key1

        if len(key1) == 10:
            print('你输入的是10位密钥,将自动生产两个8位密钥')
            self.generateKey(key1)
        else:
            if not key2:
                print('你输入了一个8位密钥')
                self.K1 = self.K2 = key1
            else:
                assert len(key2) == 8, '密钥2长度不合法, 应该为8位str:' + key2
                print('你输入了两个8位密钥')
                self.K1, self.K2 = key1, key2

    def encode(self, text: str) -> str:
        assert len(text) == 8, '明文长度不合法, 应该为8位str:' + text

        text = self.IP(text)

        text = self.funK(text, self.K1)

        text = self.SW(text)

        text = self.funK(text, self.K2)

        text = self.IP_RE(text)

        print('加密完成, 密文: ' + text)

        return text

    def decode(self, text: str) -> str:
        assert len(text) == 8, '密文长度不合法, 应该为8位str:' + text

        text = self.IP(text)

        text = self.funK(text, self.K2)

        text = self.SW(text)

        text = self.funK(text, self.K1)

        text = self.IP_RE(text)

        print('解密完成, 明文: ' + text)

        return text

    def __init__(self, *args, **kwargs):
        if args or kwargs:
            print('自动设置密钥')
            self.initKey(*args, **kwargs)
        else:
            print('未设置密钥')


if __name__ == '__main__':
    # s=S_DES()
    # s.initKey('1010000010')
    # s.initKey('10100100')
    # s.initKey('10100100','01000011')

    s = S_DES('1010000010')
    res = s.encode('1' * 8)
    s.decode(res)