国密算法库(gmssl)入门:安装、基本用法、SM2密钥生成示例

做国密开发,绕不开一个库——gmssl。它封装了SM2/SM3/SM4等国密标准,Python调用起来非常方便。我个人习惯用gmssl做原型验证,因为它够轻量,文档也还算清晰。这节咱们就把它装好、跑一遍,再生成一对SM2密钥。

gmssl是什么?为什么选它?

gmssl是国密算法的Python实现,底层依赖OpenSSL,但接口更Pythonic。我在项目中对比过好几个国密库,最后选gmssl的原因很简单:

  • 纯Python接口,不用理解复杂的C代码
  • 同时支持SM2/SM3/SM4,一个库搞定
  • 社区活跃,遇到问题容易搜到解决方案

说到底,它帮我们省去了手搓椭圆曲线算法的麻烦,咱们只需调API就行。

提示:gmssl目前主要维护在GitHub上,pypi版本更新较快。生产环境建议锁定版本号,避免接口变动。

安装gmssl

安装非常简单,一条命令搞定:

pip install gmssl

如果你在国内,加个镜像源会快很多:

pip install gmssl -i https://pypi.tuna.tsinghua.edu.cn/simple

装完之后验证一下:

python -c "import gmssl; print(gmssl.__version__)"

我见过有人装了之后报ImportError: No module named 'gmssl',多半是pip和python版本对不上。建议用虚拟环境,避免污染系统Python。

基本用法快速上手

gmssl主要提供三个核心模块:

模块说明常用类/函数
gmssl.sm2SM2非对称加密/签名SM2Key, CryptSM2, Sign
gmssl.sm3SM3哈希sm3_hash
gmssl.sm4SM4对称加密CryptSM4, SM4_ENCRYPT, SM4_DECRYPT

实际项目中,你大概率同时用到这三种算法。比如先SM2加密会话密钥,再用SM4加密业务数据。嗯,这里要注意:gmssl的SM2默认使用16进制字符串作为输入输出,不是字节流,设计时别搞混了。

SM2密钥生成示例

直接上代码。咱们生成一对SM2密钥,然后看看私钥、公钥长什么样。

from gmssl import sm2

# 创建一个SM2密钥对象
sm2_key = sm2.SM2Key()

# 生成密钥对
private_key_hex = sm2_key.generate_private_key()
public_key_hex = sm2_key.generate_public_key(private_key_hex)

print("私钥(hex):", private_key_hex)
print("公钥(hex):", public_key_hex)

# 验证:用私钥签名,用公钥验签
data = "hello gmssl".encode()
random_hex = "1234567890abcdef1234567890abcdef"
sign_hex = sm2_key.sign(data, private_key_hex, random_hex)
print("签名:", sign_hex)

verify_ok = sm2_key.verify(sign_hex, data, public_key_hex)
print("验签结果:", verify_ok)

注意random_hex这个参数:它其实是SM2签名算法要求的随机数k。我曾在项目里随手写了个固定值,结果每次签名都一样,差点被攻击方利用。这个k必须每次随机生成,最好用系统安全的随机数源。

生成的私钥是一串64字符的十六进制数(32字节),公钥是130字符(65字节,含04前缀)。你可以直接存文件,或者转成PEM格式。gmssl也提供了export_key方法,但我习惯自己封装,方便兼容其他库。

警告:私钥一旦泄露,所有加密数据都可被破解。生产环境请务必使用硬件安全模块(HSM)或密钥管理系统保管私钥,不要明文写死在代码里。我曾经见过把私钥放在配置文件里上传到Git的…嗯,那场面很惨。

SM2密钥生成流程图

下面这张图展示了密钥生成的完整流程,你可以对照代码理解每个步骤的作用。

SM2密钥生成流程 随机数生成 系统安全随机数 私钥生成 大整数 dB (32字节) 公钥计算 PB = dB * G (椭圆曲线点) 输出密钥对 hex / PEM / DER 私钥必须保密,公钥公开 每个步骤都依赖前一步结果

避坑指南:我踩过的几个坑

  • Python版本问题:gmssl要求Python 3.6+,我曾在CentOS自带2.7上装了半天才发现不支持。建议直接用Python 3.8~3.10。
  • 密钥长度:SM2私钥固定32字节,公钥65字节(含04)。如果你从其他系统拿到压缩公钥(33字节),需要先解压才能导入gmssl。我写过一段解压函数,有兴趣可以留言。
  • 随机数重用:前面提到的签名随机数必须唯一。如果你用多线程生成签名,小心竞争条件导致重复随机数。最好用secrets._hex(32)替代自己写的随机数。
  • 编码问题:gmssl默认输入输出是hex字符串。如果你拿到的是base64格式,记得先转成hex再传参。我在对接某第三方接口时,对方发来的公钥是base64编码,没转换直接传进去,结果验签一直失败……

小结

gmssl的安装和基本使用就这么简单。你可以试试把生成的密钥对存成PEM文件,或者用SM2加密一段小数据。下个章节咱们会深入SM2的加密解密接口,到时候代码量会多一些,但原理是一样的。先把这个基础打牢。

核心提要:
  • 安装:pip install gmssl
  • 密钥生成:SM2Key().generate_private_key() + .generate_public_key()
  • 私钥32字节hex,公钥130字符hex(含04)
  • 签名签名随机数必须每次不同