SM2是国产的非对称加密算法,对其软件层面实现支持的库有很多,比如gmssl和bouncycastle,这里主要记录gmssl的Python用法。
不同的库相互之间的加解密可能存在不兼容的情况
如果需要使用对方的公钥进行加密数据,最好双方都使用同一个软件实现库,不然可能出现无法解密的情况:)
比如userA使用gmssl库和userB提供的公钥进行SM2数据加密,但是userB使用bouncycastle库和其私钥进行解密,这个时候就可能出现Invalid point encoding 115 … 的异常。
Invalid point encoding 115 at Org.BouncyCastle.Math.EC.ECCurve.DecodePoint(Byte[] encoded) in /_/crypto/src/math/ec/ECCurve.cs:line 457\n at Org.BouncyCastle.Crypto.Engines.SM2Engine.Decrypt(Byte[] input, Int32 inOff, Int32 inLen) in /_/crypto/src/crypto/engines/SM2Engine.cs:line 119\n at LongshineWS.Api.Utils.Sm2Utils.Decrypt(Byte[] encodeData, AsymmetricKeyParameter privateKey)\n at LongshineWS.Api.Utils.Sm2Utils.Decrypt(String content, String privateKey)\n at WebApi.Core.Controllers.WS.RMBasicController.BimRemoteSyncService(JObject jo)
下面主要使用两个文件main.py和security.py
main.py
Python
# -*- coding: utf-8 -*-
from security import SM2, generate_key_pair
# 两个模式,模式不同会影响加解密
MODE_C1C2C3 = 0
MODE_C1C3C2 = 1
if __name__ == "__main__":
# 这里的公钥和私钥都是以16进制的形式存在的,如果对方给的公钥是base64字符或者Bytes格式,则需要先转换处理一下
private_key, public_key = generate_key_pair()
print("private_key is:\n{}".format(private_key))
print("public_key is:\n{}".format(public_key))
plaintext = "Hello World"
print("\nplaintext is :{}".format(plaintext))
# 如果使用对方提供的公钥进行加密,则这里参数不用传递私钥
sm2 = SM2(public_key=public_key, private_key=private_key, mode=MODE_C1C2C3)
ciphertext = sm2.encrypt(plaintext)
print("ciphertext is :{}".format(ciphertext))
plaintext = sm2.decrypt(ciphertext)
print("plaintext is :{}".format(plaintext))
private_key is:
d20728b5e0d49e041d55fdfc2897016f5e7f68f946f3a76345958fcb08646524
public_key is:
04a107c2f6a1c3ceb9ae9f1e84b84f5fd0edf2fb952b758a4955649b886fb9b6a56fa976a561b244a7cf73b0f24aea56000acb7917de43636136e6ab6dadd49548
plaintext is :Hello World
ciphertext is :DIxIDB7ln7Lb1/A5cE26fl6w/BDXt03L6hLhTKqGNiRctj1eZN88neBf6UPrGm1Hj4E/y4BWNcPYIhUooBkZy9DncXBXJDFbSR33GPRUMjlyPe+niVYWLHAevgRSmCvU343QgLdrK5HCSSg=
plaintext is :Hello World
gmalg和gmssl可能会需要安装
pip install gmalg -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install gmssl -i https://pypi.tuna.tsinghua.edu.cn/simple
security.py
Python
# -*- coding: utf-8 -*-
from gmssl.sm2 import CryptSM2
from base64 import b64encode, b64decode
import gmalg
def generate_key_pair():
private_key, public_key = gmalg.sm2.SM2().generate_keypair()
private_key = private_key.hex()
public_key = public_key.hex()
return private_key, public_key
class SM2:
def __init__(self, public_key = None, private_key = None, mode=1, asn1=False):
self.public_key = public_key
self.private_key = private_key
self.sm2 = None
self.asn1 = asn1
self.mode = mode
pass
def encrypt(self, plaintext):
if self.sm2 == None:
self.sm2 = CryptSM2(public_key=self.public_key, private_key=self.private_key, asn1=self.asn1, mode=self.mode)
encode_plaintext = plaintext.encode(encoding="utf-8")
ciphertext_bytes = self.sm2.encrypt(encode_plaintext)
ciphertext_base64 = b64encode(ciphertext_bytes).decode()
return ciphertext_base64
def decrypt(self, ciphertext_base64):
if self.sm2 == None:
self.sm2 = CryptSM2(public_key=self.public_key, private_key=self.private_key, asn1=self.asn1, mode=self.mode)
ciphertext_bytes = b64decode(ciphertext_base64.encode())
encode_plaintext = self.sm2.decrypt(ciphertext_bytes)
plaintext = encode_plaintext.decode(encoding="utf-8")
return plaintext