黄石网站建设哪家专业,做网站建设一条龙全包,安徽招标网官网,做网站要做哪些DES加密算法原理及实现
DES是一种对称加密算法【即发送者与接收者持有相同的密钥】#xff0c;它的基本原理是将要加密的数据划分为n个64位的块#xff0c;然后使用一个56位的密钥逐个加密每一个64位的块#xff0c;得到n个64位的密文块#xff0c;最后将密文块拼接起来得…DES加密算法原理及实现
DES是一种对称加密算法【即发送者与接收者持有相同的密钥】它的基本原理是将要加密的数据划分为n个64位的块然后使用一个56位的密钥逐个加密每一个64位的块得到n个64位的密文块最后将密文块拼接起来得到最终的密文 加密
加密过程
DES加密过程接收一个明文盒一个64位的密钥key明文字符串会被转换为对各64位的块加密过程以块位单位经过初态转换16轮循环加密终态转换最终每个64位的块都会被加密成一个64位的密文块将得到的密文块拼起来得到的就是最终加密后的结果。 def encode(self, enter: str, key: str):result # 将输入的字符串处理为长度为64的块blocks self.processing_encode_input(enter)for block in blocks:# 对每一块进行初态置换irb_result self._init_replace_block(block)# 对每一块进行16轮循环加密block_result self.iteration(irb_result, key, is_decodeFalse)# 对每一块进行终态置换block_result self._end_replace_block(block_result)# 返回16进制形式的密文串result str(hex(int(block_result.encode(), 2)))return result1. 明文数据处理processing_encode_input
首先需要将字符串的明文转换为二进制按64位一组分成若干组如果不够64位就补零。 from bitarray import bitarraystaticmethoddef _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) % 64 ! 0:for i in range(64 - len(bit_string) % 64):bit_string 0for i in range(len(bit_string) // 64):result.append(bit_string[i * 64: i * 64 64])# print(f转换为二进制后的初始明文 {result})return result2. 初态转换
初态转换是将初始的64位块按照 【IP置换表】的规则重新排序
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7IP 置换表中每一位的意思是将原来第i位的元素填充到这如第一个58就表示把原来比特串中第58位放在新串的第1位第二个50表示把原来比特串的第50位放在新串的第2位… staticmethoddef replace_block(block: str, replace_table: tuple) - str:对单个块进行置换Args:block: str, 要进行转换的64位长的01字符串replace_table: 转换表Return:返回转换后的字符串result for i in replace_table:try:result block[i - 1]except IndexError:print(i)print(fblock {block}, len{len(block)})raisereturn resultdef _init_replace_block(self, block: str):对一个块进行初态置换replace_table (58, 50, 42, 34, 26, 18, 10, 2,60, 52, 44, 36, 28, 20, 12, 4,62, 54, 46, 38, 30, 22, 14, 6,64, 56, 48, 40, 32, 24, 16, 8,57, 49, 41, 33, 25, 17, 9, 1,59, 51, 43, 35, 27, 19, 11, 3,61, 53, 45, 37, 29, 21, 13, 5,63, 55, 47, 39, 31, 23, 15, 7)return self.replace_block(block, replace_table)3. 16轮循环加密iteration 每一轮循环加密的过程为
将初态置换后或上一次循环后得到的64位块分成左右各32位的子块Left盒RightRight经过f函数转换后得到一个32位的串这个串与Left做异或后得到下一轮循环的Right将这一轮原视的Right作为下一轮的Left拼接Left盒Right,进行下一轮循环 def iteration(self, block: str, key: str) - str:for i in range(16):# 分成左右两个子块left, right block[0: 32], block[32: 64]# 将这一轮原视的Right作为下一轮的Leftnext_left right# f函数f_result self._f_function(right, i)# f函数的输出与left做异或得到下一轮的rightright self._not_or(left, f_result)# 拼接准备进行下一轮block next_left rightreturn block[32:] block[:32]在最后一轮循环加密之后left盒right是相反的所以进行终态置换之前要换过来
3.1 f函数 f函数有三部分组成
拓展置换S盒置换P盒置换 def _f_function(self, right: str, num: int):# 拓展置换right self.block_extend(right)# S盒置换sbc_result self.s_box_compression(num, right)# P盒置换return self.p_box_replacement(sbc_result)3.1.1 拓展置换
拓展置换的目的是将一个32位的串根据【拓展置换表】转换为48位其实就是重复其中的某些位达到混淆的目的。具体就是将32位的数据分成4*8小块每个小块拓展为6位。
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1拓展置换表中每一行代表拓展后的一个小块内部数字表示原来子块中01的位置其实就是在每一个小块前面加上前一个小块的最后一个字符后面加上下一个小块的第一个字符比如有三个小块
0 1 0 0 1 0 1 1 1 0 0 1那么第二个小块拓展之后就是
0 1 0 1 1 1staticmethoddef block_extend(block: str) - str:拓展置换extended_block extend_table (32, 1, 2, 3, 4, 5,4, 5, 6, 7, 8, 9,8, 9, 10, 11, 12, 13,12, 13, 14, 15, 16, 17,16, 17, 18, 19, 20, 21,20, 21, 22, 23, 24, 25,24, 25, 26, 27, 28, 29,28, 29, 30, 31, 32, 1)for i in extend_table:extended_block block[i - 1]return extended_block3.1.2 S盒置换 S盒置换有两步
与密钥keyi{key}_ikeyi做异或S盒压缩 def s_box_compression(self, num: int, block48: str) - str:对经过拓展置换后的48位01串进行S盒压缩Args:num: 第几次迭代block48: rightReturn:返回经过S盒压缩后的32位01字符串# 与密钥key做异或result_not_or self._not_or(block48, self.child_keys[num])# S盒压缩return self._s_box_replace(result_not_or)密钥keyi{key}_ikeyi的获得 DES的原始密钥是一个64位的01串其中816 24 32 40 4856 64位作为奇偶检验位通过密钥转换去除实际加密中使用的只有56位这56位的密钥经过密钥旋转和置换选择会产生16个48位的子密钥所以每次循环加密用到的子密钥都是不同的。
密钥转换的目的是将64位原始密钥转换为56位的密钥并进行一次置换 依照的表是密钥转换表 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代码实现 def key_conversion(self, key):将64位原始密钥转换为56位的密钥并进行一次置换first_key keykey_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)密钥旋转是为了保证16个子密钥各不相同。具体做法是将56位密钥分成两个28位的子串然后将这两个子串进行循环旋转具体规则依照DesRotations表
Round12345678910111213141516Rotations1122222212222221
Round表示第几轮旋转也就是第几个keyRotations表示旋转次数 除了第1 2 9 16个key旋转1位其他都旋转两位 每次旋转是相对于上一次的结果而言的比如第三个子密钥就是原视的两个28位串向左旋转4位得到的 代码实现 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置换选择密钥旋转之后拼接得到一个56位的串置换选择可以选择其中48位作为最终的keyi{key}_ikeyi,置换选择依照置换选择表 置换选择表 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 代码实现 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))S盒压缩
密钥keyi{key}_ikeyi与拓展置换后的right做异或后得到一个48位的串这个串必须压缩成32位才能作为下一轮的left。把这个48位的串分成8组每组六位压缩就是要把6位变成4位这里用到了8张 4*16 的【S盒压缩表】
s_box1 [[14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7],[0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8],[4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0],[15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13],
],
s_box2 [[15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10],[3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5],[0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15],[13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9],
],
s_box3 [[10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8],[13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1],[13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7],[1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12],
],
s_box4 [[7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15],[13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9],[10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4],[3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14],
],
s_box5 [[2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9],[14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6],[4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14],[11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3],
],
s_box6 [[12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11],[10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8],[9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6],[4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13],
],
s_box7 [[4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1],[13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6],[1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2],[6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12],
],
s_box8 [[13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7],[1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2],[7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8],[2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11],
]具体做法是
将经过拓展置换后得到的48位串与48位密钥做异或得到48位密文串每6个分一组分8组如第二组是111011就查找把第一位与最后一位取出得到11,转换为十进制3作为行号中间四位1101转换为十进制13作为列号查找s_box2的3行13列得到9将9转换为二进制为1001就是这6为密文压缩后的结果其他一样最终会输出32位密文串。
代码实现 def _s_box_replace(self, block48: str) - str:S盒置换将48位的输入转换为32位输出s_box_table (((14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7),(0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8),(4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0),(15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13),),((15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10),(3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5),(0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15),(13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9),),((10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8),(13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1),(13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7),(1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12),),((7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15),(13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9),(10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4),(3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14),),((2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9),(14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6),(4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14),(11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3),),((12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11),(10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8),(9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6),(4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13),),((4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1),(13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6),(1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2),(6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12),),((13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7),(1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2),(7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8),(2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11),))result for i in range(8):row_bit (block48[i * 6] block48[i * 6 5]).encode(utf-8)line_bit (block48[i * 6 1: i * 6 5]).encode(utf-8)row int(row_bit, 2)line int(line_bit, 2)# print(f第{row}行 第{line}列)data s_box_table[i][row][line]no_full str(bin(data))[2:]while len(no_full) 4:no_full 0 no_fullresult no_fullreturn result2.1.3 P盒置换
p盒置换作用也是为了混淆用到了【P盒置换表】原理与其他置换一样 def p_box_replacement(self, block32: str) - str:P盒置换Return:返回经过P盒置换后的32位01串p_box_replace_table (16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25,)return self.replace_block(block32, p_box_replace_table)4. 终态置换
与初态置换一样, 只不过使用的置换表不一样而已
终态置换表 40, 8, 48, 16, 56, 24, 64, 32,39, 7, 47, 15, 55, 23, 63, 31,38, 6, 46, 14, 54, 22, 62, 30,37, 5, 45, 13, 53, 21, 61, 29,36, 4, 44, 12, 52, 20, 60, 28,35, 3, 43, 11, 51, 19, 59, 27,34, 2, 42, 10, 50, 18, 58, 26,33, 1, 41, 9, 49, 17, 57, 25代码实现 def _end_replace_block(self, block: str) - str:对某一个块进行终态转换replace_table (40, 8, 48, 16, 56, 24, 64, 32,39, 7, 47, 15, 55, 23, 63, 31,38, 6, 46, 14, 54, 22, 62, 30,37, 5, 45, 13, 53, 21, 61, 29,36, 4, 44, 12, 52, 20, 60, 28,35, 3, 43, 11, 51, 19, 59, 27,34, 2, 42, 10, 50, 18, 58, 26,33, 1, 41, 9, 49, 17, 57, 25)return self.replace_block(block, replace_table)解密
解密使用与加密相同的算法只不过使用子密钥的顺序不同而已加密过程第一轮循环使用key1key_1key1,解密过程第一轮循环使用key16key_{16}key16,可以在循环加密处添加一个标志位完成
分组模式
明文可能被转换为多个64位的块如果将每个块单独加密后将所有块加密后的结果简单拼接起来构成最终密文这样的模式叫做ECB(电码本模式)这种模式简单 但安全性不高如果将上一个块的加密后的结果与这个块的原视数据做异或后再加密的模式叫做CBC分组链接模式还有CFBOFB等
CBC模式下DES的加解密流程
完整代码
# __author: Junebao
# data:2020/3/9from bitarray import bitarrayclass MyDES:def __init__(self):self.child_keys []staticmethoddef _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 _str_to__fixed_len_bit(self, s: str, length: int) - str:将字符串转变为固定长度的01字符串:param s: 要转换的字符串:param length: 目标长度:return: 长度为length的01字符串bit_iv self._bit_encode(s)while len(bit_iv) length:bit_iv 0return bit_iv[: length]staticmethoddef _bit_decode(s: list):return .join([chr(i) for i in [int(b, 2) for b in s]])staticmethoddef _negate(s: str):result try:for i in s:result 0 if i 1 else 1return resultexcept:print(密钥错误)raisestaticmethoddef _replace_block(block: str, replace_table: tuple) - str:对单个块进行置换Args:block: str, 要进行转换的64位长的01字符串replace_table: 转换表Return:返回转换后的字符串result for i in replace_table:try:result block[i - 1]except IndexError:print(i)# print(fblock {block}, len{len(block)})raisereturn resultdef _processing_encode_input(self, enter: str) - list:将输入的字符串转换为二进制形式并没64位为一组进行分割result []bit_string self._bit_encode(enter)# 如果长度不能被64整除就补零if len(bit_string) % 64 ! 0:for i in range(64 - len(bit_string) % 64):bit_string 0for i in range(len(bit_string) // 64):result.append(bit_string[i * 64: i * 64 64])# print(f转换为二进制后的初始明文 {result})return resultstaticmethoddef _processing_decode_input(enter: str) - list:result []try:input_list enter.split(0x)[1:]int_list [int(0x i, 16) for i in input_list]for i in int_list:bin_data str(bin(i))[2:]while len(bin_data) 64:bin_data 0 bin_dataresult.append(bin_data)return resultexcept Exception as e:raisedef _key_conversion(self, key: str):将64位原始密钥转换为56位的密钥并进行一次置换key self._bit_encode(key)while len(key) 64:key 0first_key key[:64]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)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_spindef _key_selection_replacement(self, key: str):通过选择置换得到48位的子密钥# 先置空self.child_keys []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))def _init_replace_block(self, block: str):对一个块进行初态置换replace_table (58, 50, 42, 34, 26, 18, 10, 2,60, 52, 44, 36, 28, 20, 12, 4,62, 54, 46, 38, 30, 22, 14, 6,64, 56, 48, 40, 32, 24, 16, 8,57, 49, 41, 33, 25, 17, 9, 1,59, 51, 43, 35, 27, 19, 11, 3,61, 53, 45, 37, 29, 21, 13, 5,63, 55, 47, 39, 31, 23, 15, 7)return self._replace_block(block, replace_table)def _end_replace_block(self, block: str) - str:对某一个块进行终态转换replace_table (40, 8, 48, 16, 56, 24, 64, 32,39, 7, 47, 15, 55, 23, 63, 31,38, 6, 46, 14, 54, 22, 62, 30,37, 5, 45, 13, 53, 21, 61, 29,36, 4, 44, 12, 52, 20, 60, 28,35, 3, 43, 11, 51, 19, 59, 27,34, 2, 42, 10, 50, 18, 58, 26,33, 1, 41, 9, 49, 17, 57, 25)return self._replace_block(block, replace_table)staticmethoddef _block_extend(block: str) - str:拓展置换extended_block extend_table (32, 1, 2, 3, 4, 5,4, 5, 6, 7, 8, 9,8, 9, 10, 11, 12, 13,12, 13, 14, 15, 16, 17,16, 17, 18, 19, 20, 21,20, 21, 22, 23, 24, 25,24, 25, 26, 27, 28, 29,28, 29, 30, 31, 32, 1)for i in extend_table:extended_block block[i - 1]return extended_blockstaticmethoddef _not_or(a: str, b: str) - str:对两个01字符串做异或result size len(a) if len(a) len(a) else len(b)for i in range(size):result 0 if a[i] b[i] else 1return resultdef _s_box_replace(self, block48: str) - str:S盒置换将48位的输入转换为32位输出s_box_table (((14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7),(0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8),(4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0),(15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13),),((15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10),(3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5),(0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15),(13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9),),((10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8),(13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1),(13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7),(1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12),),((7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15),(13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9),(10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4),(3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14),),((2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9),(14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6),(4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14),(11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3),),((12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11),(10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8),(9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6),(4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13),),((4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1),(13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6),(1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2),(6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12),),((13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7),(1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2),(7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8),(2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11),))result for i in range(8):row_bit (block48[i * 6] block48[i * 6 5]).encode(utf-8)line_bit (block48[i * 6 1: i * 6 5]).encode(utf-8)row int(row_bit, 2)line int(line_bit, 2)# print(f第{row}行 第{line}列)data s_box_table[i][row][line]no_full str(bin(data))[2:]while len(no_full) 4:no_full 0 no_fullresult no_fullreturn resultdef _s_box_compression(self, num: int, block48: str) - str:对经过拓展置换后的48位01串进行S盒压缩有两部1. 与key做异或2. 根据S盒压缩表经48位压缩为36位Args:num: 第几次迭代block48: rightReturn:返回经过S盒压缩后的32位01字符串result_not_or self._not_or(block48, self.child_keys[num])# print(f与key 做异或后的结果{result_not_or})return self._s_box_replace(result_not_or)def _p_box_replacement(self, block32: str) - str:P盒置换Return:返回经过P盒置换后的32位01串p_box_replace_table (16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25,)return self._replace_block(block32, p_box_replace_table)def _f_function(self, right: str, is_decode: bool, num: int):right self._block_extend(right)if is_decode:sbc_result self._s_box_compression(15 - num, right)else:sbc_result self._s_box_compression(num, right)# print(fs盒压缩后的结果:{sbc_result})return self._p_box_replacement(sbc_result)def _iteration(self, block: str, key: str, is_decode: bool) - str:self._key_selection_replacement(key)for i in range(16):left, right block[0: 32], block[32: 64]next_left rightf_result self._f_function(right, is_decode, i)right self._not_or(left, f_result)block next_left rightreturn block[32:] block[:32]def encode(self, enter: str, key: str):result blocks self._processing_encode_input(enter)for block in blocks:irb_result self._init_replace_block(block)block_result self._iteration(irb_result, key, is_decodeFalse)block_result self._end_replace_block(block_result)result str(hex(int(block_result.encode(), 2)))return resultdef encode_by_cbc(self, enter: str, des_key: str, iv: str):使用 CBC 模式进行 DES加密:param enter: 明文:param des_key: 密钥:param iv: CBC模式中的因子:return: 加密后的十六进制格式密文串bit_iv self._str_to__fixed_len_bit(iv, 64)result blocks self._processing_encode_input(enter)previous bit_ivfor block in blocks:block self._not_or(block, previous)irb_result self._init_replace_block(block)block_result self._iteration(irb_result, des_key, is_decodeFalse)block_result self._end_replace_block(block_result)previous block_resultresult str(hex(int(block_result.encode(), 2)))return resultdef decode(self, cipher_text: str, key: str):result []blocks self._processing_decode_input(cipher_text)for block in blocks:irb_result self._init_replace_block(block)block_result self._iteration(irb_result, key, is_decodeTrue)block_result self._end_replace_block(block_result)for i in range(0, len(block_result), 8):result.append(block_result[i: i8])return self._bit_decode(result)def decode_by_cbc(self, cipher_text: str, des_key: str, iv: str):bit_iv self._str_to__fixed_len_bit(iv, 64)result []blocks self._processing_decode_input(cipher_text)previous bit_ivfor block in blocks:irb_result self._init_replace_block(block)block_result self._iteration(irb_result, des_key, is_decodeTrue)block_result self._end_replace_block(block_result)block_result self._not_or(block_result, previous)previous blockfor i in range(0, len(block_result), 8):result.append(block_result[i: i8])return self._bit_decode(result)if __name__ __main__:key hahahhaiv this is ivmd MyDES()des_encode md.encode(junebao.top, key)print(DES加密后的数据为 des_encode)print(f解密出的数据为 md.decode(des_encode, key))cbc_encode md.encode_by_cbc(http://blog.junebao.top, des_keykey, iviv)print(fCBC mode encryption {cbc_encode})print(fCBC mode decrypt {md.decode_by_cbc(cbc_encode, des_keykey, iviv)})
结果 参考
https://blog.csdn.net/wowocpp/article/details/80132097 https://www.bilibili.com/video/av75630674?t133p7 https://blog.csdn.net/weixin_42940826/article/details/83687007?depth_1-utm_sourcedistribute.pc_relevant.none-taskutm_sourcedistribute.pc_relevant.none-task