4. 国密开发环境搭建:OpenSSL 国密模块、GMSSL 库、GmSSL 命令行工具安装

说实话,国密开发环境搭建这件事,我见过太多人在这里踩坑了。不是装不上,就是装完验不了,甚至有人把系统 OpenSSL 搞崩了重装系统…… 其实没什么难的,就是三个工具各自怎么装、怎么验证、怎么共存。这一章我带你把每一步走通。

4.1 三个工具,各管一摊

先搞清楚我们要装什么。国内做国密,绕不开下面三个东西:

工具 / 库 定位 特点
OpenSSL 国密模块 官方补丁 在标准 OpenSSL 上打国密补丁,覆盖 SM2/SM3/SM4
GMSSL 库 国产独立实现 完全自主的国密密码库,不支持国际算法
GmSSL 命令行工具 命令行 CLI 基于 GMSSL 库的命令行工具,类似 openssl 的 sm2/sm3/sm4

你看,OpenSSL 国密模块是在原来 OpenSSL 上添砖加瓦;GMSSL 是另起炉灶;GmSSL 则是给 GMSSL 套了个命令行壳。我个人习惯把它们全装上,开发时用 GMSSL 库直接调用,CI/CD 里用 GmSSL 命令行做签名验签,生产环境则更倾向加固后的 OpenSSL 国密模块。

我的经验: 别试图只用一种工具应付所有场景。CI/CD 流水线里,不同阶段可能要用不同接口。全装上也不会冲突,关键是把 PATH 和库路径管好。

4.2 从 OpenSSL 国密模块开始

这个最常用,但也最容易翻车。为什么要打补丁?因为官方 OpenSSL 1.1.1 之后才原生支持国密,而且很多发行版根本没打开。我从源码编一遍给你看。

# 1. 下载 OpenSSL 1.1.1 源码(推荐 1.1.1w)
wget https://www.openssl.org/source/openssl-1.1.1w.tar.gz
tar -xzf openssl-1.1.1w.tar.gz
cd openssl-1.1.1w

# 2. 应用国密补丁(补丁从 gmssl.org 获取)
wget https://gmssl.org/download/openssl-1.1.1w_gmssl.patch
patch -p1 < openssl-1.1.1w_gmssl.patch

# 3. 配置并编译,打开国密扩展
./config --prefix=/usr/local/openssl-gm enable-sm2 enable-sm3 enable-sm4
make -j$(nproc)
sudo make install
注意: --prefix 一定要指定独立路径!我曾经图省事直接覆盖系统 OpenSSL,结果 ssh 连不上了…… 所以建议装到 /usr/local/openssl-gm 这样的路径,不影响系统默认 OpenSSL。

验证很简单:

/usr/local/openssl-gm/bin/openssl version
# 看到 "OpenSSL 1.1.1w  11 Sep 2023" 说明编对了

# 测试 SM3 哈希
echo -n "hello" | /usr/local/openssl-gm/bin/openssl dgst -sm3
# 输出应该是一串 SM3 摘要

4.3 GMSSL 库——纯国产密码库

GMSSL 是国密局推荐的参考实现,纯 C 语言,没有历史包袱。我项目里处理国密证书、签名验签都优先用它。

# 下载 GMSSL 源码(推荐 v2.0 稳定版)
git clone -b v2.0 https://github.com/guanzhi/GmSSL.git
cd GmSSL

# 编译安装
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install

# 默认装到 /usr/local/lib 和 /usr/local/include/GmSSL

装完后写个简单 C 程序验证:

// test_sm3.c
#include <GmSSL/sm3.h>
#include <stdio.h>

int main() {
    unsigned char dgst[32];
    SM3_CTX ctx;
    sm3_init(&ctx);
    sm3_update(&ctx, (unsigned char*)"hello", 5);
    sm3_final(&ctx, dgst);
    // 打印 32 字节摘要
    for (int i = 0; i < 32; i++) printf("%02x", dgst[i]);
    printf("\n");
    return 0;
}
gcc test_sm3.c -lGmSSL -o test_sm3
./test_sm3
# 输出应与 OpenSSL SM3 结果一致
避坑: 链接时用 -lGmSSL,不是 -lgmssl。大小写搞错会报 undefined reference。我曾经因为这个浪费了半小时…… 嗯,记牢。

4.4 GmSSL 命令行工具

这个工具和 OpenSSL 命令行用法几乎一样,只是把算法换成了国密。我推荐 CI/CD 里用它对文件签名、验签,因为命令简单,不需要写代码。

# 从 GitHub 下载预编译二进制,或源码编译
git clone https://github.com/guanzhi/GmSSL.git
cd GmSSL  # 没错,和上面的 GMSSL 库是同一个仓库
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/gmssl-cli
make -j$(nproc)
sudo make install

# 使用 gmssl 命令(注意是 gmssl 不是 openssl)
/usr/local/gmssl-cli/bin/gmssl version
# 输出类似 "GmSSL 2.0"

生成 SM2 密钥对和签名示例:

# 生成 SM2 私钥
/usr/local/gmssl-cli/bin/gmssl ecparam -genkey -name sm2 -out sm2_priv.pem
# 导出公钥
/usr/local/gmssl-cli/bin/gmssl ec -in sm2_priv.pem -pubout -out sm2_pub.pem
# 对文件签名
/usr/local/gmssl-cli/bin/gmssl sm2sign -in data.bin -inkey sm2_priv.pem -out data.sig
# 验签
/usr/local/gmssl-cli/bin/gmssl sm2verify -in data.bin -sig data.sig -pubkey sm2_pub.pem

你看,和 OpenSSL 操作流程一模一样,只是算法参数换了。我建议把 gmssl 命令加到 CI 镜像的 PATH 里,后面章节讲流水线集成时直接调用。

4.5 环境验证清单

三个工具装完后,我习惯跑一遍快速验证,保证所有国密算法都可用。下面这个表格你直接抄过去当 check list:

验证项 命令 预期结果
OpenSSL 国密扩展 openssl version + openssl sm3 不报错 版本 1.1.1w,SM3 正常
GMSSL 库 gcc test_sm3.c -lGmSSL 编译通过 可执行文件输出 32 字节摘要
GmSSL 命令行 gmssl version 显示 GmSSL 2.0
SM2 签名验签 上节示例命令 验签通过,返回 OK
SM4 加解密 gmssl enc -sm4-cbc -in data.bin -out data.enc -K ... -iv ... 能加密且解密恢复原文
我的习惯: 把上面验证命令写成一个 shell 脚本 verify_gm_env.sh,每次换环境或更新版本后跑一遍,一分钟知道环境是否可用。脚本放在项目根目录,和 CI 共享。

4.6 环境结构图

为了让你全局看清楚这三个工具的关系,我画了一张图。绿的是源码构建入口,蓝的是最终产物:

国密开发环境搭建总览 OpenSSL 源码 国密补丁(patch) 编译安装 /usr/local/openssl-gm GMSSL 源码 CMake 编译 /usr/local/lib(库) GmSSL 源码 CMake 编译 /usr/local/gmssl-cli 注意 三个工具安装路径独立,互不干扰

说实话,这套环境装好,后面所有的 CI/CD 集成才有根基。你按上面的步骤一个个来,半小时内肯定搞定。要是碰到编译错误,多半是依赖缺了——build-essential、cmake、perl 这些基础包先装上。我建议在干净的 Ubuntu 20.04/22.04 上实验,最容易复现。

曾经有位同事: 直接在 CentOS 6 上编 OpenSSL 1.1.1,结果缺 C99 编译器,折腾半天。所以环境操作系统最好选新一点的,至少 gcc 5+。