DES加密原理及python脚本

一、加密

1、秘钥处理

​ DES算法会先对64位密钥进行处理生成48位子密钥后再参与到算法的轮操作中,在每一轮的迭代过程中,使用不同的子密钥。其中的处理包括置换选择、循环左移、压缩置换。

1.1 置换选择

DES秘钥有64位,其中每8位有一个校验位,所以有56位的子密钥。根据下表生成56位密钥,并将置换后的56位密钥分成两部分C0和D0,每部分28位:

注意:这里的数字表示的是原数据的位置,不是数据,例:把第57位放在第1位

 

# 置换函数,用于密钥置换、IP置换、P置换等
    def __substitution(self, table: str, self_table: list) -> str:
        """
        :param table: 需要进行置换的列表,是一个01字符串
        :param self_table: 置换表,在__init__中初始化了
        :return: 返回置换后的01字符串
        """
        sub_result = ""
        for i in self_table:
            sub_result += table[i - 1]
        return sub_result

# 返回加密过程中16轮的子密钥
    def __get_key_list(self):
        """
        :return: 返回加密过程中16轮的子密钥
        """
        key = self.__substitution(self.K, self.k1)  # 置换
        left_key = key[0:28]
        right_key = key[28:56]
        keys = []
        for i in range(1, 17):     # 循环左移
            move = self.k0[i - 1]
            move_left = left_key[move:28] + left_key[0:move]
            move_right = right_key[move:28] + right_key[0:move]
            left_key = move_left
            right_key = move_right
            move_key = left_key + right_key
            ki = self.__substitution(move_key, self.k2)  #  压缩置换
            keys.append(ki)
        return keys
    def key_conversion(self, key):
        """
        将64位原始密钥转换为56位的密钥,并进行一次置换
        """
        first_key = key
        key_replace_table = (
            57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
            10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
            63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
            14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
        )
        return self.replace_block(first_key, key_replace_table)

1.2 循环左移

​ 将C0和D0进行循环左移变化(注:每轮循环左移的位数由轮数决定(如下图)),变换后生成C1和D1,然后C1和D1合并。

    def spin_key(self, key: str):
        """
        旋转获得子密钥
        """
        kc = self.key_conversion(key)
        first, second = kc[0: 28], kc[28: 56]
        spin_table = (1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28)
        for i in range(1, 17):
            first_after_spin = first[spin_table[i - 1]:] + first[:spin_table[i - 1]]
            second_after_spin = second[spin_table[i - 1]:] + second[:spin_table[i - 1]]
            print(f"旋转后的key: left: {first_after_spin}, right: {second_after_spin}")
            yield first_after_spin + second_after_spin

1.3 压缩置换

移动后,从56位中选出48位。这个过程中,既置换了每位的顺序,又选择了子密钥,因此称为压缩置换。压缩置换规则如PC-2表(注意表中没有9,18,22,25,35,38,43和54这8位)

​ 压缩置换后的48位子密钥将参与到轮操作中,而C1、D1也将再进行左移和置换后得到下一轮的子密钥。

    def key_selection_replacement(self, key: str):
        """
        通过选择置换得到48位的子密钥
        """
        key_select_table = (
            14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
            23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
            41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
            44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
        )
        for child_key56 in self.spin_key(key):
            self.child_keys.append(self.replace_block(child_key56, key_select_table))
# 置换函数,用于密钥置换、IP置换、P置换等
    def __substitution(self, table: str, self_table: list) -> str:
        """
        :param table: 需要进行置换的列表,是一个01字符串
        :param self_table: 置换表,在__init__中初始化了
        :return: 返回置换后的01字符串
        """
        sub_result = ""
        for i in self_table:
            sub_result += table[i - 1]
        return sub_result

# 返回加密过程中16轮的子密钥
    def __get_key_list(self):
        """
        :return: 返回加密过程中16轮的子密钥
        """
        key = self.__substitution(self.K, self.k1)  # 置换
        left_key = key[0:28]
        right_key = key[28:56]
        keys = []
        for i in range(1, 17):     # 循环左移
            move = self.k0[i - 1]
            move_left = left_key[move:28] + left_key[0:move]
            move_right = right_key[move:28] + right_key[0:move]
            left_key = move_left
            right_key = move_right
            move_key = left_key + right_key
            ki = self.__substitution(move_key, self.k2)  #  压缩置换
            keys.append(ki)
        return keys

2.明文处理

2.1 将明文变为二进制

将字符串的明文转换为二进制,按64位一组,分成若干组,如果不够64位,就补零。

    from bitarray import bitarray
    
    @staticmethod
    def _bit_encode(s: str) -> str:
        """
        将字符串转换为01字符串的形式
        """
        return bitarray(
            ''.join([bin(int('1' + hex(c)[2:], 16))[3:]
                     for c in s.encode('utf-8')])).to01()
    
    def processing_encode_input(self, enter: str) -> list:
        """
        将输入的字符串转换为二进制形式,并没64位为一组进行分割
        """
        result = []
        bit_string = self._bit_encode(enter)
        # 如果长度不能被64整除,就补零
        if len(bit_string) %
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值