国密算法SM2作为我国自主知识产权的非对称密钥标准,在金融、政务等领域广泛应用。实际开发中,常需本地工具与云服务协同工作,兼容性成为关键痛点。本文通过完整互操作验证,展示EasyGmSSL库与腾讯云KMS在SM2加解密、签名验签上的完美兼容性,特别突出其在极致易用性、格式灵活性和协议兼容性方面的优势。
通过腾讯云KMS生成数据加密密钥(DEK),生成时上传本地SM2公钥到KMS加密DEK,再由本地私钥解密,实现云端和本地端无缝密钥交换。
腾讯云 KMS 在生成数据密钥时,接口中允许传入一把本地的 SM2 公钥。
生成数据密钥的接口会使用这把公钥对数据密钥明文做加密,然后将密文返回,本地使用 SM2 私钥进行解密得到密文,通过这种方式实现信道安全传输,完成安全且合规的密钥交换。
from __future__ import annotations
import base64
import os
from easy_gmssl import EasySm2EncryptionKey , SM2CipherMode
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.kms.v20190118 import kms_client , models
cred = credential.Credential(os.getenv("CLOUD_SECRET_ID") ,
os.getenv("CLOUD_SECRET_KEY"))
client = kms_client.KmsClient(cred , "ap-guangzhou")
try:
# 生成本地 SM2密钥对
# 去 KMS-API 侧生成 DEK,并使用本地的 SM2公钥加密 DEK 明文得到 DEK 密文
with open('test_sm2_public.pem' , 'rb') as f:
sm2_pub_key_bytes = f.read()
req = models.GenerateDataKeyRequest()
req.KeyId = '7bab23ea-1a0e-11ee-a405-52540078f78b'
req.NumberOfBytes = 32
req.EncryptionAlgorithm = 'SM2_C1C3C2_ASN1'
req.EncryptionPublicKey = sm2_pub_key_bytes.decode('utf-8')
resp = client.GenerateDataKey(req)
print(resp.to_json_string(indent = 4))
####################################################
# 使用本地的 SM2私钥解密 KMS 返回的 DEK 密文数据
decrypt_sm2 = EasySm2EncryptionKey()
decrypt_sm2.load_sm2_private_key('./test_sm2_private.pem' , '12345678')
cipher = base64.b64decode(resp.Plaintext)
plain_data = decrypt_sm2.Decrypt(cipher_data = cipher ,
cipher_mode = SM2CipherMode.C1C3C2_ASN1)
print(f'original dek data: {plain_data}, length: {len(plain_data)}')
except TencentCloudSDKException as err:
print(err)
本地使用 KMS SM2 公钥加密明文得到密文,KMS 控制台或云 API 使用 SM2 私钥解密密文得到明文,实现云端和本地端无缝明文数据交换。
腾讯云 KMS 的 SM2 解密接口,允许传入格式为 C1C3C2_ASN1 的密文进行解密。
控制台也提供了 SM2 解密的工具,可以快速进行解密验证。
本地使用 EasyGmSSL 和 腾讯云 KMS 进行 SM2 加解密的互通验证。
from __future__ import annotations
import base64
import os
from easy_gmssl import EasySm2EncryptionKey , SM2CipherMode
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.kms.v20190118 import kms_client , models
cred = credential.Credential(os.getenv("CLOUD_SECRET_ID") ,
os.getenv("CLOUD_SECRET_KEY"))
client = kms_client.KmsClient(cred , "ap-guangzhou")
try:
# KMS公钥加密,然后去 KMS 控制台使用私钥解密
# 密钥 ID:5f6b0824-bbf1-11ee-968e-5254000a5333
encrypt_sm2 = EasySm2EncryptionKey()
encrypt_sm2.load_sm2_pub_key('./sm2_encrypt.pem')
plain = b'hello,world\n'
ret = encrypt_sm2.Encrypt(plain)
print(f'using kms sm2 public key to encrypt plain, got cipher in base64: {ret}')
req = models.AsymmetricSm2DecryptRequest()
req.KeyId = '5f6b0824-bbf1-11ee-968e-5254000a5333'
req.Ciphertext = ret
resp = client.AsymmetricSm2Decrypt(req)
print(resp.to_json_string(indent = 4) , base64.b64decode(resp.Plaintext) == plain)
assert base64.b64decode(resp.Plaintext) == plain , 'kms decrypt failed, decrypted data is invalid'
except TencentCloudSDKException as err:
print(err)
腾讯云 KMS 提供非对称密钥的签名验签云 API 接口
控制台也提供针对消息原文和消息摘要的签名验签工具,用户可以在控制台快速完成签名验签的验证流程。
云端签名 → 本地验签
from __future__ import annotations
import base64
import os
from easy_gmssl import EasySM2VerifyKey , EasySM3Digest , EasySm2Key , SignatureMode
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.kms.v20190118 import kms_client , models
cred = credential.Credential(os.getenv("CLOUD_SECRET_ID") ,
os.getenv("CLOUD_SECRET_KEY"))
client = kms_client.KmsClient(cred , "ap-guangzhou")
try:
plain = os.urandom(2048)
req = models.SignByAsymmetricKeyRequest()
req.KeyId = '6b9a11ff-bbf1-11ee-829f-5254007a9eec'
req.Algorithm = 'SM2DSA'
req.Message = base64.b64encode(plain).decode('utf-8')
req.MessageType = 'RAW'
resp = client.SignByAsymmetricKey(req)
print(resp.to_json_string(indent = 4))
signature = resp.Signature
signature_bytes = base64.b64decode(signature)
test_verify = EasySM2VerifyKey(pem_public_key_file = './sm2_verify.pem')
test_verify.UpdateData(plain)
ret = test_verify.VerifySignature(signature_data = signature_bytes , signature_mode = SignatureMode.RS_ASN1)
print(f'verify sm2 signature for plain data: {ret}')
except TencentCloudSDKException as err:
print(err)
本地摘要 → 云端签名 → 本地验签
from __future__ import annotations
import base64
import os
from easy_gmssl import EasySM2VerifyKey , EasySM3Digest , EasySm2Key , SignatureMode
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.kms.v20190118 import kms_client , models
cred = credential.Credential(os.getenv("CLOUD_SECRET_ID") ,
os.getenv("CLOUD_SECRET_KEY"))
client = kms_client.KmsClient(cred , "ap-guangzhou")
try:
plain = os.urandom(2048)
h = EasySM3Digest()
h.UpdateData(plain)
hash_bytes , hash_len , plain_len = h.GetHash()
print(f'plain sm3 hash:{base64.b64encode(hash_bytes).decode()}, length:{hash_len}, plain_len:{plain_len}')
req = models.SignByAsymmetricKeyRequest()
req.KeyId = '6b9a11ff-bbf1-11ee-829f-5254007a9eec'
req.Algorithm = 'SM2DSA'
req.Message = base64.b64encode(hash_bytes).decode('utf-8')
req.MessageType = 'DIGEST'
resp = client.SignByAsymmetricKey(req)
print(resp.to_json_string(indent = 4))
signature = resp.Signature
signature_bytes = base64.b64decode(signature)
verify = EasySm2Key()
verify.load_sm2_pub_key('./sm2_verify.pem')
ret = verify.verify_digest_signature(hash_bytes , signature_bytes)
print(f'verify sm2 digest signature for plain sm3 hash: {ret}')
except TencentCloudSDKException as err:
print(err)
双模式全支持
pip install easy_gmssl
MacOS/Linux安装一条命令搞定。
密钥加解密模式多样化 新增了多种SM2密钥加解密模式选择,包括C1C3C2、C1C3C2_ASN1、C1C2C3、C1C2C3_ASN1。这些模式为不同应用需求提供了更灵活的加密策略,无论是在对加密效率有要求,还是对加密数据格式兼容性有考量的场景下,都能找到合适的解决方案。
签名验签模式扩展 在SM2签名验签时,增加了RS_ASN1、RS两种模式选择,适应不同的签名规范和验证场景,使签名验签操作更加贴合实际业务需求。
from __future__ import annotations
from easy_gmssl import EasySm2EncryptionKey, SM2CipherFormat, SM2CipherMode
enc = EasySm2EncryptionKey()
plain = 'hello,world'
# 遍历当前支持的所有 SM2 加解密算法模式
# 当前支持的模式包括:
# C1C3C2_ASN1、C1C3C2、C1C2C3_ASN1、C1C2C3
for mode in SM2CipherMode:
print(mode, '密文 in Hex:', enc.Encrypt('hello,world'.encode('utf-8'), mode, SM2CipherFormat.HexStr))
密钥读取便捷化 允许用户轻松读取SM2公钥、私钥的十六进制明文,方便在调试、密钥管理等环节快速获取关键信息,提升开发效率。
from __future__ import annotations
from easy_gmssl import EasySm2Key
test = EasySm2Key()
print('公钥数据 In Hex:', test.get_sm2_public_key_in_hex())
print('私钥数据 In Hex:', test.get_sm2_private_key_in_hex())