土法炼钢兴趣小组的算法知识备份

国密生态全景:GmSSL、铜锁、硬件密码机与合规落地

目录

算法确定了——SM3 替 SHA-256SM4 替 AESSM2 替 ECDSA/X25519国密 TLS 替标准 TLS 1.3。但接下来才是真正的工程问题:用什么库?跑在什么硬件上?怎么过等保和密评?

这篇文章就来系统梳理国密生态:开源实现的选型、硬件加速的路线、合规落地的流程,以及 DTLS 1.3 + 国密在车联网/物联网场景中的最新进展。

国密技术栈全景

一、开源库对比:GmSSL vs 铜锁 vs OpenSSL 3.x

选库是国密改造的第一步。目前主流的三条路线各有优劣。

GmSSL 3.x

GmSSL 由北京大学郭宝安团队主导开发,定位是 纯国密密码库

特点:

编译很简单:

git clone https://github.com/guanzhi/GmSSL.git
cd GmSSL
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install

SM3 哈希示例:

#include <gmssl/sm3.h>
#include <stdio.h>
#include <string.h>

int main(void) {
    SM3_CTX ctx;
    uint8_t digest[SM3_DIGEST_SIZE];
    const char *msg = "hello guomi";

    sm3_init(&ctx);
    sm3_update(&ctx, (uint8_t *)msg, strlen(msg));
    sm3_finish(&ctx, digest);

    printf("SM3: ");
    for (int i = 0; i < SM3_DIGEST_SIZE; i++)
        printf("%02x", digest[i]);
    printf("\n");
    return 0;
}

编译:

gcc sm3_demo.c -lgmssl -o sm3_demo

铜锁(Tongsuo)

铜锁(原 BabaSSL)由蚂蚁集团开源,基于 OpenSSL fork。核心优势是 兼容 OpenSSL API,迁移成本最低。

历史脉络:BabaSSL → 2022 年捐赠开放原子基金会 → 更名铜锁 Tongsuo。

特点:

编译 Tongsuo:

git clone https://github.com/Tongsuo-Project/Tongsuo.git
cd Tongsuo
./config enable-ntls enable-sm2 enable-sm3 enable-sm4
make -j$(nproc)
sudo make install

用 EVP 接口做 SM4-CBC 加密:

#include <openssl/evp.h>
#include <openssl/rand.h>
#include <string.h>
#include <stdio.h>

int sm4_cbc_encrypt(const unsigned char *key,
                    const unsigned char *iv,
                    const unsigned char *in, int in_len,
                    unsigned char *out, int *out_len) {
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    if (!ctx) return -1;

    /* Tongsuo 兼容 OpenSSL EVP,但多了 EVP_sm4_cbc() */
    if (EVP_EncryptInit_ex(ctx, EVP_sm4_cbc(), NULL, key, iv) != 1)
        goto err;
    if (EVP_EncryptUpdate(ctx, out, out_len, in, in_len) != 1)
        goto err;

    int final_len = 0;
    if (EVP_EncryptFinal_ex(ctx, out + *out_len, &final_len) != 1)
        goto err;
    *out_len += final_len;

    EVP_CIPHER_CTX_free(ctx);
    return 0;
err:
    EVP_CIPHER_CTX_free(ctx);
    return -1;
}

OpenSSL 3.x Provider 机制

OpenSSL 3.0 引入了 Provider 架构,可以通过加载外部 provider 来支持 SM2/SM3/SM4,而不需要 fork。

# openssl.cnf 中加载国密 provider
[openssl_init]
providers = provider_sect

[provider_sect]
default = default_sect
smtc    = smtc_sect

[smtc_sect]
module = /usr/local/lib/ossl-modules/smtc.so
activate = 1

命令行验证:

openssl list -providers
openssl dgst -sm3 test.txt
openssl enc -sm4-cbc -in plain.txt -out cipher.bin -K $(xxd -p -l 16 /dev/urandom) -iv $(xxd -p -l 16 /dev/urandom)

优势是对现有 OpenSSL 生态侵入最小,但功能完整度不如前两者——不支持国密 TLS 双证书模式

对比总结

维度 GmSSL 3.x 铜锁 Tongsuo OpenSSL 3.x Provider
API 兼容性 独立 API 兼容 OpenSSL 原生 OpenSSL
国密 TLS 支持 支持(含双证书) 部分(RFC 8998)
SM9/ZUC
双证书
迁移成本 高(需改 API) 低(重链接) 最低(配置加载)
维护方 北大团队 蚂蚁/开放原子 OpenSSL 社区
适用场景 纯国密新系统 存量 OpenSSL 改造 最小侵入探索
FIPS 模式 开发中 支持(非国密)

选型建议

二、硬件加速:从密码卡到 CPU 指令

软件实现够用,但在高并发场景——每秒数万次 TLS 握手、海量数据加密——硬件加速是刚需。

密码卡 / 密码机

国内密码硬件厂商(渔翁信息、三未信安、江南天安等)提供 PCIE 密码卡密码机(独立设备,网络接口)。

接口标准:

通过 PKCS#11 调用密码卡:

#include <pkcs11.h>

/* 初始化并打开会话 */
CK_SESSION_HANDLE session;
C_Initialize(NULL);
C_OpenSession(slot_id, CKF_SERIAL_SESSION | CKF_RW_SESSION,
              NULL, NULL, &session);
C_Login(session, CKU_USER, pin, pin_len);

/* SM4 加密 */
CK_MECHANISM mech = { CKM_SM4_CBC_PAD, iv, 16 };
C_EncryptInit(session, &mech, key_handle);
C_Encrypt(session, plaintext, plain_len, ciphertext, &cipher_len);

典型 PCIE 密码卡性能:

操作 软件(单核) PCIE 密码卡
SM2 签名 ~8,000 次/s ~50,000 次/s
SM2 验签 ~3,000 次/s ~80,000 次/s
SM4-CBC ~500 MB/s ~5 GB/s
SM3 哈希 ~600 MB/s ~8 GB/s

鲲鹏 920:SM3/SM4 硬件指令

华为鲲鹏 920 处理器实现了 ARMv8.4 SM3/SM4 Crypto Extension,在 CPU 指令级别加速国密运算。

检测指令支持:

# Linux
cat /proc/cpuinfo | grep -i sm3
# 或者
lscpu | grep sm
# 输出示例:Flags: ... sm3 sm4 ...

在 GmSSL/Tongsuo 编译时启用:

# Tongsuo
./config enable-sm2 enable-sm3 enable-sm4 enable-arm-sm

# GmSSL
cmake -DENABLE_ARM_SM=ON ..

鲲鹏 920 的指令加速效果:

算法 无硬件指令 鲲鹏 SM 指令 加速比
SM3 ~450 MB/s ~2,100 MB/s 4.7x
SM4-CBC ~380 MB/s ~1,800 MB/s 4.7x
SM4-CTR ~400 MB/s ~3,200 MB/s 8.0x

CTR 模式因为可以并行处理多个块,加速比更高。

Intel QAT

Intel QuickAssist Technology (QAT) 通过异步卸载支持国密算法。需要安装 QAT 驱动和引擎:

# 加载 QAT 引擎
openssl speed -engine qatengine -evp sm4-cbc

QAT 的优势在于 异步卸载——CPU 不用等加密完成就可以处理下一个请求,适合 Nginx 等高并发反向代理。

FPGA 加速

FPGA 方案提供最高的灵活性和吞吐量:

缺点:开发成本高,需要专门的 RTL 工程师,且算法更新不如软件灵活。

方案选择矩阵

场景 推荐方案 原因
Web 服务 TLS 卸载 密码卡 + Nginx 成熟方案,密评认可
信创服务器 鲲鹏 SM 指令 零额外成本,4-8x 加速
高并发 API 网关 Intel QAT 异步卸载,不阻塞 CPU
运营商 / 云 FPGA 100G 线速加密
物联网终端 纯软件 成本敏感,算力有限

三、等保 2.0 与密评:合规不是选做题

国密不是”可以用”,在特定行业是 “必须用”。两个关键合规框架:等保 2.0 和商用密码应用安全性评估(简称密评)。

等保三级对密码的要求

GB/T 22239-2019(等保 2.0)对三级系统的密码要求覆盖多个层面:

关键条款:应采用国家密码管理主管部门认可的密码技术和产品——这就是国密的强制要求来源。

密评:商用密码应用安全性评估

密评是 GB/T 39786-2021 规定的评估流程,比等保更聚焦密码层面。评估覆盖六大方面:

密评六大方面

每个方面的典型检查点:

方面 检查重点 常见问题
物理环境 门禁系统使用国密证书 门禁还在用国际算法
网络通信 TLS 采用国密套件 混用国际/国密未隔离
设备计算 可信启动链使用国密 固件签名用 RSA
应用数据 数据库加密用 SM4 只加密传输不加密存储
密钥管理 密钥在密码机内生成 软件生成密钥
安全管理 有密码应用方案文档 缺少密码使用记录

金融行业时间线

金融行业是国密推进最积极的领域:

务实建议:不要等到必须改才改。双算法并行方案可以渐进式迁移,避免”大爆炸”上线的风险。

等保三级合规检查清单

密评准备阶段最怕”以为都改完了,评审时才发现遗漏”。以下是一份面向等保三级的国密合规自查清单,涵盖算法、证书、密钥管理和协议层面的常见检查点:

  1. 算法白名单检查:系统中所有密码运算是否仅使用 SM2/SM3/SM4/SM9/ZUC?是否残留 RSA/AES/SHA 用于核心业务链路?
  2. 证书链验证:TLS 证书是否由国密 CA(CFCA/BJCA/GDCA 等)签发?证书链是否完整(叶子→中间 CA→根 CA)?
  3. 密钥长度要求:SM2 密钥是否 256 bit?SM4 密钥是否 128 bit?是否存在使用弱密钥长度的遗留配置?
  4. 随机数源合规:密钥生成是否使用硬件 TRNG 或经过认证的 DRBG?是否存在 rand()/Math.random() 等非密码学安全随机源?
  5. 协议版本限制:TLS 是否禁用了 1.0/1.1?国密 TLS 是否正确协商 SM4-GCM-SM3 套件?是否允许降级到非国密套件?
  6. 密钥存储安全:等保三级以上的签名私钥是否存储在硬件密码模块(密码卡/密码机)中?软件密钥存储是否有访问控制?
  7. 密钥生命周期管理:是否有密钥轮换策略?过期密钥是否安全销毁?是否有密钥备份和恢复机制?
  8. 数据完整性保护:日志、审计记录、关键业务数据是否使用 SM3/HMAC-SM3 做完整性校验?
  9. 双证书配置:国密 TLS 是否正确配置了签名证书和加密证书?Certificate 消息中的 KeyUsage 是否正确区分?
  10. 时间戳服务:关键操作的可信时间戳是否使用国密算法签名?

以下脚本可以自动化其中几项基础检查:

#!/bin/bash
# gm_compliance_check.sh — 等保三级国密合规基础自查
# 用法: ./gm_compliance_check.sh <server_host> <port>

HOST=${1:-"localhost"}
PORT=${2:-"443"}
GMSSL=${GMSSL_BIN:-"gmssl"}       # 或 Tongsuo 的 openssl
OPENSSL=${OPENSSL_BIN:-"openssl"}

echo "=== [检查 1] TLS 密码套件协商 ==="
# 检查服务端是否支持国密套件
echo | $OPENSSL s_client -connect ${HOST}:${PORT} \
    -ciphersuites "TLS_SM4_GCM_SM3" \
    -sigalgs "sm2sig_sm3" 2>/dev/null | \
    grep -E "Cipher|Protocol" && \
    echo "[PASS] 国密套件协商成功" || \
    echo "[FAIL] 国密套件协商失败"

echo ""
echo "=== [检查 2] 证书算法检查 ==="
# 检查服务端证书是否使用 SM2
echo | $OPENSSL s_client -connect ${HOST}:${PORT} 2>/dev/null | \
    $OPENSSL x509 -noout -text 2>/dev/null | \
    grep -E "Public Key Algorithm|Signature Algorithm" | \
    grep -qi "sm2" && \
    echo "[PASS] 证书使用 SM2 算法" || \
    echo "[WARN] 证书未使用 SM2(可能是国际证书回退)"

echo ""
echo "=== [检查 3] 协议版本检查 ==="
# 检查是否禁用了 TLS 1.0/1.1
for ver in tls1 tls1_1; do
    echo | $OPENSSL s_client -connect ${HOST}:${PORT} \
        -${ver} 2>&1 | grep -q "alert" && \
        echo "[PASS] ${ver} 已禁用" || \
        echo "[FAIL] ${ver} 仍可连接——应禁用"
done

echo ""
echo "=== [检查 4] 本地密码库版本 ==="
$OPENSSL version 2>/dev/null
$GMSSL version 2>/dev/null || echo "(gmssl 未安装)"
echo "检查是否支持 SM3: "
echo -n "test" | $OPENSSL dgst -sm3 2>/dev/null && \
    echo "[PASS] SM3 可用" || echo "[FAIL] SM3 不可用"

这个脚本只覆盖网络层面的基础检查。密钥存储、随机数源、密钥生命周期等深层检查需要结合系统架构文档人工审计。

常见合规问题

Q:只用 SM4 加密数据库,SM2/SM3 不用,能过密评吗?

不能。密评要求完整性保护(SM3)、身份认证(SM2)、数据加密(SM4)缺一不可。

Q:用了国密算法但是软件实现,密码机必须要吗?

等保三级以上系统的密钥管理通常要求使用硬件密码模块(密码卡/密码机)。纯软件实现在密钥管理评分上会扣分。

Q:公有云上怎么办?

主流云厂商(阿里云、华为云、腾讯云)都提供了云密码机服务(CloudHSM),通过 VPC 网络访问,兼容 PKCS#11/SDF 接口。

四、DTLS 1.3 + 国密:车联网与物联网的前沿

国密 TLS 解决了 TCP 场景,但 UDP 场景——车联网 V2X、物联网 CoAP——需要 DTLS。

DTLS 1.3(RFC 9147)在 TLS 1.3 基础上增加了 epoch/序号、ACK 重传、cookie 防放大攻击和可选 Connection ID。国密 DTLS 的标准化仍有缺口——GM/T 0024-2014 未覆盖 DTLS,行业在自行摸索。

场景 为什么需要 DTLS 国密 DTLS 现状 建议
车联网 V2X(V2V/V2I) 延迟敏感,UDP 传输,不能等 TCP 重传 部分 V2X 平台自行实现 DTLS+SM2/SM3/SM4;无官方密码套件标识 参考 Tongsuo 实验性实现;密切关注标准进展
物联网 CoAP 受限设备基于 UDP;CoAP 标准要求 DTLS 无官方规范;GmSSL TinyGmSSL 可裁剪用于嵌入式 用 PSK 模式减少握手开销;外挂 TRNG 芯片补随机源
实时音视频 WebRTC SRTP 密钥协商走 DTLS-SRTP 无国密适配;国际 SRTP 标准尚无 SM4 密码套件 等标准成熟;当前保持国际算法
工业控制 SCADA 高可靠低延迟;部分基于 UDP 安全等级要求高但标准空白 内网场景可用 IPSec+国密替代

资源受限设备跑国密面临额外挑战:RAM < 64KB(SM2 点乘占内存大→用窗口法优化)、主频 < 100MHz(握手慢→预计算+会话恢复)、无硬件 RNG(→外挂 TRNG)、能耗敏感(→DTLS Connection ID 保持连接减少重握手)。GmSSL 的 TinyGmSSL 分支专门针对这些场景做了裁剪。

五、国密改造实战路径

讲完了技术选型,来看落地的四个阶段。

阶段 1:评估现有系统

首先搞清楚”家底”——现在用了哪些密码算法、在哪里用、怎么用。

# 扫描系统中的密码使用(示例脚本)
#!/bin/bash
echo "=== TLS/SSL 证书 ==="
find /etc -name "*.pem" -o -name "*.crt" | while read f; do
    echo "$f:"
    openssl x509 -in "$f" -noout -text 2>/dev/null | grep -E "Signature Algorithm|Public Key Algorithm"
done

echo "=== Nginx 密码套件 ==="
grep -r "ssl_ciphers\|ssl_protocols" /etc/nginx/

echo "=== Java Keystore ==="
find / -name "*.jks" -o -name "*.keystore" 2>/dev/null | while read f; do
    echo "$f:"
    keytool -list -keystore "$f" -storepass changeit 2>/dev/null | grep "算法\|Algorithm"
done

评估清单:

阶段 2:选择技术方案

根据评估结果选型:

系统选型决策树

阶段 3:双算法并行

不要一步到位。推荐灰度切换方案:

# 双算法并行的伪代码逻辑
def select_algorithm(request):
    """根据策略选择国密或国际算法"""
    # 按流量百分比灰度
    if request.user_id in gm_whitelist:
        return "GM"          # 白名单用户走国密
    if random() < gm_ratio:  # gm_ratio: 0.0 → 1.0 逐步调大
        return "GM"
    return "INTERNATIONAL"

def tls_handshake(client):
    algo = select_algorithm(client.request)
    if algo == "GM":
        # 国密 TLS:SM2 证书 + SM4 加密 + SM3 哈希
        ctx = create_gm_tls_context()
    else:
        # 标准 TLS 1.3:ECDSA + AES-GCM + SHA-256
        ctx = create_standard_tls_context()
    return ctx.handshake(client)

Nginx 的双栈配置示例(Tongsuo 编译的 Nginx):

server {
    listen 443 ssl;

    # 国密证书
    ssl_certificate      /etc/nginx/certs/sm2_sign.pem;
    ssl_certificate_key  /etc/nginx/certs/sm2_sign_key.pem;
    ssl_enc_certificate     /etc/nginx/certs/sm2_enc.pem;
    ssl_enc_certificate_key /etc/nginx/certs/sm2_enc_key.pem;

    # 国际证书(回退)
    ssl_certificate      /etc/nginx/certs/ecdsa.pem;
    ssl_certificate_key  /etc/nginx/certs/ecdsa_key.pem;

    # 双算法套件:优先国密,回退国际
    ssl_ciphers "ECC-SM2-SM4-CBC-SM3:ECC-SM2-SM4-GCM-SM3:TLS_AES_128_GCM_SHA256";
    ssl_protocols TLSv1.2 TLSv1.3;
    # 开启 NTLS(国密 TLS)
    enable_ntls on;
}

阶段 4:全面切换 + 密评

灰度验证通过后:

  1. 全量切换gm_ratio 调到 1.0,观察 7-14 天
  2. 下线国际算法(可选,或保留做冗余)
  3. 准备密评材料:密码应用方案、密钥管理制度、系统拓扑图
  4. 委托测评机构:选择持有商用密码检测资质的机构
  5. 整改:根据测评报告修复问题
  6. 出具报告:获得密评合格结论

常见踩坑点

1. SM2 证书链不完整

# 检查证书链
gmssl certparse -in server.pem
# 确保包含:服务器证书 → 中间 CA → 根 CA
# 很多问题出在少了中间 CA

2. SM4-GCM IV 重用

和 AES-GCM 一样,SM4-GCM 的 IV 绝对不能重用。每个加密操作必须使用唯一的 IV:

/* 正确做法:每次加密生成新 IV */
unsigned char iv[12];
RAND_bytes(iv, sizeof(iv));

3. 时间戳服务遗漏

密评要求对关键操作有可信时间戳,但很多系统只改了加密算法,忘了时间戳服务也要用国密。

4. 日志审计的哈希

操作日志的完整性保护也需要用 SM3,不能继续用 SHA-256。容易被忽略但密评会查。

5. 跨系统对接的编码问题

SM2 签名有两种编码格式——DER 和 (r, s) 裸编码——不同系统可能不一致。提前约定好。

六、展望:国密生态的未来

国密与后量子密码(PQC)的交叉

后量子密码的到来对国密生态提出了新命题:

国际互认

国际互认意味着国密不再是”中国特色”,而是全球密码算法库的一部分。跨境金融、“一带一路”数字基建都能用。

开源社区的角色

国密生态能走多远,很大程度上取决于开源社区:


系列回顾

篇目 链接
SM3 vs SHA-256 哈希算法对比
SM4 vs AES 分组密码对比
SM2 vs ECDSA/X25519 公钥算法对比
国密 TLS vs 标准 TLS 1.3 传输层安全对比
国密生态全景 本文

算法只是起点,生态才是终局。选对库、用好硬件、过好合规——国密落地这条路,每一步都得踩实。


By .