国密SDK架构:两大主流方案的模块划分
咱们做国密改造,第一步就得搞清楚 SDK 里面到底拆成了哪些块。GmSSL 和 OpenSSL 国密分支我前后都折腾过,说实话,两个的设计思路差挺大的。今天咱们就拆开看看它们的模块划分,避坑经验我也会一并聊。
GmSSL:从零造的“全套国密”
GmSSL 的作者是我很佩服的一位前辈。它完全是按照国密标准从零写的一套库,模块划分很清晰,我当初第一次看源码目录,基本能猜到哪块负责什么。
GmSSL 核心模块清单
- libcrypto – 基础密码算法实现(SM2、SM3、SM4、ZUC 等)
- libssl – SSL/TLS 协议层,支持国密套件(ECC_SM4_SM3 等)
- libx509 – 证书解析、SM2 证书链验证
- libpki – PKI 基础设施:证书签发、CRL、OCSP
- libsdf – 密码设备接口(对接加密卡、HSM 的抽象层)
- libsdsm – 分布式签名管理模块(我接触不多,但架构上很清晰)
每个库可以独立编译,也可以静态链接到主程序。我记得有一次项目只用到 SM2 签名验证,我就只编译了 libcrypto,直接把 libssl 和 libx509 跳过了,编译时间少了将近一半。
| 模块名 | 定位 | 典型场景 |
|---|---|---|
| libcrypto | 底层算法引擎 | 纯加解密、哈希、密钥生成 |
| libssl | 通信协议封装 | HTTPS 国密握手、TLS 1.3 国密套件 |
| libx509 | 证书栈 | SM2 证书解析、双向认证 |
| libsdf | 硬件抽象层 | 适配国产加密卡、UKey |
注意一个小细节:GmSSL 的 libcrypto 里把 SM2 签名和 SM2 加密分成了两个文件 sm2_sign.c 和 sm2_enc.c,刚开始我不理解,后来发现国密标准对签名和加密的 ASN.1 格式要求不一样,拆开反而好维护。
OpenSSL 国密分支:在巨人肩膀上打补丁
OpenSSL 官方其实一直没有完整支持国密,咱们用的多是华为或者银联维护的国密分支。它们没动 OpenSSL 的整体架构,而是在现有模块里“插桩”。说白了就是 复用 OpenSSL 的 EVP 框架 + ENGINE 机制,把 SM2/SM3/SM4 注册成新的算法。
我个人习惯把 OpenSSL 国密分支的模块划分理解为三层:
- 算法层 – 在
crypto/ec里新增 SM2 曲线参数,在crypto/evp里注册 SM3 哈希和 SM4-CBC。 - 引擎层 – 通过
dynamic ENGINE加载国密算法,或者直接内嵌built-in ENGINE(如 engine/gmssl.so)。 - 协议层 – 在
ssl/t1_lib.c里修改 cipher suites 列表,添加SM2-WITH-SM4-SM3。
我曾经在适配华为版 OpenSSL 国密分支时踩了一个坑:分支里把 SM2 密钥结构挂在 EC_KEY 上,但标准 EC_KEY 的公开接口不支持国密曲线 OID 1.2.156.10197.1.301。后来只能在 ec_cvt.c 里手动加一段 OID 映射。如果你也用 OpenSSL 国密分支,记得先确认你的版本有没有打上这个补丁。
模块划分对比:GmSSL vs OpenSSL国密分支
| 维度 | GmSSL | OpenSSL国密分支 |
|---|---|---|
| 独立程度 | 完全自研,无 OpenSSL 依赖 | 基于 OpenSSL,需同步主线更新 |
| 模块粒度 | 细(libcrypto/libssl/libx509/…) | 粗(在 OpenSSL 现有模块内打补丁) |
| 国密算法集成方式 | 内建、无外部引擎 | EVP + ENGINE 动态加载 |
| 证书链支持 | 原生 SM2 证书解析 | 通过 OID 映射 + 扩展 patch |
| 硬件适配 | 提供 libsdf 统一接口 | 需自己写 ENGINE 桥接 |
| 内存泄漏风险 | 相对可控(代码量少) | 较高(patch 可能和主线冲突) |
为什么要掌握模块划分?因为做适配改造时,你不可能每次都给整个 SDK 打补丁。比如你只需要 SM3 哈希,在 GmSSL 里只需要 #include "gmssl/sm3.h",在 OpenSSL 国密分支里则要 EVP_MD_CTX_new + EVP_DigestInit_ex 带 EVP_sm3() 参数。模块边界不同,接口调用习惯完全不同。
一张图看懂模块关系
这是我根据实际项目画的一张简图,把两个框架的模块层次放在一起对比。你注意看:GmSSL 各层互不依赖,而 OpenSSL 国密分支所有国密能力都寄生在已有的 EC/EVP/SSL 模块里。
重要提醒:模块划分决定了你改代码时的影响面。如果你项目里已经有大量 OpenSSL 调用(比如 EVP_ 系列),强上 GmSSL 会导致接口重写,不如直接用 OpenSSL 国密分支。反过来,如果你从零开始做国密产品,GmSSL 更干净、合规审计也更容易通过。
好了,模块划分大概就这些。下一块咱们会聊到各模块的接口调用方式,到时候我会直接放几个实际改造中用过的代码片段,你们看完就能拿来用。