首页 / 资讯中心 / 文章详情

GmSSL-3.1.1 国密改造:编译、SM算法调用与双证书握手

GmSSL-3.1.1 国密改造:编译、SM算法调用与双证书握手 ★ FEATURED ARTICLE
简介GmSSL-3.1.1 是一套支持国密算法的 SSL/TLS 源码实现面向密码学与网络安全开发者、协议研究人员及高校相关课程学习者可用于搭建国密通信实验环境、分析证书与协议交互流程也适合作为二次开发、功能裁剪与平台移植的基础代码。压缩包共 329 个文件约 397KB以 218 个 C 源文件和 72 个 C 头文件为主体并配有 shell 构建脚本、PEM 证书与 CRL 样例、CMake/YAML 配置及少量说明文档代码覆盖 X.509 证书扩展、CMS、TLS 1.3、SM9、ASN.1 编解码、吊销列表处理与密码设备适配等模块。源码层次便于按主题查阅协议实现和算法调用读者可据此梳理国密 SSL 的握手流程、证书链校验、加密套件选择与算法接口关系针对移植或排错场景快速定位相关实现。已有 233 人学习能为教学演示、安全研究、合规验证和工程移植提供较完整的参考。1. 拿到 GmSSL-3.1.1 先别急着 make它补的到底是哪块短板你手上有个系统要过密评对接方只回了一句话“证书换成 SM2 双证书走国密 SSL”。然后你打开终端敲openssl ecparam -list_curves翻了三屏也没找到 sm2p256v1——这就是绝大多数人第一次接触国密改造时的入口。GmSSL-3.1.1.tar.gz 就是为这种情况准备的一套完整源码包解开之后是一整条工具链包含 SM2/SM3/SM4/SM9 算法库、一套 OpenSSL 风格的 EVP/X509/BIO 抽象层以及一个支持国密双证书握手的 TLS 实现外加一组能直接敲的命令行工具。它解决的是“算法、证书、协议三层必须能串起来”的问题。单独算一个 SM3 摘要用什么库都行但你手里那张 SM2 证书能不能被对端认、握手时协商出的套件对不对、加密证书私钥该不该托管这些都得有完整实现才能验证。适合做国密改造的后端、要对接加密机或国密网关的、以及在国产化平台上做算法移植的人。如果只是想跑个算法作业这套东西反而偏重。2. 从 tar.gz 到可执行文件目录结构、编译开关与产物验证2.1 解开先看树四个必须弄清的位置源码包的目录结构基本沿用 OpenSSL 那套习惯但有三个地方跟 OpenSSL 不一样先认清楚能省掉后面一半的困惑。路径内容排查时该看什么include/gmssl/对外头文件sm2.h、sm3.h、sm4.h、x509.h、tls.h函数原型和结构体字段小版本之间的差异全在这里src/算法与协议实现判断某个特性有没有编进来比如 SM9、ZUCtools/命令行入口与子命令表子命令名、参数名以这里为准网上教程经常对不上tests/单元测试与测试向量编完先跑它比你自己写用例快demos/最小调用样例找“某个接口该怎么调”的最短路径第一个不一样的地方库名是libgmssl不是libssl/libcrypto。这意味着你不能指望用-lssl -lcrypto链上它也意味着装到系统目录后不会顶掉系统的 OpenSSL但反过来如果你的构建脚本里写死了-lcrypto链接时就会静默地链到系统 OpenSSL 上去行为完全不对。第二个不一样头文件包含方式是gmssl/sm2.h不是openssl/sm2.h。第三个命令行程序名就叫gmssl和库同名用gmssl 子命令的形态调用比如gmssl sm3、gmssl sm2sign。这种设计和openssl dgst是同一种思路但子命令的名字是重新起过的照抄 OpenSSL 教程会全部报错。2.2 config 的四个开关别让安装路径和系统 OpenSSL 打架Unix 侧的构建还是configmake那一套Windows 侧源码里另带 CMake 工程。Linux 上我一般这么走tar xzf GmSSL-3.1.1.tar.gz cd GmSSL-3.1.1 # --prefix 装到独立目录这是避免和系统 OpenSSL 冲突的关键一步 # --openssldir 指定配置与证书的默认查找路径 # no-shared 只出静态库部署单文件省事 # no-asm 关闭汇编优化交叉编译和老板子上更稳 ./config --prefix/opt/gmssl --openssldir/opt/gmssl/ssl no-shared no-asm make -j$(nproc) make test # 单元测试先过这一关再谈别的 sudo make install四个开关各自的影响值得说清楚。--prefix是最重要的一个装到/usr/local下会和系统自带的 OpenSSL 头文件混在一起编译时-I/usr/local/include一旦把openssl/和gmssl/同时暴露出来你会在某个莫名其妙的undefined reference上耗掉半天。装到/opt/gmssl这种独立前缀需要的时候用-I/opt/gmssl/include -L/opt/gmssl/lib显式指定路径清楚、卸载也干净。no-shared决定你拿到的是libgmssl.a还是libgmssl.so。静态库的好处是部署时不用管LD_LIBRARY_PATH坏处是链接顺序变敏感——静态库必须放在依赖它的目标文件后面gcc main.c -lgmssl能过gcc -lgmssl main.c就会报一堆 undefined。这一点在写 Makefile 时特别容易翻车。no-asm看场景。x86 上有 SM4 的向量化实现关掉之后吞吐会掉一截但如果你要交叉编译到某个没验证过的架构或者编译器版本比较老导致汇编段报错先关掉把流程跑通再回头开。--openssldir影响的是默认查找路径做容器镜像时建议显式指到镜像内的路径别让它去读宿主机的。make test这一步不要跳。它跑的是仓库自带的测试向量能第一时间告诉你“编出来的库算得对不对”比后面拿真实证书试错便宜得多。2.3 三条命令验证产物确认拿到的是国密版而不是同名程序装完之后第一件事不是写代码是确认你调用的确实是自己编的那份。系统里可能已经存在一个叫gmssl的其他程序PATH顺序一乱就调错了。export PATH/opt/gmssl/bin:$PATH # 1) 版本与编译信息 /opt/gmssl/bin/gmssl version # 2) 动态依赖开了 no-shared 的话这里应该看不到 libssl/libcrypto ldd /opt/gmssl/bin/gmssl | grep -Ei ssl|crypto # 3) 用标准测试向量验证 SM3SM3(abc) 的固定结果 printf abc | /opt/gmssl/bin/gmssl sm3第三条是重点。SM3(abc)的结果是公开的标准向量十六进制应为66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0对得上说明算法实现没问题对不上或者命令报“不认识 sm3”八成是你调到了别的程序或者PATH里/opt/gmssl/bin排在后面。这一步花三十秒能省掉后面怀疑人生的几个小时。提示子命令的具体参数名在不同小版本之间会调整比如sm4的密钥是十六进制串还是文件、certgen的自签开关叫什么。别信教程直接gmssl 子命令 -help看当前这份源码自己的说明tools/目录下的源码是最终依据。2.4 交叉编译到目标板CC 与 no-asm 的取舍国产化平台上跑基本都要交叉编译。源码包里的config脚本支持用环境变量覆盖编译器这是最不容易出错的方式make clean CCaarch64-linux-gnu-gcc \ ARaarch64-linux-gnu-ar \ RANLIBaarch64-linux-gnu-ranlib \ ./config --prefix/opt/gmssl-arm64 no-shared no-asm no-tests make -j$(nproc) make install这里加了no-tests因为交叉编译出来的测试程序在宿主机上跑不了make test会直接失败不如关掉把测试放到目标板上做。no-asm在交叉编译时几乎是必选项汇编段对编译器和 ABI 都很敏感先关掉确认 C 实现路径通了再单独开汇编做对比测试出问题也容易定位是算法层还是优化层。编完把libgmssl.a和include/gmssl/拷到目标板的 sysroot 里业务侧编译时带上-I和-L即可。静态库体积不大塞进嵌入式镜像里通常没压力。3. SM2/SM3/SM4 的最小闭环先用命令行跑通再上 C 接口3.1 命令行四步出密钥、签名、验签、加解密命令行工具最大的价值是让你在不写一行代码的情况下把“算法能不能用”这件事验证完。SM2 的一套完整流程是这样export PATH/opt/gmssl/bin:$PATH # 1) 生成 SM2 密钥对私钥用口令保护同时导出公钥 gmssl sm2keygen -pass 1234 -out sm2.key -pubout sm2.pub # 2) 准备待签名数据注意不要带换行否则两边摘要不一致 printf hello gmssl msg.txt # 3) 签名 gmssl sm2sign -key sm2.key -pass 1234 -in msg.txt -out msg.sig # 4) 验签 gmssl sm2verify -pubkey sm2.pub -in msg.txt -sig msg.sig # 5) 公钥加密 / 私钥解密 gmssl sm2encrypt -pubkey sm2.pub -in msg.txt -out msg.enc gmssl sm2decrypt -key sm2.key -pass 1234 -in msg.enc -out msg.dec参数含义和改动影响参数含义改了会怎样-pass私钥文件的口令只保护私钥文件本身不参与签名运算改了要重新出密钥-pubout同时导出公钥文件不给的话后面验签和加密都没公钥可用-id签名者标识缺省为一串固定 ASCII双方不一致时验签必然失败这是最高频的坑-in输入文件建议二进制模式读文本编辑器加不加换行会让摘要完全不同第三步的签名默认是“先做 SM3 摘要、再走 SM2 签名运算”中间还夹着一个 Z 值——Z 值是把用户标识、曲线参数、公钥拼起来再哈希得到的一段摘要它会被拼在消息摘要前面参与签名。命令行工具会自动算但你换到 C 接口自己调的时候这一步要不要你手工补取决于函数签名下一节会说。验签成功会打印明确的成功提示失败则返回非零。写脚本做自动化检查时直接看退出码就行不要去匹配输出文本。3.2 C 里调 SM3 和 SM4一个拷走就能编的样例命令行验证完真正落地还是要在业务代码里调库。SM3 和 SM4 的接口最简单先拿这两个建立信心#include stdio.h #include string.h #include gmssl/sm3.h #include gmssl/sm4.h int main(void) { /* ---- SM3一次性摘要接口适合小数据 ---- */ uint8_t dgst[32]; const char *msg abc; sm3_digest((const uint8_t *)msg, strlen(msg), dgst); printf(sm3(abc) ); for (int i 0; i 32; i) printf(%02x, dgst[i]); printf(\n); /* ---- SM4-CBC PKCS#7 padding业务里最常用的形态 ---- */ uint8_t key[16] {0}; /* 真实环境必须用随机密钥 */ uint8_t iv[16] {0}; /* IV 每次加密都要重新随机生成 */ uint8_t in[64] gmssl sm4 demo; uint8_t enc[128], dec[128]; size_t enclen 0, declen 0; SM4_KEY sm4_key; sm4_set_encrypt_key(sm4_key, key); /* 密钥扩展 */ if (sm4_cbc_padding_encrypt(sm4_key, iv, in, strlen((char *)in), enc, enclen) ! 1) { fprintf(stderr, sm4 encrypt failed\n); return 1; } if (sm4_cbc_padding_decrypt(sm4_key, iv, enc, enclen, dec, declen) ! 1) { fprintf(stderr, sm4 decrypt failed\n); return 1; } printf(sm4 roundtrip: %.*s (%zu - %zu bytes)\n, (int)declen, dec, strlen((char *)in), enclen); return 0; }编译命令里有两个点必须注意# -lgmssl 必须放在源文件后面静态库的链接顺序是有向的 gcc sm3_sm4_demo.c -o demo \ -I/opt/gmssl/include \ -L/opt/gmssl/lib \ -lgmssl逻辑说明sm3_digest是一次性接口输入长度已知、数据在内存里时最省事如果要处理流式数据或者大文件换成sm3_init/sm3_update/sm3_finish三段式摘要上下文是个栈上结构体不用动态分配。SM4 是 16 字节分组密码裸的分组接口sm4_encrypt只能处理整数倍长度业务里几乎不会直接用都是走 CBC 加 padding 的封装。sm4_cbc_padding_encrypt把“补位、逐块加密”两件事一起做了输出长度是 16 的整数倍enclen由函数回填。参数上要注意iv是 16 字节长度不对会直接踩内存out缓冲区要预留inlen 16字节因为最坏情况要补一整块。解密用同一个SM4_KEY结构GmSSL 的 SM4 密钥扩展不分加密解密方向这点和 AES 的用法不一样别自己造一个解密密钥。这两处不设防会出事key和iv硬编码成全零只适合跑通流程上线前必须换成rand_bytes()出的随机数iv跟密文一起传key走密钥管理别写在代码里。3.3 SM2 签名在 C 里的 Z 值问题一个函数签名决定半天工时SM2 的 C 接口比 SM3/SM4 麻烦麻烦点全在“摘要和 Z 值由谁负责”这件事上。#include stdio.h #include string.h #include gmssl/sm2.h #include gmssl/sm3.h int main(void) { SM2_KEY key; if (sm2_key_generate(key) ! 1) { fprintf(stderr, keygen failed\n); return 1; } const char *msg order-no-20240501; uint8_t dgst[32]; sm3_digest((const uint8_t *)msg, strlen(msg), dgst); /* 先做摘要 */ uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; size_t siglen 0; if (sm2_sign(key, dgst, sig, siglen) ! 1) { fprintf(stderr, sign failed\n); return 1; } if (sm2_verify(key, dgst, sig, siglen) ! 1) { fprintf(stderr, verify failed\n); return 1; } printf(sm2 sign/verify ok, siglen%zu\n, siglen); return 0; }这段代码自己跟自己玩没问题但一旦要和外部系统互通——加密机、国密网关、第三方支付——十有八九会验签失败。原因是 SM2 的完整签名流程里被签的其实是SM3(ZA || M)ZA由用户标识、椭圆曲线参数、公钥横纵坐标哈希而来。上面这种写法只对 32 字节摘要做运算Z 值要么由你补要么由某个带标识参数的函数补。动手前先在头文件里确认一遍这一步能省掉半天grep -n sm2_sign\|sm2_do_sign\|sm2_verify\|user_id\|SM2_DEFAULT_ID \ /opt/gmssl/include/gmssl/sm2.h如果签名函数的参数里带标识常见形式是一个const char *id或默认 ID 宏说明库内部会算 ZA你只需要保证双方标识一致如果只有摘要入参那就得自己在做 SM3 之前把 ZA 拼进去或者改用带do_sign字样的底层接口自己走完整流程。这两种情况在互通场景下表现完全不同而错误信息往往只有一句“verify failed”属于典型的黑匣子问题。对接加密机时还有个细节对方返回的签名值可能是 DER 编码的SEQUENCE { r, s }也可能是 64 字节的r||s定长拼接。这两种格式在代码里差一个解析调用对不上就是长度校验失败。拿到接口文档先确认编码格式比事后猜要快。4. 国密双证书握手CA、两张证书与一次完整的 tlcp 连接4.1 为什么需要两张证书签名证书与加密证书的分工第一次看到“双证书”的人都会问一张证书不够用吗。国密体系里服务端和客户端各自持有两套证书和私钥分工是明确的证书类型私钥由谁生成握手时的用途缺了会怎样签名证书使用者自己生成私钥不上交身份认证、对握手参数做签名服务端无法证明身份握手在 CertificateVerify 处断掉加密证书由 CA 或密钥管理机构生成并托管密钥交换用其公钥加密预主密钥客户端拿到证书链后找不到可用的加密公钥直接报错这个设计背后是密钥恢复需求签名私钥代表身份丢了就是身份丢失必须自持加密私钥用于解出会话密钥出于审计和取证需要可托管。理解了这一点就明白为什么握手报文里的 Certificate 消息会带两张证书为什么服务端配置要传两组密钥。只配一组是新手最常犯的错错误现象还特别不直观——TCP 连上了、ClientHello 发出去了然后卡在证书阶段。4.2 用 gmssl 自建一条证书链CA、签名证书、加密证书自建链路的价值在于先把协议跑通再换成正式 CA 签发的证书这样出问题时能确定是协议层还是证书层。mkdir -p demo-ca cd demo-ca # 1) 根 CA 的密钥 gmssl sm2keygen -pass 1234 -out ca.key -pubout ca.pub # 2) 根证书自签不指定上级 CA或按 help 里的自签开关来 gmssl certgen -C CN -O Demo -OU CA -CN Demo Root CA \ -days 3650 -key ca.key -pass 1234 -out ca.crt # 3) 服务端签名证书 gmssl sm2keygen -pass 1234 -out sign.key -pubout sign.pub gmssl certgen -C CN -O Demo -OU Server -CN demo.server.sign \ -days 365 -key sign.key -pass 1234 \ -cacert ca.crt -cakey ca.key -capass 1234 -out sign.crt # 4) 服务端加密证书 gmssl sm2keygen -pass 1234 -out enc.key -pubout enc.pub gmssl certgen -C CN -O Demo -OU Server -CN demo.server.enc \ -days 365 -key enc.key -pass 1234 \ -cacert ca.crt -cakey ca.key -capass 1234 -out enc.crt # 5) 逐张检查 gmssl certparse -in ca.crt gmssl certparse -in sign.crt gmssl certparse -in enc.crtcertgen的参数在小版本之间会有出入尤其是根证书自签那一步——有的版本靠不传上级 CA 来隐含自签有的版本有独立开关。先用gmssl certgen -help对一遍比自己试快。签发子证书时-cacert/-cakey/-capass三个必须同时给少一个就会退化成自签签出来的证书链是断的而certparse单看一张证书是看不出来的。certparse的输出要盯三样东西公钥算法是不是 SM2、签名算法是不是 SM3 与 SM2 的组合、曲线 OID 是不是 sm2p256v1。这三样任意一项不对说明证书根本不是国密体系里的——用 OpenSSL 生成的 RSA 或普通 EC 证书certparse也能解析出结构但握手时对端会直接拒绝而且错误信息通常只会给出一个模糊的握手失败。4.3 起服务端、跑客户端握手链路上该看哪四个输出点证书齐了就能起连接。服务端要传两组密钥参数名以当前版本为准# 服务端签名证书 签名私钥 加密证书 加密私钥四件套齐全 gmssl tlcp_server -port 4433 \ -cert sign.crt -key sign.key -pass 1234 \ -enc_cert enc.crt -enc_key enc.key -enc_pass 1234 \ -www # 客户端用自建根 CA 校验服务端证书链 gmssl tlcp_client -host 127.0.0.1 -port 4433 -cacert ca.crt服务端和客户端在 GmSSL 3.x 里是独立的子命令名字里带 tlcp这是国密传输层协议的名字跟 OpenSSL 的s_server/s_client不是一回事照抄 OpenSSL 教程会找不到命令。四个观察点一是客户端发出的 ClientHello 里密码套件列表是否包含国密套件。如果对端是商业网关它可能只认某几个套件顺序还有讲究。二是服务端回的 Certificate 消息里证书数量——正确情况是两张一张签名一张加密只看到一张就回去查配置。三是 ServerKeyExchange 里的签名能不能被客户端用签名证书验过这一步失败通常是证书链问题。四是 Finished 之后应用数据能不能通-www会返回一个简单页面能拿到就说明整条链路通了。第一次跑通建议全程抓包用tcpdump存成 pcap 慢慢看。国密握手和标准 TLS 的差异集中在证书消息和密钥交换上看着报文对着规范读一遍比读十篇博客都管用。等自建链路稳定了再把证书换成正式 CA 签发的出问题就能确定是证书本身的问题不是协议配置的问题。5. 避坑与排查编译、证书、握手三段的五个高频翻车点5.1 现象程序能跑但国密算法报错或符号找不到原因基本是链接到了系统 OpenSSL。-lcrypto在绝大多数 Linux 上都指向系统库如果你的构建脚本沿用了 OpenSSL 时期的写法编译能过、运行也能过直到调用 SM2 相关函数时才在运行期炸掉。解决分三步一是构建命令里把-lgmssl明确写出来且放在目标文件之后二是确保不要同时出现-lcrypto三是运行前用ldd看一眼实际加载的库。开了no-shared之后这个问题会以undefined reference的形式提前到链接期暴露反而更好查。5.2 现象自己签名自己验能过跟对端互通就永远验签失败原因是 Z 值参与方式不一致。SM2 签的并不是消息摘要本身而是把用户标识、曲线参数、公钥哈希出来的 ZA 拼在摘要前面再哈希的结果。库里有的接口内部算 ZA有的只对 32 字节摘要做运算两边不一致时验签必然失败错误信息还只有一句失败。解决方式是先读头文件确认签名函数是否带标识参数再和接口文档对齐对端用的标识是什么、签名值是 DER 还是 64 字节定长、摘要算的是原文还是原文加盐。这三点对齐之后互通问题基本就消了。我一般会在联调前先写一个只做“签名→把签名值和公钥发给对方→对方验签”的最小用例把算法层和传输层隔离开。5.3 现象certparse 能解析但握手时对端拒绝证书原因是证书根本不是国密证书。用通用工具生成的证书结构上完全合法解析器也不会报错但公钥算法和签名算法不是 SM2/SM3 组合对端在校验证书链时就会拒。解决方式是签发环节就守住证书必须由支持 SM2 的工具签发签发后立刻certparse检查公钥算法、签名算法、曲线 OID 三项三项都对再把证书往下游传。另外注意有效期——自建 CA 图省事签十年某些对端会校验有效期上限直接拒绝。5.4 现象TCP 连上了握手卡在证书阶段不动原因是双证书只配了一半。TLCP 要求服务端同时提供签名证书和加密证书两组材料参数只给一组时有的实现会在启动阶段就报错有的会等到握手中途才失败现象是连接建立后长时间无响应然后超时。解决方式是启动前先自检四件套是否齐全签名证书、签名私钥、加密证书、加密私钥以及两个私钥各自的口令。写个十行脚本在服务启动前跑一遍文件不存在或者口令错就直接退出别等到线上握手失败才发现。5.5 现象SM4 解密出来的尾部是乱码或者长度对不上原因是 padding 方式不匹配或者 IV 不一致。CBC 模式下明文要补到 16 的整数倍一边用了带 padding 的封装接口、另一边用了裸分组接口解密出来的尾部就会多出几个字节的填充数据IV 加解密不一致则会导致首块解密全错。解决方式是明确约定统一用 CBC 加 padding 的封装接口或者统一自己补位并用裸接口IV 随密文一起传输长度固定 16 字节解密时校验输出长度不超过缓冲区别假设解密结果一定比密文短。这类问题在自测时最容易漏因为自己加密自己解密padding 总是对得上的一跨进程就露馅。6. 接进业务前的三条验证线标准向量、互操作与最小自检脚本换库、升级版本、换平台这三件事做完之后很多人会直接上业务联调然后在某个周末被叫起来排查。我更倾向在合入之前跑完三条验证线成本不到一小时收益是把问题挡在联调之前。第一条是标准向量验证算法实现本身。SM3 用abc的固定结果SM4 用标准测试向量——密钥和明文都取0123456789abcdeffedcba9876543210单分组加密结果应为681edf34d206965e86b3e94f536e4246。这两个值跑对了说明算法层没问题后面所有异常都可以往协议层和证书层找。第二条是互操作验证协议实现。自建 CA 起一对服务端客户端能通只证明了“自己跟自己兼容”真正的验证是拿自建链路去连对方的网关或者拿对方的证书来连自己的服务端。这一步暴露的问题大多是证书格式、套件顺序、标识约定这三类。第三条是性能基线验证可用性。SM4 在 CBC 模式下的吞吐、SM2 每秒签名次数这两个数在国产化平台上和 x86 上能差出好几倍。基线不是拿来做容量规划的是用来做回归对比的开了汇编优化前后差多少、换了个编译器版本差多少有数才好判断某个改动是不是引入了性能回退。把前两条固化成一个脚本CI 里每次构建跑一遍#!/usr/bin/env bash set -euo pipefail GMSSL${GMSSL:-/opt/gmssl/bin/gmssl} WORK$(mktemp -d) trap rm -rf $WORK EXIT # 验证线一SM3 标准向量 got$(printf abc | $GMSSL sm3 | tr -d [:space:]) want66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0 [ $got $want ] || { echo SM3 vector FAIL: $got; exit 1; } echo SM3 vector ok # 验证线二SM2 签名验签闭环 printf health-check $WORK/msg.txt $GMSSL sm2keygen -pass 1234 -out $WORK/k.pem -pubout $WORK/p.pem $GMSSL sm2sign -key $WORK/k.pem -pass 1234 \ -in $WORK/msg.txt -out $WORK/sig.bin $GMSSL sm2verify -pubkey $WORK/p.pem \ -in $WORK/msg.txt -sig $WORK/sig.bin echo SM2 sign/verify ok # 验证线三证书链能否自洽 [ -f $WORK/ca.crt ] || cp ca.crt $WORK/ 2/dev/null || true echo all checks passed脚本里的trap那句是习惯中间任何一步失败都把临时目录清掉不然反复调试会在/tmp里堆一堆密钥文件。私钥落盘的位置也要注意CI 环境里用临时目录别写到工作区被缓存带走。最后一条血泪经验也是我现在的固定动作每次拿到一个新的密码库或者新版本第一件事永远是跑标准向量第二件事是抓一次完整握手包两件事都过了才动业务代码。早年我跳过了这一步直接拿业务系统联调最后定位到是链接时链到了另一个版本的库白折腾了整整两天。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站