基于Python的SM4ECB及CBC加密


最近在学习SM4算法,通过代码实现可以更好地理解算法的具体运算过程。

1.算法简述

SM4分为加解密算法和密钥拓展算法,简单地说就是将128比特数据分为四组,使用轮函数对其进行运算,密钥拓展算法用于生成轮密钥,当使用密钥拓展算法时,轮函数输入为(四组输入数据,固定参数CK),当使用加密算法时轮函数输入为(四组输入数据,轮密钥rk),解密算法与加密算法相同只是使用的轮密钥顺序相反。

在本文中,明文和密钥及IV的输入都为16进制数,如果需要加密字符串类型的明文,需要先将其转为16进制,但在本文中仅针对明文为128bit时进行了实现,如果小于或大于128bit需要进行相应的填充。

(1)异或:

异或可以表示为xor,在python中可以通过^实现,a与b的异或运算可以理解为(假设a和b为16进制),需注意python默认值是字符串比如,a = “01234567”,需要进行转码后进行运算。

a = int('01234567',16)
b = int('30',16)
print(bin(a^b))
#a的二进制值为0b1001000110100010101100111
                   #b的二进制值为0b110000
#输出的结果为:0b1001000110100010101010111

其实就是,首先将进行异或的数转为2进制,从低位开始比较,两者相同则该位改为0,两者不同该位改为1,如果a>b,那么将比较至b的最高位,剩余的未比较的位数值保持不变

(2)轮函数:

轮函数结构GB-T 32907中对轮函数的描述很好理解,其中T为合成置换,包括一次S盒置换后将输出作为线性变换L的输入。

(3)S盒置换:

SBOX = ['d6', '90', 'e9', 'fe', 'cc', 'e1', '3d', 'b7', '16', 'b6', '14', 'c2', '28', 'fb', '2c', '05',
       '2b', '67', '9a', '76', '2a', 'be', '04', 'c3', 'aa', '44', '13', '26', '49', '86', '06', '99',
       '9c', '42', '50', 'f4', '91', 'ef', '98', '7a', '33', '54', '0b', '43', 'ed', 'cf', 'ac', '62',
       'e4', 'b3', '1c', 'a9', 'c9', '08', 'e8', '95', '80', 'df', '94', 'fa', '75', '8f', '3f', 'a6',
       '47', '07', 'a7', 'fc', 'f3', '73', '17', 'ba', '83', '59', '3c', '19', 'e6', '85', '4f', 'a8',
       '68', '6b', '81', 'b2', '71', '64', 'da', '8b', 'f8', 'eb', '0f', '4b', '70', '56', '9d', '35',
       '1e', '24', '0e', '5e', '63', '58', 'd1', 'a2', '25', '22', '7c', '3b', '01', '21', '78', '87',
       'd4', '00', '46', '57', '9f', 'd3', '27', '52', '4c', '36', '02', 'e7', 'a0', 'c4', 'c8', '9e',
       'ea', 'bf', '8a', 'd2', '40', 'c7', '38', 'b5', 'a3', 'f7', 'f2', 'ce', 'f9', '61', '15', 'a1',
       'e0', 'ae', '5d', 'a4', '9b', '34', '1a', '55', 'ad', '93', '32', '30', 'f5', '8c', 'b1', 'e3',
       '1d', 'f6', 'e2', '2e', '82', '66', 'ca', '60', 'c0', '29', '23', 'ab', '0d', '53', '4e', '6f',
       'd5', 'db', '37', '45', 'de', 'fd', '8e', '2f', '03', 'ff', '6a', '72', '6d', '6c', '5b', '51',
       '8d', '1b', 'af', '92', 'bb', 'dd', 'bc', '7f', '11', 'd9', '5c', '41', '1f', '10', '5a', 'd8',
       '0a', 'c1', '31', '88', 'a5', 'cd', '7b', 'bd', '2d', '74', 'd0', '12', 'b8', 'e5', 'b4', 'b0',
       '89', '69', '97', '4a', '0c', '96', '77', '7e', '65', 'b9', 'f1', '09', 'c5', '6e', 'c6', '84',
       '18', 'f0', '7d', 'ec', '3a', 'dc', '4d', '20', '79', 'ee', '5f', '3e', 'd7', 'cb', '39', '48',]

GB-T 32907中给出的S盒数据为16进制,不过我们将在进行S盒置换时将数据转为10进制进行运算,所以不需要使用0X形式描写数据。

其中如果使用Oxd6形式描写数据,在转为10进制时直接使用int(0xd6)而不需添加进制参数,而使用“d6”描写数据时需要使用int(“d6”,16)。

(4)线性变换L:

线性变换
其中B<<<2 表示为对B进行32位左移2,可以理解位将高位的两位移动到低位,输入和输出都为32位。

2.密钥拓展算法

在一次针对128bit明文的加密过程中,密钥拓展算法将生成32个轮密钥。而密钥拓展算法的输入为128bit的密钥。

首先将16字节也就是128bit的密钥分为一个每4字节为一组的列表,这里可以使用如下方式进行分组,其中n为分组位数。

def group(list, n):
    for i in range(0, len(list), n):
        yield list[i:i + n]

使用方法为:(本文中明文和密钥的输入都是用标准中给出的示例,即’0123456789abcdeffedcba9876543210’)

MK = []
    for i in group('0123456789abcdeffedcba9876543210',8)
        MK.append(i)
>>>
  • 9
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值