最近一个项目,需要使用sm2非对称加密,对方直接给的秘钥证书,python使用gmssl 进行加密,解密,加签,验签用的秘钥是这种格式
# Private Key秘钥 5aa03412c3051e1d4cf9d19cfbeeec70c28f388c9f82747cc912096c9cd44bea
# Public Key 公钥 044291b381a039a8d7d02d7272d2d7c78a30d33e3eeaa0b509bf77d2376582ab2d573730e6bfe9a53bad53f53ac1a85d9c11050931f04bc8b3afc04144d5a6f9be
但是对方给的是这种格式的秘钥证书,python如何使用呢?
1. openssl提取 privateKey.pfx
秘钥证书秘钥转换为python gmssl库可用秘钥
# 注意openssl提取sm2秘钥证书需要对应版本,我这里是下载的 openssl.1.1.1 因为有的版本是不支持提取sm2秘钥证书的
openssl pkcs12 -in privateKey.pfx -nocerts -out private_key.pem -nodes
# 转为把私钥证书转为private_key.pem格式
openssl ec -in private_key.pem -text -noout
# 查看公私钥
priv = """上面复制私钥"""pub = """上面复制公钥"""print('处理后的私钥:{}'.format(priv.replace(":", '').replace('\n', '').replace(' ', '')))
print('处理后的公钥:{}'.format(pub.replace(":", '').replace('\n', '')).replace(' ',''))
# 我这里privateKey.pfx 其实就包含了公私钥信息,就不用单独提取公钥了
2.对方PublicKey.cer文件公钥提取
对方公钥提取起来就简单了,直接安装一下步骤就行
3.python实现 SM2加密
# 这里直接上代码 python解释器版本为3.6 3.10 本人亲测可以运行下面代码 sm2有不同的配置,要看对方使用的sm2进行修改 如 iv mode
import json
import os
import random
import string
import base64
import tracebackimport requests
from Crypto.PublicKey import RSA
from gmssl import sm4, sm2
from datetime import datetime# python解释器版本3.6
class SM4(object):def __init__(self):self.crypt_sm4 = sm4.CryptSM4()self.crypt_sm4_iv = base64.b64decode("这里请填写你的iv值")# sm4 cbc 加密def encrypt_sm4(self, encrypt_key, value):"""国密sm4加密:param encrypt_key: sm4加密key:param value: 待加密的字符串:return: sm4加密后的十六进制值"""crypt_sm4 = self.crypt_sm4crypt_sm4.set_key(encrypt_key.encode(), sm4.SM4_ENCRYPT)date_str = str(value)encrypt_value = crypt_sm4.crypt_cbc(self.crypt_sm4_iv, date_str.encode())# 返回base64编码的加密数据return base64.b64encode(encrypt_value).decode()# sm4 cbc 解密def decrypt_sm4(self, decrypt_key, encrypt_value):"""国密sm4解密:param decrypt_key:sm4加密key:param encrypt_value: 待解密的十六进制值:return: 原字符串"""crypt_sm4 = self.crypt_sm4crypt_sm4.set_key(decrypt_key.encode(), sm4.SM4_DECRYPT) # 设置密钥decrypt_value = crypt_sm4.crypt_cbc(self.crypt_sm4_iv, encrypt_value) # 开始解密。十六进制类型return decrypt_value.decode()# 生成128位随机密钥key@staticmethoddef generate_key():"""生成128位随机密钥key:return: 128位随机密钥key"""return ''.join(random.sample(string.ascii_letters + string.digits, 16))class SM2(object):def __init__(self):self.public_key = '044291b381a039a8d7d02d7272d2d7c78a30d33e3eeaa0b509bf77d2376582ab2d573730e6bfe9a53bad53f53ac1a85d9c11050931f04bc8b3afc04144d5a6f9be'self.private_key = '5aa03412c3051e1d4cf9d19cfbeeec70c28f388c9f82747cc912096c9cd44bea'# 对方的公钥self.others_public_key = ''# 公钥加密def encrypt_sm2(self, public_key, data, java=False):sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key='', mode=1, asn1=True)encrypt_res = sm2_crypt.encrypt(data.encode("UTF_8"))if java:encrypt_res = b'\x04' + encrypt_resreturn base64.b64encode(encrypt_res).decode("utf-8")# 私钥签名def sign_sm2(self, private_key, public_key, data):sm2_crypt = sm2.CryptSM2(private_key, public_key, mode=1, asn1=True)random_hex_str = os.urandom(32).hex() # 随机数signature = sm2_crypt.sign_with_sm3(data.encode("utf-8"), random_hex_str)return base64.b64encode(bytes.fromhex(signature)).decode('utf-8')# 公钥验签def verify_sm2(self, public_key, sign, data):sm2_crypt = sm2.CryptSM2(private_key=None, public_key=public_key, mode=1, asn1=True)return sm2_crypt.verify(sign, data)obj_sm4 = SM4()
obj_sm2 = SM2()