当前位置: 首页 > 后端技术 > Python

使用Python脚本进行国密sm2加解密

时间:2023-03-26 11:15:34 Python

1.场景工作中的一个场景:Go需要对信息进行加解密,但是研究了GmSSLGoAPI文档后发现依赖于CGO。匹配成功。于是我换了一个方法,选择了Go调用Python脚本进行加解密。之前写过Python是用国密sm2算法对信息进行加解密,比较方便。二、代码importsysfromgmsslimportsm2frombase64importb64encode,b64decode#sm2的公私钥SM2_PRIVATE_KEY='00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'SM2_PUBLIC_KEY='B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'sm2_crypt=sm2.CryptSM2(public_key=SM2_PUBLIC_KEY,private_key=SM2_PRIVATE_KEY)#加密defencrypt(info):encode_info=sm2_crypt.encrypt(info.encode(encoding="utf-8"))encode_info=b64encode(encode_info).decode()#通过base64对二进制字节进行编码returnencode_info#解密defdecrypt(info):decode_info=b64decode(info.encode())#base64解码成二进制字节decode_info=sm2_crypt.decrypt(info).decode(encoding="utf-8")returndecode_infoif__name__=="__main__":action=sys.argv[1]#获取theencryptionanddecryptactioninthecommandcontact_info=sys.argv[2]#获取命令中需要加解密的内容ifaction=="encrypt":encrypted_contact_info=encrypt(contact_info)打印(encrypted_contact_info)ifaction=="decrypt":decrypted_contact_info=decrypt(contact_info)print(decrypted_contact_info)在VSCode的终端中执行命令:$C:/Users/admin/anaconda3/envs/xxx/python.exed:/Code/python/sm2_test.pyencrypt123456输出加密后的内容:H24OlVZgSTtevCW138O+C5PlZp8OiD920JnpVr7r9ndkGBWFZUVDD48iIVrZRnamgosV5910m9k0438WpIyi0guEt8F5inG7Y5A51whRfdPZ+qdvWVQxI857CBEzkb3h1bMp1ETQ再执行解密:$C:/Users/admin/anaconda3/envs/xxx/python.exed:/Code/python/sm2_test.pydecryptH24OlVZgSTtevCW138O+C5PlZp8OiD920JnpVr7r9ndkGBWFZUVDD48iIVrZRnamgosV5910m9k0438WpIyi0guEt8F5inG7Y5A51whRfdPZ+qdvWVQxI857CBEzkb3h1bMp1ETQ输出解密内容:123456可正确参考本教程加密解密脚本参数说明,请参考sys.argv[0]表示脚本名称;sys.argv[1]表示要调用的加解密动作;sys.argv[2]表示需要加解密的内容。如上图,命令行参数对应:sys.argv[0]:d:/Code/python/sm2_test.pysys.argv[1]:encryptsys.argv[2]:1234563.补充扩充和说说为什么里面需要转base64。因为经过实际测试,发现sm2的加解密是bytes类型的,直接加密没问题,但是单独解密是不成功的:按住Ctrl,然后鼠标点击解密功能,并直接跳转到源码查看源码:发现源码会转hex类型,但是报错:str对象没有hex属性。但是如果你把解密写在加密之后(也就是加密之后马上解密),你会发现没有问题。fromgmsslimportsm2#sm2的公私钥SM2_PRIVATE_KEY='00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'SM2_PUBLIC_KEY='B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'sm2_crypt=sm2.CryptSM2(public_key=SM2_PUBLIC_KEY,private_key=SM2_PRIVATE_KEY)#加密defencrypt(info):encode_info=sm2_crypt.encrypt(info.encode(encoding="utf-8"))returnencode_info#解密defdecrypt(info):decode_info=sm2_crypt.decrypt(info).decode(encoding="utf-8")returndecode_infoif__name__=="__main__":info="123456"encode_info=encrypt(info)print(encode_info)decode_info=decrypt(encode_info)print(decode_info)输出:b'\x9b\x19\xa8\xc6\xfb\x0b\xf9\xfc\xf15,E*\x9f\x12\xfd\xd6\xd3@\x82N.\x82|\xb2"Y\x86V\xce\x1d\x99\x0e\x8e\xa1\xf6\xfcP\x81x\xbf(:[\xb2UYq\xbc\x84\xe8\x93[\x01\t\xc1\xcf1(E\xcc\xf9{\xe2\x88\xbb(\x90t\xb2\xfa\xd7\xe9\r\x8b\x81\x98\xf9\x85z/\xd5;\x88U\x89Sc\xcfx\xa8\x84\xee,A\xb3\x9de\xa9\xe3\x8e\xd4'123456可以加解密成功,但是现在需要调用的是PythonscriptthroughGo去执行加密和解密,要求加密和解密可以分开(根据命令行传入的参数来判断是加密还是解密),所以这个方法不行。查阅了一些资料,我们得到了第一段代码,通过base64编解码,进行加解密。另一个需要考虑的问题是:直接将加密的二进制数据存储在数据库中可能会影响Go从数据库中读取数据的能力。因为数据库是以二进制字节存储的,所以字段使用的是BinaryField,但是Go并不确定是否有这种类型的字段,可能需要自定义。考虑到项目比较匆忙,马上就要上线测试,没有时间研究Go中如何自定义类型,所以选择换成CharField类型存入数据库。因此,将加密后的二进制字节进行base64编码后存入数据库。解密就是从数据库中读取数据,然后通过base64解码,转换成二进制字节进行解密。还有一个问题是:看到上面加密的二进制字节,发现有很多反斜杠\\,但是反斜杠有转义的功能,比如两个反斜杠\\代表一个反斜杠\(这里可以参考C语言基础语法).考虑到存储读取也可能出现此类问题,最终采用base64进行编解码存储。4.Thesm2publicandprivatekeygenerationcodefromgmssl.utilsimportPrivateKeypriKey=PrivateKey()pubKey=priKey.publicKey()print(priKey.toString())print(pubKey.toString(compressed=False))Thepublicandprivatekeysgeneratedeachtimeare不一样:036e29c4ce1f17b5fd35c88e81793bc9de53f46b3766b779b297e062af9584058d22779ef058a61365d8a427dfd4df5f661535cb515a05567436ab0bd7ff7803a9e31c90630d9221960e614a4228a0a5162bde4072ef3aa9a1ba6fe74d240577五、参考Python命令行参数[Byte[]和Base64之间的转换(加密)](https://www.jianshu.com/p/af1...支持国密SM2/SM3/SM4OpenSSLbranchGmSSLGoAPIdocumentationfor/SM9/ZUC/SSL