openHiTLS初识

admin 2026-09-22 06:14:31 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文介绍openHiTLS开源密码套件,针对密评中密码产品选型封闭、算法切换成本高、自研密码模块验证难三大痛点,提出模块化五组件架构、国密全栈支持与形式化验证能力。详述编译流程与TLCP/DTLCP实操命令,为密评建设提供可落地方案。 综合评分: 84 文章分类: 安全建设,解决方案,安全工具


openHiTLS 初识

原创

利刃信安 利刃信安

利刃信安

2026年9月20日 10:30 北京

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

openHiTLS 初识

摘要

随着《密码法》《商用密码管理条例》等法规落地,商用密码应用安全性评估(简称密评)已成为政企信息系统合规的刚性门槛。密评整改中,”密码产品选型封闭、算法切换成本高、自研密码模块安全性难以验证”三大痛点始终困扰从业者。openHiTLS 作为业界首款面向全场景的开源密码套件,通过模块化架构、国密全栈支持和形式化验证能力,为密评建设提供了全新解题思路。

适用读者:密评工程师、国密改造开发人员、密码学方向学生与研究者。

你将收获:

  • • 理解 openHiTLS 的定位、五组件架构与国密全栈能力(第一、二章)
  • • 从源码编译 hitls 命令行工具的完整流程与关键编译宏(第三章)
  • • 用 hitls 复现 TLCP/DTLCP 单向/双向身份鉴别的可执行命令(第四章)
  • • TLCP/DTLCP 抓包分析要点与常见错误码排障方法(第五章、附录 A)

一、密评困境与 openHiTLS 破局

密评的核心要求可归纳为四点:密码算法合规、密码协议合规、密码产品合规、密钥管理合规。在实际落地中,常见困境包括:

  • • 选型受限:商用密码产品多为闭源交付,用户无法审查底层实现,与密评”自主可控”导向存在张力。
  • • 迁移困难:从国际算法(RSA/AES)向国密算法(SM2/SM4)迁移时,应用层需大幅改造,接口不兼容。
  • • 验证成本高:自研密码模块要分别通过功能正确性、侧信道安全性等多维度验证,中小企业难以负担。

一套算法丰富、接口统一、安全可验证的开源密码套件,是破解上述困局的可行路径。

2024年12月,由华为、西安电子科技大学、山东大学等15家单位联合宣布 openHiTLS 正式开源,定位为面向全场景数智安全、独立创新的开源密码套件。它由五个松耦合组件构成:

| 组件 | 职责 | 密评关联度 | | — | — | — | | Crypto | 密码算法库(国密/国际/PQC) | ★★★★★ | | TLS | 安全传输协议(TLS 1.2/1.3/TLCP/DTLCP) | ★★★★★ | | PKI | 公钥基础设施(证书解析、验证、CRL管理) | ★★★★ | | Auth | 认证协议(Privacy Pass/SPAKE2+等) | ★★★ | | BSL | 基础支撑层(内存管理、错误栈、平台抽象等) | ★★ |

openHiTLS 密码套件(五组件松耦合)

BSL 基础支撑层内存管理 · 错误栈 · 平台抽象

Crypto 密码算法库国密 SM2/SM3/SM4 · 国际 · 后量子

TLS 安全传输协议TLS 1.2/1.3 · TLCP · DTLCP

PKI 公钥基础设施证书解析 · 证书验证 · CRL 管理

Auth 认证协议Privacy Pass · SPAKE2+

组件高度解耦,可按需裁剪——单算法场景可精简至不足10KB,这意味着它既能跑在云服务器上,也能嵌入物联网终端设备。


二、国密全栈:算法、协议与安全验证

密评最核心的诉求是密码算法和协议必须采用国家标准,openHiTLS 的覆盖全面:

国密算法(全部遵循国家标准):

| 算法 | 国家标准 | 类型 | 支持能力 | | — | — | — | — | | SM2 | GB/T 32918 | 椭圆曲线公钥密码 | 加解密、签名验签、密钥交换 | | SM3 | GB/T 32905 | 密码杂凑 | 完整性校验、HMAC | | SM4 | GB/T 32907 | 分组密码 | CBC/GCM/CTR/CFB/OFB/XTS 等工作模式 |

国密协议:

| 协议 | 标准 | 承载 | 典型场景 | | — | — | — | — | | TLCP | GB/T 38636-2020 | TCP | Web/API 网关、业务系统加密传输 | | DTLCP | GM/T 0128-2023 | UDP | 物联网、音视频、实时交互 |

密码套件矩阵(本文后续实操围绕以下 4 个套件展开):

| 密码套件 | 密钥交换 | 加密模式 | 杂凑 | | — | — | — | — | | ECDHE_SM4_CBC_SM3 | ECDHE(SM2 临时密钥协商) | SM4-CBC | SM3 | | ECC_SM4_CBC_SM3 | ECC(SM2 静态加密密钥) | SM4-CBC | SM3 | | ECDHE_SM4_GCM_SM3 | ECDHE(SM2 临时密钥协商) | SM4-GCM | SM3 | | ECC_SM4_GCM_SM3 | ECC(SM2 静态加密密钥) | SM4-GCM | SM3 |

同时支持国际算法(AES、RSA、ECDSA、Ed25519、X25519)和后量子算法(ML-KEM、ML-DSA、SLH-DSA、FrodoKEM、Classic McEliece,需编译时启用),一套代码即可覆盖国密 + 国际 + 抗量子三套密码体系。

丰富算法之外,密评对密码模块的安全性同样有硬性要求(参考 GB/T 39786),openHiTLS 提供了多层次安全保障:

  • • KAT 测试(Known Answer Test):确保密码算法实现的数学正确性
  • • 形式化验证:对核心算法进行数学证明级别的正确性验证
  • • 侧信道防护:对时序/功耗/电磁泄漏等侧信道攻击实现有效防护
  • • FUZZ 测试:通过模糊测试发现边界条件与内存安全问题
  • • ISO 19790 认证:与国际认证机构(DEKRA、SGS、BSI 等)共建认证生态

目前 openHiTLS 已通过 ISO 19790 密码模块认证,在密评场景中可以作为合规的密码模块引入。


三、编译与集成:基于 openhitls-0.3 分支实测流程

快速路径:环境准备 → 获取源码 → configure.py 生成工程 → CMake 配置 → make 编译 → 验证产物。完整步骤如下。

3.1 环境准备

# Ubuntu/Debian/Kali
sudo apt update && sudo apt install -y cmake gcc make python3 git tcpdump

# 确认版本(本手册实测版本如下,非强制最低要求)
gcc --version     # 实测: gcc 15.3.0
cmake --version   # 实测: cmake 4.3.4
python3 --version # 实测: Python 3.13.14

3.2 获取源码

# 克隆官方仓库 openhitls-0.3 稳定分支
git clone -b openhitls-0.3 https://gitcode.com/openHiTLS/openhitls
cd openhitls

# 确认版本
git log --oneline -3
# 5e742870 fix:Command line certificate generation supports setting userid
# ab0d11e1 fix:The command line parameter "noverify" has been added to app_server.c
# 0b41641b fix: harden file permissions for sensitive data and add input validation

git describe --tags --always
# openhitls-0.3.3-24-g5e742870

3.3 使用 configure.py 生成 CMake 工程

openHiTLS 0.3 版本采用 configure.py 脚本预生成 CMake 工程,自动完成 Secure_C 安全库编译(39 个 C 文件 → libboundscheck.a)。

关键:--enable all 仅启用非国密模块(AES, RSA, ECDSA, SHA2 等)。国密 TLCP 必须通过 --add_options 显式传递 7 个编译宏,其中 HITLS_CRYPTO_PROVIDER_DEFAULT_SM 将 SM2/SM3/SM4 集成到默认 Provider,是 0.3 版本可用性的必要条件。

cd /path/to/openhitls

python3 configure.py \
    --system linux --bits 64 --asm_type x8664 \
    --build_dir build --output_dir build \
    --enable all --executes hitls \
    --add_options="-DHITLS_TLS_PROTO_TLCP11 \
      -DHITLS_TLS_SUITE_ECDHE_SM4_CBC_SM3 \
      -DHITLS_TLS_SUITE_ECC_SM4_CBC_SM3 \
      -DHITLS_TLS_SUITE_ECDHE_SM4_GCM_SM3 \
      -DHITLS_TLS_SUITE_ECC_SM4_GCM_SM3 \
      -DHITLS_CRYPTO_PROVIDER_DEFAULT_SM \
      -DHITLS_TLS_SUITE_AUTH_SM2"

configure.py 内部执行流程:

1. 检查 Secure_C 依赖 → 未找到 → 自动编译 39 个 securec C 文件 → libboundscheck.a
2. 生成 feature_config.json(各模块 C/ASM 源文件清单)
3. 生成 compile_config.json(-D 宏定义和链接参数)
4. 生成 CMake 辅助模块文件

3.4 CMake 配置 + 编译

cd build
cmake -DCMAKE_BUILD_TYPE=Debug ..
make -j$(nproc)

编译耗时约 2-3 分钟(8核)。SM3/SM4 使用 x86-64 汇编优化(.s/.S 文件)。

3.5 产物验证

$ file hitls
hitls: ELF 64-bit LSB pie executable, x86-64, dynamically linked,
       with debug_info, not stripped

$ ldd hitls
    libhitls_tls.so => .../build/libhitls_tls.so
    libhitls_crypto.so => .../build/libhitls_crypto.so
    libhitls_pki.so => .../build/libhitls_pki.so
    libhitls_bsl.so => .../build/libhitls_bsl.so

$ ls -lh libhitls_*.so hitls
-rwxrwxr-x ... libhitls_bsl.so     913K
-rwxrwxr-x ... libhitls_crypto.so  6.3M  ← 含 SM2/SM3/SM4 汇编优化
-rwxrwxr-x ... libhitls_pki.so     1011K
-rwxrwxr-x ... libhitls_tls.so     5.7M
-rwxrwxr-x ... hitls               908K

3.6 环境变量

# 每个运行 hitls 的终端必须先执行
export LD_LIBRARY_PATH=/path/to/openhitls/build:$LD_LIBRARY_PATH

# 验证
./build/hitls help

3.7 编译宏说明

| # | 编译宏 | 作用 | 必须? | | — | — | — | — | | 1 | HITLS_TLS_PROTO_TLCP11 | 启用 TLCP v1.1 协议栈(含 DTLCP over UDP) | 是 | | 2 | HITLS_TLS_SUITE_ECDHE_SM4_CBC_SM3 | 注册 ECDHE_SM4_CBC_SM3 密码套件 | 是 | | 3 | HITLS_TLS_SUITE_ECC_SM4_CBC_SM3 | 注册 ECC_SM4_CBC_SM3 密码套件 | 是 | | 4 | HITLS_CRYPTO_PROVIDER_DEFAULT_SM | 将 SM2/SM3/SM4 加载到默认 Provider(必要条件) | 是 | | 5 | HITLS_TLS_SUITE_AUTH_SM2 | 启用 SM2 证书身份认证 | 是 | | 6 | HITLS_TLS_SUITE_ECDHE_SM4_GCM_SM3 | 注册 ECDHE_SM4_GCM_SM3(备用) | 否 | | 7 | HITLS_TLS_SUITE_ECC_SM4_GCM_SM3 | 注册 ECC_SM4_GCM_SM3(备用) | 否 |

关键:宏 #1~#5 是 TLCP/DTLCP 工作的充分必要条件。--enable all 仅启用非国密模块,国密必须通过这 5 个核心宏显式启用。


四、实操:使用 hitls CLI 完成 TLCP/DTLCP 通信

以下命令基于 openhitls-0.3 分支(5e742870)编译产物,使用源码内置的 SM2 测试证书。

4.1 测试证书说明

源码内置两套 SM2 测试证书,推荐使用 sm2_with_userid/:

| 目录 | 格式 | 说明 | | — | — | — | | testcode/testdata/tls/certificate/der/sm2_with_userid/ | 混合 | 推荐 ——.crt 文件为 “OpenSSL x509 -text 文本转储 + PEM 证书块” 混合格式,hitls 内置 PEM 解析器(hitls_bsl/pem.c)自动跳过前缀文本 | | testcode/testdata/tls/certificate/der/sm2_cert/ | PEM | 备用——私钥为纯 PKCS #8 格式(-----BEGIN PRIVATE KEY-----),证书为纯 PEM 格式,需先合并 root.pem+intCa.pem 为 chain.pem,且无需 -chainCAfile 参数 |

sm2_with_userid/ 目录文件清单(ls -lh 实测):

| 文件 | 大小 | 格式 | 用途 | | — | — | — | — | | ca.crt | 843B | PEM | CA根证书 | | ca.der | 582B | 纯 DER | CA根证书(DER格式) | | ca.key | 241B | EC PARAMETERS + PRIVATE KEY (PEM) | CA私钥 | | ca.key.der | 121B | 纯 DER | CA私钥(DER格式) | | inter.crt | 794B | PEM | 中间CA证书 | | inter.der | 546B | 纯 DER | 中间CA证书(DER格式) | | sign.crt | 2.4K | x509文本转储 + PEM | TLCP签名证书 | | sign.key | 316B | EC PARAMETERS + PRIVATE KEY (PEM) | TLCP签名私钥 | | sign.der | 533B | 纯二进制DER | 签名证书(供cert callback使用) | | sign.key.der | 121B | 纯二进制DER | 签名私钥(供cert callback使用) | | sign22.crt | 782B | x509文本转储 + PEM | 备用签名证书(v2) | | sign22.der | 535B | 纯 DER | 备用签名证书(DER) | | sign22.key | 316B | EC PARAMETERS + PRIVATE KEY (PEM) | 备用签名私钥 | | enc.crt | 2.4K | x509文本转储 + PEM | TLCP加密证书 | | enc.key | 316B | EC PARAMETERS + PRIVATE KEY (PEM) | TLCP加密私钥 | | enc.der | 532B | 纯二进制DER | 加密证书(供cert callback使用) | | enc.key.der | 121B | 纯二进制DER | 加密私钥(供cert callback使用) | | enc22.crt | 778B | x509文本转储 + PEM | 备用加密证书(v2) | | enc22.der | 532B | 纯 DER | 备用加密证书(DER) | | enc22.key | 316B | EC PARAMETERS + PRIVATE KEY (PEM) | 备用加密私钥 |

格式说明:.crt 文件不是纯 DER 格式。其内部结构为 “OpenSSL x509 -text 人类可读输出 + PEM证书块”。hitls内置PEM解析器(hitls_bsl/pem.c)自动跳过前缀文本并解析PEM块。命令行无需指定 -certform/-keyform。sign22.* 和 enc22.* 为备用证书(可能用于不同测试场景),实际 TLCP 测试使用 sign.* 和 enc.* 即可。

TLCP 双证书体系(GM/T 0024):

| 证书 | Subject标识 | Key Usage | 握手阶段使用 | | — | — | — | — | | sign.crt | OU=testsign | Digital Signature, Non Repudiation | ServerKeyExchange SM2签名 | | enc.crt | OU=testenc | Key Encipherment, Data Encipherment, Key Agreement | 密钥交换 SM2加密/解密 |

备用证书目录(sm2_cert)

sm2_cert/ 目录提供另一套证书,核心差异在于私钥为纯 PKCS #8 格式(-----BEGIN PRIVATE KEY-----),不含 EC PARAMETERS 前缀。主要 PEM 文件:

| 文件 | Key Usage | 用途 | | — | — | — | | root.pem | CA:TRUE, KeyCertSign | 根 CA 自签名证书 | | intCa.pem | CA:TRUE, KeyCertSign | 中间 CA 证书 | | server_sign.pem | Digital Signature | 服务端 TLCP 签名证书 | | server_sign.key.pem | — | 服务端签名私钥(PKCS #8) | | server_enc.pem | Key Encipherment | 服务端 TLCP 加密证书 | | server_enc.key.pem | — | 服务端加密私钥(PKCS #8) | | client_sign.pem | Digital Signature | 客户端 TLCP 签名证书 | | client_sign.key.pem | — | 客户端签名私钥(PKCS #8) | | client_enc.pem | Key Encipherment | 客户端 TLCP 加密证书 | | client_enc.key.pem | — | 客户端加密私钥(PKCS #8) |

使用前需合并证书链:

cd testcode/testdata/tls/certificate/der/sm2_cert
cat root.pem intCa.pem > chain.pem

# 验证证书链
/path/to/openhitls/build/hitls verify -CAfile chain.pem -nokeyusage server_sign.pem
# 输出: OK

两套证书的命令行参数对照:

| 参数 | sm2_with_userid | sm2_cert | | — | — | — | | -CAfile | ca.crt | chain.pem (root+intCa 合并) | | -chainCAfile | inter.crt | 不需要(已合并到 -CAfile) | | -tlcp_sign_cert | sign.crt | server_sign.pem | | -tlcp_sign_key | sign.key | server_sign.key.pem | | -tlcp_enc_cert | enc.crt | server_enc.pem | | -tlcp_enc_key | enc.key | server_enc.key.pem |

私钥格式差异:sm2_cert 的 .key.pem 文件为纯 PKCS #8(-----BEGIN PRIVATE KEY-----),而 sm2_with_userid 的 .key 文件包含 EC PARAMETERS 前缀块。hitls 的 PEM 解析器对两种格式均可自动处理,但使用 hitls genpkey 子命令生成新私钥时输出为纯 PKCS #8 格式。

4.2 统一环境变量

export LD_LIBRARY_PATH=/path/to/openhitls/build:$LD_LIBRARY_PATH
export C=/path/to/openhitls/testcode/testdata/tls/certificate/der/sm2_with_userid
export HITLS=/path/to/openhitls/build/hitls

每个新终端必须先执行以上三行 export。服务端和客户端需在不同终端运行。

4.3 TLCP 双向身份鉴别(ECDHE_SM4_CBC_SM3)

握手成功。双方均提供双证书,ECDHE密钥交换正常,证书链验证通过。

服务端(终端1,先启动):

$HITLS s_server \
    -tlcp -accept 127.0.0.1:4433 \
    -cipher TLS_ECDHE_SM4_CBC_SM3 \
    -CAfile $C/ca.crt -chainCAfile $C/inter.crt \
    -tlcp_sign_cert $C/sign.crt -tlcp_sign_key $C/sign.key \
    -tlcp_enc_cert $C/enc.crt -tlcp_enc_key $C/enc.key \
    -provider default -state

预期输出(服务端):

Listening on 127.0.0.1:4433 (TCP)
Server started, waiting for connections...
Accepted connection from 127.0.0.1:<ephemeral_port>
STATE: SSL negotiation finished successfully
STATE: SSL negotiation finished successfully

客户端(终端2):

echo&nbsp;"利刃信安"&nbsp;|&nbsp;$HITLS&nbsp;s_client \
&nbsp; &nbsp; -tlcp -host 127.0.0.1 -port 4433 \
&nbsp; &nbsp; -cipher TLS_ECDHE_SM4_CBC_SM3 \
&nbsp; &nbsp; -CAfile&nbsp;$C/ca.crt -chainCAfile&nbsp;$C/inter.crt \
&nbsp; &nbsp; -tlcp_sign_cert&nbsp;$C/sign.crt -tlcp_sign_key&nbsp;$C/sign.key \
&nbsp; &nbsp; -tlcp_enc_cert&nbsp;$C/enc.crt -tlcp_enc_key&nbsp;$C/enc.key \
&nbsp; &nbsp; -provider default -state

预期输出(客户端):

Connected to 127.0.0.1:4433
Starting TLS handshake...
STATE: SSL negotiation finished successfully
STATE: SSL negotiation finished successfully
TLS handshake completed successfully
Protocol version: TLCP v1.1
Cipher suite negotiated: TLS_ECDHE_SM4_CBC_SM3
Handshake state: connected

说明:握手成功后 hitls 客户端进入交互模式。通过管道发送的测试数据”利刃信安”经 TLCP 加密传输至服务端,服务端解密后原样回显给客户端。客户端收到回显数据后直接输出显示。注意:hitls 是 TLS/TLCP 协议测试工具,不是 HTTP 客户端,因此输出中不会出现 “HTTP/1.1 200 OK” 等 HTTP 协议头。

消息序列(双向身份鉴别,ECDHE 套件):

服务端客户端服务端客户端1-3 TCP 三次握手4 ClientHello(携带 ECDHE_SM4_CBC_SM3)5 ServerHello(选定套件)6 Certificate(服务端签名+加密双证书)7 ServerKeyExchange(ECDHE 公钥 + 签名)8 CertificateRequest(ECDHE 强制)9 ServerHelloDone10 Certificate(客户端双证书)11 ClientKeyExchange(ECDHE 密钥协商)12 ChangeCipherSpec + Finished(客户端)13 ChangeCipherSpec + Finished(服务端)14 加密应用数据(利刃信安)服务端解密后回显(利刃信安)
&nbsp;1-3 &nbsp; TCP 三次握手
&nbsp;4 &nbsp; &nbsp; ClientHello (含 ECDHE_SM4_CBC_SM3)
&nbsp;5 &nbsp; &nbsp; ServerHello
&nbsp;6 &nbsp; &nbsp; Certificate (服务端双证书)
&nbsp;7 &nbsp; &nbsp; ServerKeyExchange (ECDHE 公钥+签名)
&nbsp;8 &nbsp; &nbsp; CertificateRequest (ECDHE 强制)
&nbsp;9 &nbsp; &nbsp; ServerHelloDone
10 &nbsp; &nbsp; Certificate (客户端双证书)
11 &nbsp; &nbsp; ClientKeyExchange (ECDHE 密钥协商)
12 &nbsp; &nbsp; [CCS]+Finished (客户端)
13 &nbsp; &nbsp; [CCS]+Finished (服务端)
14 &nbsp; &nbsp; 加密应用数据

4.4 TLCP 单向身份鉴别(ECC_SM4_CBC_SM3 + -noverify)

重要说明:ECDHE 单向不可行(协议级限制,不是Bug)。ECDHE密钥交换强制客户端提供加密证书参与密钥派生(见源码 tls/handshake/send/src/send_server_key_exchange.c L305-310),即使使用 -noverify 也不例外。此限制同时适用于 TLS_ECDHE_SM4_CBC_SM3 和 TLS_ECDHE_SM4_GCM_SM3 两个密码套件——GCM 与 CBC 共享相同的密钥交换算法(ECDHE),仅 AEAD 加密模式不同,单向支持行为完全一致。

解决办法:使用 ECC_SM4_CBC_SM3 或 ECC_SM4_GCM_SM3 密码套件 + 服务端 -noverify 参数。

服务端(终端1,-noverify + ECC 密码套件):

$HITLS&nbsp;s_server \
&nbsp; &nbsp; -tlcp -accept 127.0.0.1:4433 \
&nbsp; &nbsp; -cipher TLS_ECC_SM4_CBC_SM3 \
&nbsp; &nbsp; -CAfile&nbsp;$C/ca.crt -chainCAfile&nbsp;$C/inter.crt \
&nbsp; &nbsp; -tlcp_sign_cert&nbsp;$C/sign.crt -tlcp_sign_key&nbsp;$C/sign.key \
&nbsp; &nbsp; -tlcp_enc_cert&nbsp;$C/enc.crt -tlcp_enc_key&nbsp;$C/enc.key \
&nbsp; &nbsp; -provider default -state -noverify

预期输出(服务端):

Listening on 127.0.0.1:4433 (TCP)
Server started, waiting for connections...
Accepted connection from 127.0.0.1:<ephemeral_port>
STATE: SSL negotiation finished successfully
STATE: SSL negotiation finished successfully

客户端(终端2,不提供自身证书,仅 CA 根证书验证服务端):

echo&nbsp;"利刃信安"&nbsp;|&nbsp;$HITLS&nbsp;s_client \
&nbsp; &nbsp; -tlcp -host 127.0.0.1 -port 4433 \
&nbsp; &nbsp; -cipher TLS_ECC_SM4_CBC_SM3 \
&nbsp; &nbsp; -CAfile&nbsp;$C/ca.crt -chainCAfile&nbsp;$C/inter.crt \
&nbsp; &nbsp; -provider default -state

预期输出(客户端):

Connected to 127.0.0.1:4433
Starting TLS handshake...
STATE: SSL negotiation finished successfully
STATE: SSL negotiation finished successfully
TLS handshake completed successfully
Protocol version: TLCP v1.1
Cipher suite negotiated: TLS_ECC_SM4_CBC_SM3
Handshake state: connected

注意:单向鉴别时服务端命令中同时包含 -CAfile(用于服务端自身证书链)和 -noverify(关闭客户端证书验证),两者不冲突。-CAfile 是服务端加载自身证书链所必需的参数,-noverify 仅控制是否验证客户端证书。

如果错误地使用 ECDHE 密码套件做单向鉴别,预期结果如下(握手失败):

client: TLS handshake failed: 0x20c0029
client: Failed to create config and connection: 0x27
server: TLS handshake failed: 0x2040017
server: Failed to handle client connection

错误码详解见 附录 A:常见错误码。

4.5 DTLCP 双向身份鉴别(ECDHE_SM4_CBC_SM3,UDP 承载)

服务端(终端1,端口 4444,避免与 TCP 冲突):

$HITLS&nbsp;s_server \
&nbsp; &nbsp; -dtlcp -accept 127.0.0.1:4444 \
&nbsp; &nbsp; -cipher TLS_ECDHE_SM4_CBC_SM3 \
&nbsp; &nbsp; -CAfile&nbsp;$C/ca.crt -chainCAfile&nbsp;$C/inter.crt \
&nbsp; &nbsp; -tlcp_sign_cert&nbsp;$C/sign.crt -tlcp_sign_key&nbsp;$C/sign.key \
&nbsp; &nbsp; -tlcp_enc_cert&nbsp;$C/enc.crt -tlcp_enc_key&nbsp;$C/enc.key \
&nbsp; &nbsp; -provider default -state

客户端(终端2):

echo&nbsp;"利刃信安"&nbsp;|&nbsp;$HITLS&nbsp;s_client \
&nbsp; &nbsp; -dtlcp -host 127.0.0.1 -port 4444 \
&nbsp; &nbsp; -cipher TLS_ECDHE_SM4_CBC_SM3 \
&nbsp; &nbsp; -CAfile&nbsp;$C/ca.crt -chainCAfile&nbsp;$C/inter.crt \
&nbsp; &nbsp; -tlcp_sign_cert&nbsp;$C/sign.crt -tlcp_sign_key&nbsp;$C/sign.key \
&nbsp; &nbsp; -tlcp_enc_cert&nbsp;$C/enc.crt -tlcp_enc_key&nbsp;$C/enc.key \
&nbsp; &nbsp; -provider default -state

握手成功。DTLCP over UDP,无TCP三次握手,握手消息含序号和分片偏移量。

预期输出(服务端):

Listening on 127.0.0.1:4444 (UDP)
Server started, waiting for connections...
STATE: SSL negotiation finished successfully
STATE: SSL negotiation finished successfully

预期输出(客户端):

Connected to 127.0.0.1:4444
Starting TLS handshake...
STATE: SSL negotiation finished successfully
STATE: SSL negotiation finished successfully
TLS handshake completed successfully
Protocol version: TLCP v1.1
Cipher suite negotiated: TLS_ECDHE_SM4_CBC_SM3
Handshake state: connected

注意:DTLCP 基于 UDP,服务端不会输出 “Accepted connection” 行(UDP 无连接建立过程)。协议版本字段统一显示为 “TLCP v1.1″(TLCP 协议族)。证书消息可能因超过 MTU 而通过 handshake_fragment 分片传输。

4.6 DTLCP 单向身份鉴别(ECC_SM4_CBC_SM3 + -noverify)

服务端(终端1,ECC + -noverify):

$HITLS&nbsp;s_server \
&nbsp; &nbsp; -dtlcp -accept 127.0.0.1:4444 \
&nbsp; &nbsp; -cipher TLS_ECC_SM4_CBC_SM3 \
&nbsp; &nbsp; -CAfile&nbsp;$C/ca.crt -chainCAfile&nbsp;$C/inter.crt \
&nbsp; &nbsp; -tlcp_sign_cert&nbsp;$C/sign.crt -tlcp_sign_key&nbsp;$C/sign.key \
&nbsp; &nbsp; -tlcp_enc_cert&nbsp;$C/enc.crt -tlcp_enc_key&nbsp;$C/enc.key \
&nbsp; &nbsp; -provider default -state -noverify

客户端(终端2,无自身证书):

echo&nbsp;"利刃信安"&nbsp;|&nbsp;$HITLS&nbsp;s_client \
&nbsp; &nbsp; -dtlcp -host 127.0.0.1 -port 4444 \
&nbsp; &nbsp; -cipher TLS_ECC_SM4_CBC_SM3 \
&nbsp; &nbsp; -CAfile&nbsp;$C/ca.crt -chainCAfile&nbsp;$C/inter.crt \
&nbsp; &nbsp; -provider default -state

握手成功(与TLCP ECC单向相同原理)。

4.7 常用参数速查(openhitls-0.3 分支实测可用)

| 参数 | 说明 | | — | — | | -tlcp / -dtlcp | 协议类型:TLCP (TCP) / DTLCP (UDP) | | -cipher <val> | 密码套件标准名称(大小写敏感) | | -tlcp_sign_cert <file> / -tlcp_sign_key <file> | SM2 签名证书与私钥 | | -tlcp_enc_cert <file> / -tlcp_enc_key <file> | SM2 加密证书与私钥 | | -CAfile <file> / -chainCAfile <file> | CA 根证书 / 中间CA证书链 | | -accept host:port | 服务端监听地址和端口 | | -host <host> / -port <uint> | 客户端连接地址和端口(分开指定) | | -noverify | 单向鉴别核心参数 :服务端跳过对客户端证书的验证(-noverify 仅控制是否验证对端证书,不影响服务端加载自身证书链) | | -provider default | 指定密码Provider(必须指定) | | -state | 输出握手状态信息 | | -accept_once | 服务端完成一次连接后退出 |

密码套件常用值:

| -cipher 参数值 | 密钥交换 | 单向支持 | | — | — | — | | TLS_ECDHE_SM4_CBC_SM3 | ECDHE + SM4-CBC + SM3 | 不支持 | | TLS_ECC_SM4_CBC_SM3 | ECC + SM4-CBC + SM3 | 支持 | | TLS_ECDHE_SM4_GCM_SM3 | ECDHE + SM4-GCM + SM3 | 不支持 | | TLS_ECC_SM4_GCM_SM3 | ECC + SM4-GCM + SM3 | 支持 |

-noverify 使用模式总结:

| 鉴别类型 | 服务端 | 客户端 | 说明 | | — | — | — | — | | 双向鉴别 | 无 -noverify(使用 -CAfile 验证客户端证书) | 无 -noverify(使用 -CAfile 验证服务端证书) | 双方均需验证对方证书 | | 单向鉴别 | -noverify (不验证客户端证书) | 无 -noverify(使用 -CAfile 验证服务端证书) | 仅客户端验证服务端身份 |

4.8 自定义 SM2 证书生成(使用 hitls)

以下命令基于 5e742870 commit,该版本原生支持 -userid 参数和 Version 3 证书扩展。无需 OpenSSL 辅助,hitls 已完全取代 OpenSSL 用于 SM2 证书生成。

工作目录准备:

mkdir&nbsp;-p custom_certs &&&nbsp;cd&nbsp;custom_certs

生成 CA 根证书:

# 1. 生成 CA 私钥(SM2,输出为纯 PKCS&nbsp;#8&nbsp;格式)
$HITLS&nbsp;genpkey -algorithm EC \
&nbsp; &nbsp; -pkeyopt&nbsp;"ec_paramgen_curve:sm2"&nbsp;-out ca.key

# 2. 生成 CA 证书签名请求(CSR)并设置 userid
$HITLS&nbsp;req -new -key ca.key \
&nbsp; &nbsp; -subj&nbsp;"/C=CN/O=openHiTLS/OU=TestCA/CN=RootCA"&nbsp;\
&nbsp; &nbsp; -userid&nbsp;"1234567812345678"&nbsp;-out ca.csr

# 3. CA 自签名根证书
$HITLS&nbsp;x509 -req -in&nbsp;ca.csr \
&nbsp; &nbsp; -signkey ca.key -days 365 -userid&nbsp;"1234567812345678"&nbsp;\
&nbsp; &nbsp; -md sm3 -out ca.crt

注意:CA 根证书自签名时未使用 -extfile 参数,因此生成的是 Version 1 证书(无 X509V3 扩展)。CA 根证书仅用于签发下级证书,Version 1 格式不影响其功能。

创建扩展配置文件:

cat&nbsp;> openssl_ext.cnf <<&nbsp;'EOF'
# SM2 双证书体系扩展配置文件

[server_sign]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyCertSign, cRLSign
subjectKeyIdentifier =&nbsp;hash

[server_enc]
basicConstraints = CA:FALSE
keyUsage = critical, keyEncipherment, dataEncipherment
subjectKeyIdentifier =&nbsp;hash

[client_sign]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyCertSign, cRLSign
subjectKeyIdentifier =&nbsp;hash

[client_enc]
basicConstraints = CA:FALSE
keyUsage = critical, keyEncipherment, dataEncipherment
subjectKeyIdentifier =&nbsp;hash
EOF

生成服务端签名/加密证书:

# 服务端签名证书
$HITLS&nbsp;genpkey -algorithm EC -pkeyopt&nbsp;"ec_paramgen_curve:sm2"&nbsp;-out server_sign.key
$HITLS&nbsp;req -new -key server_sign.key \
&nbsp; &nbsp; -subj&nbsp;"/C=CN/O=openHiTLS/OU=TestSign/CN=TLCP_Server"&nbsp;\
&nbsp; &nbsp; -userid&nbsp;"1234567812345678"&nbsp;-out server_sign.csr
$HITLS&nbsp;x509 -req -in&nbsp;server_sign.csr \
&nbsp; &nbsp; -CA ca.crt -CAkey ca.key -days 365 \
&nbsp; &nbsp; -userid&nbsp;"1234567812345678"&nbsp;-md sm3 \
&nbsp; &nbsp; -extfile openssl_ext.cnf -extensions server_sign \
&nbsp; &nbsp; -out server_sign.crt

# 服务端加密证书
$HITLS&nbsp;genpkey -algorithm EC -pkeyopt&nbsp;"ec_paramgen_curve:sm2"&nbsp;-out server_enc.key
$HITLS&nbsp;req -new -key server_enc.key \
&nbsp; &nbsp; -subj&nbsp;"/C=CN/O=openHiTLS/OU=TestEnc/CN=TLCP_Server"&nbsp;\
&nbsp; &nbsp; -userid&nbsp;"1234567812345678"&nbsp;-out server_enc.csr
$HITLS&nbsp;x509 -req -in&nbsp;server_enc.csr \
&nbsp; &nbsp; -CA ca.crt -CAkey ca.key -days 365 \
&nbsp; &nbsp; -userid&nbsp;"1234567812345678"&nbsp;-md sm3 \
&nbsp; &nbsp; -extfile openssl_ext.cnf -extensions server_enc \
&nbsp; &nbsp; -out server_enc.crt

生成客户端签名/加密证书(双向鉴别需要):

# 客户端签名证书
$HITLS&nbsp;genpkey -algorithm EC -pkeyopt&nbsp;"ec_paramgen_curve:sm2"&nbsp;-out client_sign.key
$HITLS&nbsp;req -new -key client_sign.key \
&nbsp; &nbsp; -subj&nbsp;"/C=CN/O=openHiTLS/OU=TestSign/CN=TLCP_Client"&nbsp;\
&nbsp; &nbsp; -userid&nbsp;"1234567812345678"&nbsp;-out client_sign.csr
$HITLS&nbsp;x509 -req -in&nbsp;client_sign.csr \
&nbsp; &nbsp; -CA ca.crt -CAkey ca.key -days 365 \
&nbsp; &nbsp; -userid&nbsp;"1234567812345678"&nbsp;-md sm3 \
&nbsp; &nbsp; -extfile openssl_ext.cnf -extensions client_sign \
&nbsp; &nbsp; -out client_sign.crt

# 客户端加密证书
$HITLS&nbsp;genpkey -algorithm EC -pkeyopt&nbsp;"ec_paramgen_curve:sm2"&nbsp;-out client_enc.key
$HITLS&nbsp;req -new -key client_enc.key \
&nbsp; &nbsp; -subj&nbsp;"/C=CN/O=openHiTLS/OU=TestEnc/CN=TLCP_Client"&nbsp;\
&nbsp; &nbsp; -userid&nbsp;"1234567812345678"&nbsp;-out client_enc.csr
$HITLS&nbsp;x509 -req -in&nbsp;client_enc.csr \
&nbsp; &nbsp; -CA ca.crt -CAkey ca.key -days 365 \
&nbsp; &nbsp; -userid&nbsp;"1234567812345678"&nbsp;-md sm3 \
&nbsp; &nbsp; -extfile openssl_ext.cnf -extensions client_enc \
&nbsp; &nbsp; -out client_enc.crt

关键:必须使用 -extfile 和 -extensions 参数生成 Version 3 证书。如果不加扩展参数,hitls 默认生成 Version 1 证书,缺少 KeyUsage 等必要扩展属性,会导致 TLCP 握手失败(错误码 0x20c001f:HITLS_CERT_ERR_CREATE_SIGN)。

验证证书:

$HITLS&nbsp;x509 -in&nbsp;server_sign.crt -text -noout |&nbsp;head&nbsp;-20
# 确认输出包含:
# &nbsp; Version: 3 (0x02)
# &nbsp; X509V3 extensions:
# &nbsp; &nbsp; &nbsp; KeyUsage: critical
# &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Digital Signature, Certificate Sign, CRL Sign

$HITLS&nbsp;verify -CAfile ca.crt -nokeyusage server_sign.crt
# 输出: OK

使用自定义证书的命令行示例(与内置证书对比):

export&nbsp;CUSTOM=/path/to/custom_certs

# 双向鉴别(自定义证书,无需 -chainCAfile)
$HITLS&nbsp;s_server \
&nbsp; &nbsp; -tlcp -accept 127.0.0.1:4433 \
&nbsp; &nbsp; -cipher TLS_ECDHE_SM4_CBC_SM3 \
&nbsp; &nbsp; -CAfile&nbsp;$CUSTOM/ca.crt \
&nbsp; &nbsp; -tlcp_sign_cert&nbsp;$CUSTOM/server_sign.crt -tlcp_sign_key&nbsp;$CUSTOM/server_sign.key \
&nbsp; &nbsp; -tlcp_enc_cert&nbsp;$CUSTOM/server_enc.crt -tlcp_enc_key&nbsp;$CUSTOM/server_enc.key \
&nbsp; &nbsp; -provider default -state

hitls vs OpenSSL 对比:hitls genpkey 输出纯 PKCS #8 私钥(无需过滤),req 原生支持 -userid 参数,x509 支持 -extfile/-extensions 生成 Version 3 证书。5e742870 commit 之后,hitls 已完全取代 OpenSSL 用于 SM2 证书生成。


五、抓包分析

5.1 抓包命令

# 终端3:tcpdump 抓包(在客户端启动前开始)
mkdir&nbsp;-p captures

# TLCP(TCP,端口4433)
sudo&nbsp;tcpdump -i lo -w captures/tlcp_ecdhe_two_way.pcap port 4433

# TLCP 单向鉴别(ECC 密码套件)
sudo&nbsp;tcpdump -i lo -w captures/tlcp_ecc_one_way.pcap port 4433

# DTLCP(UDP,端口4444 — ECDHE 密码套件)
sudo&nbsp;tcpdump -i lo -w captures/dtlcp_ecdhe_two_way.pcap port 4444

# DTLCP 单向鉴别(ECC 密码套件,端口4444)
sudo&nbsp;tcpdump -i lo -w captures/dtlcp_ecc_one_way.pcap port 4444

# 测试完成后 Ctrl+C 终止抓包

5.2 Wireshark 分析要点

用 Wireshark 打开 pcap 文件,关键分析点:

| 分析项 | TLCP/DTLCP 关键字段 | 说明 | | — | — | — | | 协议标识 | ClientHello/ServerHello 中版本 TLS 1.1 + TLCP 扩展(0x0002) | TLCP 使用扩展类型 0x0002 标识国密协议 | | 密码套件 | ServerHello 中 Cipher Suite 字段 | 确认 ECDHE_SM4_CBC_SM3 或 ECC_SM4_CBC_SM3 | | 双证书 | Certificate 消息 | 单向鉴别时无客户端Certificate消息 | | ECDHE握手 | ServerKeyExchange内SM2签名值 (r,s分量) | ECDHE专有 | | 单向标记 | 是否存在 CertificateRequest 消息 | ECC+无验证 无CR,ECDHE 始终有CR | | 加密切换 | Change Cipher Spec + Encrypted Finished | 2组 CCS+Finished |


六、面向未来的敏捷架构与开源生态

当前能力只是起点,openHiTLS 更大的价值在于面向算法演进的前瞻设计。随着后量子密码标准化推进,基于椭圆的 SM2 面临量子计算威胁(Shor 算法可在多项式时间内破解 ECC),SM4 则需应对 Grover 算法带来的等效密钥长度减半问题。openHiTLS 通过以下机制应对:

  • • Provider 插件机制:算法以插件形式挂载,切换算法无需改动应用层代码
  • • PQCP 密码创新仓:承载国产后量子算法的工程化落地
  • • 配置驱动:通过编译选项和配置文件指定算法,避免硬编码

openHiTLS 已集成多种后量子算法:ML-KEM(密钥封装)、ML-DSA(数字签名)、SLH-DSA(无状态哈希签名)、FrodoKEM、Classic McEliece 等,可通过构建选项按需启用。

这套设计使得密码标准演进时,应用层仅需少量配置调整即可完成算法迁移,大幅降低了密评整改的长期成本。

生态层面,openHiTLS 由社区技术委员会治理,10+产学研组织共建,已形成”高校创新算法设计 + 社区工程化实现 + 企业规模化应用”的协作链条。社区定期举办开源实习活动,面向高校学生提供密码学实践机会,为密评领域持续输送人才。


七、结语

对于密评从业者而言,openHiTLS 的价值不仅在于它是一个”免费的密码库”,更在于它提供了一套可审查、可裁剪、可演进的密码基础设施。从国密算法到安全协议,从编译集成到抗量子迁移,它为密评建设提供了从当下合规到未来演进的全链路支撑。在合规要求趋严、技术迭代加速的当下,拥抱开源密码套件或许是比采购黑盒产品更可持续的选择。


附录 A:常见错误码

| 错误码 | 十进制 | 宏名称 | 含义 | 典型原因 | | — | — | — | — | — | | 0x27 | 39 | (外层封装错误) | Failed to create config and connection | 聚合错误,查看下层更具体错误码 | | 0x20c0029 | 34340905 | HITLS_CERT_ERR_ENCODE | Failed to encode the certificate (证书编码失败) | ECDHE单向鉴别:客户端无加密证书,EncodeEncCert() 收到 NULL | | 0x2040017 | 33816599 | HITLS_MSG_HANDLE_NO_PEER_CERTIFIACATE | Not receive the peer certificate (未收到对端证书) | 对端未发送Certificate消息(或发送了空Certificate)。常量名中 “CERTIFIACATE” 系源码拼写错误,应为 CERTIFICATE | | 0x20c001f | 34340895 | HITLS_CERT_ERR_CREATE_SIGN | 证书签名创建失败 | SM2 userid 未正确配置,或自定义证书缺少 KeyUsage 扩展时触发 | | 0x20a000c | 34209804 | HITLS_REC_NORMAL_RECV_UNEXPECT_MSG | Record 层收到意外消息 | 对端握手失败后发送 Alert,导致 Record 层收到非预期消息。也可能是 SM 算法未集成到默认 Provider(检查编译宏 HITLS_CRYPTO_PROVIDER_DEFAULT_SM) | | 0x20a000e | 34209806 | HITLS_REC_INVLAID_RECORD | 无效记录(握手消息解析失败) | 密码套件不匹配或握手消息格式异常 | | 0x2040005 | 33816581 | HITLS_MSG_HANDLE_CIPHER_SUITE_ERR | 密码套件错误(不支持或不匹配) | 编译时未启用对应密码套件宏 |

错误码位结构:0x2 0c 0029 = 错误级别(2=ERROR) + 模块ID(0c=HITLS_CERT) + 模块内错误号(29)。模块ID 对照:04 =MSG_HANDLE, 0a=REC, 0c=CERT。详见 include/tls/hitls_error.h。

A.1 0x20c0029 深入分析(密评中常见)

调用链(从客户端收到 ServerKeyExchange 到返回错误):

parse_server_key_exchange.c:495 &nbsp; SAL_CERT_ClntGmEncodeEncCert() &nbsp;← 尝试编码客户端加密证书
&nbsp; &nbsp; ↓
cert.c:736 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;EncodeEncCert(ctx, peerCert->encCert, useLen)
&nbsp; &nbsp; ↓ &nbsp;peerCert->encCert == NULL &nbsp;(客户端未提供加密证书)
cert.c:679 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (cert == NULL) return NULL;
&nbsp; &nbsp; ↓
parse_server_key_exchange.c:497 &nbsp; → HITLS_CERT_ERR_ENCODE (0x20c0029)

附录 B:参考资源

  • • 官网:https://openhitls.net
  • • 官方源码仓库:https://gitcode.com/openHiTLS/openhitls
  • • 文档中心:https://docs.openhitls.net
  • • API 参考:https://apidoc.openhitls.net

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。

本文转载自:利刃信安 利刃信安 利刃信安《openHiTLS 初识》

openHiTLS初识 网络安全文章

openHiTLS初识

文章总结: 本文介绍openHiTLS开源密码套件,针对密评中密码产品选型封闭、算法切换成本高、自研密码模块验证难三大痛点,提出模块化五组件架构、国密全栈支持与
评论:0   参与:  0