数据加密的基本思想是通过变换信息的表现形式来伪装需要保护的敏感信息,非授权者不能了解被加密的内容。
根据业务场景,使用国密SM3/SM4加算法实现数据传输的安全性,提高数据的可靠性,满足客户场景中其他系统的接入条件
使用github上star最多的https://github.com/duanhongyi/gmssl,但是该项目截止使用时暂未实现0填充算法,后来补齐后https://github.com/kanghaov/gmssl
pr给开发者,现已实现
通讯协议
一般选定加密的通讯协议,双方约定响应的加密流程,笼统的例子:
约定信息生成sign,返回token,在token有效期内作为鉴权标志,根据需要也可以一个操作主体一个token
1.计算sign
# 定制方提供
appId = "1234567890"
appSecret = "1234567890"
person_id = "1234567890"
encryption_methon() # 约定使用sm3加密
# 请求方使用
sign = encryption_methon(appSecret,person_id,timestamp,requestId) # 生命周期7200s,
SM3
使用gmssl
的sm3模块加密sign,例子:
sign = '00000158ea0a3cef18c45e769f7136de7977db3f0000015815261641523970076F6B86C8FA70AC4CB'
encoded_sign= sm3.sm3_hash(func.bytes_to_list(bytes(sign, encoding="ascii")))
将请求信息按照预定的格式生成后使用SM4对明文进行加密后请求服务端
SM4
2.加密请求数据:
原数据格式使用json.dumps()
及bytes()
转换成bytes
resData= {'requestId': 'asf0ei8xts9ibvbv809piudtk6qtjkem', 'timestamp': '1660816878517', 'projectId': '00001842', 'robotId': '000018425682', 'sign': 'edcb260f7d2231d695c028362372c705c923d30da7d51892258f6b45d8ad2527'}
resData = bytes(json.dumps(resData),encoding="ascii")
由于该客户要求SM4加密算法使用ECB模式、0补码、utf-8编码
,而目前github上主要的基于python的SM4算法均采用PKCS7
补码及解码,需要自己补充0补码
的实现方式,两者的区别只是以16byte划分数据,对于尾部不满16byte的数据,用[16-尾部数据长度]字符进行填充还是用0进行填充,不同padding方式,加密结果如下:
pkcs7:
data = [34, 123, 92, 34, 114, 101, 113, 117, 101, 115, 116, 73, 100, 92, 34, 58, 32, 92, 34, 101, 97, 48, 97, 51, 99, 101, 102, 49, 56, 99, 52, 53, 101, 55, 54, 57, 102, 55, 49, 51, 54, 100, 101, 55, 57, 55, 55, 100, 98, 51, 102, 92, 34, 44, 32, 92, 34, 115, 105, 103, 110, 92, 34, 58, 32, 92, 34, 97, 101, 50, 98, 97, 56, 49, 49, 48, 49, 57, 99, 55, 49, 49, 50, 101, 98, 56, 101, 55, 52, 100, 50, 54, 53, 99, 55, 51, 52, 98, 48, 53, 101, 97, 55, 54, 49, 102, 56, 56, 50, 56, 99, 101, 50, 102, 54, 101, 102, 50, 98, 100, 99, 54, 100, 49, 100, 50, 54, 100, 53, 51, 50, 92, 34, 44, 32, 92, 34, 114, 111, 98, 111, 116, 73, 100, 92, 34, 58, 32, 92, 34, 48, 48, 48, 48, 48, 49, 53, 56, 49, 53, 50, 54, 92, 34, 44, 32, 92, 34, 112, 114, 111, 106, 101, 99, 116, 73, 100, 92, 34, 58, 32, 92, 34, 48, 48, 48, 48, 48, 49, 53, 56, 92, 34, 44, 32, 92, 34, 116, 105, 109, 101, 115, 116, 97, 109, 112, 92, 34, 58, 32, 92, 34, 49, 54, 52, 49, 53, 50, 51, 57, 55, 48, 48, 55, 54, 92, 34, 125, 34, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11] 240
0:
data = [34, 123, 92, 34, 114, 101, 113, 117, 101, 115, 116, 73, 100, 92, 34, 58, 32, 92, 34, 101, 97, 48, 97, 51, 99, 101, 102, 49, 56, 99, 52, 53, 101, 55, 54, 57, 102, 55, 49, 51, 54, 100, 101, 55, 57, 55, 55, 100, 98, 51, 102, 92, 34, 44, 32, 92, 34, 115, 105, 103, 110, 92, 34, 58, 32, 92, 34, 97, 101, 50, 98, 97, 56, 49, 49, 48, 49, 57, 99, 55, 49, 49, 50, 101, 98, 56, 101, 55, 52, 100, 50, 54, 53, 99, 55, 51, 52, 98, 48, 53, 101, 97, 55, 54, 49, 102, 56, 56, 50, 56, 99, 101, 50, 102, 54, 101, 102, 50, 98, 100, 99, 54, 100, 49, 100, 50, 54, 100, 53, 51, 50, 92, 34, 44, 32, 92, 34, 114, 111, 98, 111, 116, 73, 100, 92, 34, 58, 32, 92, 34, 48, 48, 48, 48, 48, 49, 53, 56, 49, 53, 50, 54, 92, 34, 44, 32, 92, 34, 112, 114, 111, 106, 101, 99, 116, 73, 100, 92, 34, 58, 32, 92, 34, 48, 48, 48, 48, 48, 49, 53, 56, 92, 34, 44, 32, 92, 34, 116, 105, 109, 101, 115, 116, 97, 109, 112, 92, 34, 58, 32, 92, 34, 49, 54, 52, 49, 53, 50, 51, 57, 55, 48, 48, 55, 54, 92, 34, 125, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
源代码中gmssl/func.py
:
padding = lambda data, block=16: data + [(16 - len(data) % block)for _ in range(16 - len(data) % block)]
unpadding = lambda data: data[:-data[-1]]
新增0补码
,为:
pkcs7_padding = lambda data, block=16: data + [(16 - len(data) % block)for _ in range(16 - len(data) % block)]
zero_padding = lambda data, block=16: data + [0 for _ in range(16 - len(data) % block)]
pkcs7_unpadding = lambda data: data[:-data[-1]]
zero_unpadding = lambda data,i =1:data[:-i] if data[-i] == 0 else i+1
选择不同补码方式只需要在SM4
模块中SM4类实例化的时候传参进去就好了
仓库地址:
3.解密返回数据
直接调用相关函数,选择0填充
方式会自动选择响应的解码方式,解密后:
{
"data": {
"token": "xAeTiWxw99Eg7QBm5qR6fIGDmrcaaUtLzlZ2zpOl0HKcvV6MYZiiW5e+ThvBzIy8"
},
"msg": "成功",
"msgCode": 0,
"requestId": "ea0a3cef18c45e769f7136de7977db3f",
"sign": "d81840ab9ec6a97085afe1bee085f6e0fea2c38ba4d65b5936abcaabc079c6c9",
"success": true,
"timestamp": "1641868606481"
}
这样就获取了请求对象专属的token,后续请求时,相应的请求主体附带上token和encryptScript信息就好了
另:
相比于使用python内置的数据结构,某些场景更喜欢使用class
搭配__repe__
方法实现数据的存储,比如:
class appInfo:
"""
开发者信息
"""
def __init__(self, appId="", appSecret="", getTime=""):
self.appId = appId
self.appSecret = bytes(appSecret, encoding="ascii")
self.appSecretStr = appSecret
self.getTime = getTime
def __repr__(self):
return "appId = {0},appSecret={1},appSecretStr={2},getTime={3}".format(
str(self.appId),self.appSecret,str(self.appSecretStr),str(self.getTime))
可以对数据有更多的处理方式
发表回复