适用范围:DM8 安全版 V8.1.3.62 及以上 / GmSSL 3.1.1 / Linux(RH6、RH7 已验证)
关键词:国密、SM2、SM3、SM4、TLCP、ENABLE_ENCRYPT、GMSSL、达梦、东方通 TongWeb
本文把《达梦数据库 GMSSL 配置方法 V1.2》的官方步骤与《GMSSL 适配说明 V1.1》的实战排错经验合并成一条完整链路:环境准备 → 证书生成 → 数据库配置 → 应用/JDBC 适配 → 抓包验证 → 常见问题速查。文中所有命令与脚本均来自上述两份文档,可直接照做。
《商用密码管理条例》与国密改造要求业务系统在数据传输环节使用国家商用密码算法。达梦数据库(DM8 安全版)已集成 GMSSL 支持,可把数据库通信从国际标准 TLS 切换到国密 TLCP,实现通信加密 + 双向身份认证双重保障。
GMSSL 是基于 OpenSSL 扩展改造的开源密码工具箱,保留了 OpenSSL 的大部分 API,因此改造后的调用方式与原有 SSL 用法差异很小,落地成本低。
| 类别 | 算法/协议 | 说明 |
|---|---|---|
| 非对称加密 | SM2 | 椭圆曲线公钥密码算法,密钥长度 256 位 |
| 哈希算法 | SM3 | 密码杂凑算法,输出 256 位摘要 |
| 对称加密 | SM4 | 分组密码算法,密钥长度 128 位 |
| 证书格式 | X.509 v3 | 遵循 GB/T 20518 标准 |
| 通信协议 | TLCP | 国密传输层密码协议(基于 TLS 改造) |
GMSSL 本身还支持 SM9、ZUC 等算法,本场景主要用到 SM2/SM3/SM4。
| 组件 | 版本要求 |
|---|---|
| 操作系统 | Linux(RH6、RH7 已验证) |
| 数据库 | DM8 安全版(V8.1.3.62 及以上) |
| GMSSL | GmSSL 3.1.1 |
| 编译工具 | cmake 3.16+ |
⚠️ 前置条件:数据库侧必须使用安全版产品安装包并配备带安全版的授权(key)文件,否则
ENABLE_ENCRYPT=3无法生效。
ENABLE_ENCRYPT 参数速查达梦通过 dm.ini 中的 ENABLE_ENCRYPT 控制加密模式,这是整个方案的总开关:
| 取值 | 含义 |
|---|---|
| 0 | 不开启 SSL 加密和 SSL 认证 |
| 1 | 开启 SSL 加密和 SSL 认证(TLS) |
| 2 | 开启 SSL 认证但不加密 |
| 3 | 使用 GMSSL 进行通信加密和认证(国密模式) |
| 4 | 开启 SSL 加密,不开启认证 |
国密改造只需要改这一个值:
ENABLE_ENCRYPT=3。注意该取值从 V8.1.3.62 版本开始支持,低版本请先升级。
GmSSL 3.0 之后改用 cmake 构建,系统若没有 cmake 需先自行安装(注意系统版本兼容性):
cmake-3.16.0-Linux-x86_64 可用cmake-3.28.4-Linux-x86_64 可用unzip /opt/GmSSL-3.1.1.zip
cd GmSSL-3.1.1
需要做两处源码修改,否则编译会失败:
CMakeLists.txt,加上 C99 标准声明:set(CMAKE_C_FLAGS "-std=c99")
include/gmssl/tls.h,补上头文件引用:#include <sys/select.h>
mkdir build
cd build
cmake ..
make
make test
sudo make install
系统没装 cmake 时,可用下载包里的绝对路径执行,例如:
/opt/cmake-3.16.0-Linux-x86_64/bin/cmake ..
编译成功后,动态库会生成在 build/bin 目录下(如 libgmssl.so)。
export LD_LIBRARY_PATH=/opt/GmSSL-3.1.1/build/bin:$LD_LIBRARY_PATH
验证命令行工具是否可用:
gmssl version
能正常输出版本号即安装成功。
采用三级结构,各级均使用 SM2 密钥对、由上一级签名,形成完整信任链:
根证书(rootcacert.pem)
└── 中间证书 / Sub CA(cacert.pem,可选)
├── 服务器证书:签名证书 signcert + 加密证书 enccert
└── 客户端证书:clientcert.pem
达梦服务端采用的是双证书模式:
signcert.pem(数字签名)+enccert.pem(密钥加密),最终合并为double_certs.pem。
创建 server_gmssl 目录,把 gen_server.sh 放进去执行:
mkdir server_gmssl && cd server_gmssl
gen_server.sh 脚本内容(为便于阅读已按语义分行):
#!/bin/bash -x
# 1) 生成根证书 CA
gmssl sm2keygen -pass dm1234 -out rootcakey.pem
gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA \
-days 3650 -key rootcakey.pem -pass dm1234 -out rootcacert.pem \
-key_usage keyCertSign -key_usage cRLSign -ca
gmssl certparse -in rootcacert.pem
# 2) 生成中间证书(Sub CA)
gmssl sm2keygen -pass dm1234 -out cakey.pem
gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN "Sub CA" \
-key cakey.pem -pass dm1234 -out careq.pem
gmssl reqsign -in careq.pem -days 365 -key_usage keyCertSign -ca \
-path_len_constraint 0 -cacert rootcacert.pem -key rootcakey.pem \
-pass dm1234 -out cacert.pem
gmssl certparse -in cacert.pem
# 3) 生成服务器签名证书
gmssl sm2keygen -pass dm1234 -out signkey.pem
gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost \
-key signkey.pem -pass dm1234 -out signreq.pem
gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature \
-cacert cacert.pem -key cakey.pem -pass dm1234 -out signcert.pem
gmssl certparse -in signcert.pem
# 4) 生成服务器加密证书
gmssl sm2keygen -pass dm1234 -out enckey.pem
gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost \
-key enckey.pem -pass dm1234 -out encreq.pem
gmssl reqsign -in encreq.pem -days 365 -key_usage keyEncipherment \
-cacert cacert.pem -key cakey.pem -pass dm1234 -out enccert.pem
gmssl certparse -in enccert.pem
# 5) 合并签名证书 + 加密证书 + 中间 CA,形成服务端证书链
cat signcert.pem > double_certs.pem
cat enccert.pem >> double_certs.pem
cat cacert.pem >> double_certs.pem
创建 client_gmssl 目录,先把中间 CA 相关文件复制过去:
mkdir client_gmssl cp cacert.pem cakey.pem rootcacert.pem /opt/GmSSL-3.1.1/build/bin/client_gmssl/
gen_client.sh 脚本内容:
#!/bin/bash -x
gmssl sm2keygen -pass dm1234 -out clientkey.pem
gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN Client \
-key clientkey.pem -pass dm1234 -out clientreq.pem
gmssl reqsign -in clientreq.pem -days 365 -key_usage digitalSignature \
-cacert cacert.pem -key cakey.pem -pass dm1234 -out clientcert.pem
gmssl certparse -in clientcert.pem
至此动态库与证书全部生成完毕。
(1)密码与有效期都写在脚本里
示例中证书密码统一为 dm1234,有效期为 365 天。想自定义直接改脚本中的 -pass 与 -days 参数即可。
subj 选项含义对照:
| 缩写 | 含义 |
|---|---|
| C | Country Name,证书持有者所在国家(填国家代码) |
| ST | State or Province Name,州或省份 |
| L | Locality Name,城市 |
| O | Organization Name,所属组织/公司 |
| OU | Organizational Unit Name,所属部门 |
| CN | Common Name,通用名(服务端通常填域名或主机名) |
| — | Email Address,通信邮箱 |
(2)证书和动态库可以复用
现象:用 GMSSL 脚本或命令行生成证书时,-days 最大只能设到 3563 天(约 9.76 年),超出会被报错或自动截断。
原因:GMSSL 基于 OpenSSL 1.1.1 分支开发,该分支在 include/internal/cryptlib.h 中硬编码了 X509_MAX_VALIDITY_PERIOD 宏,默认值 3650 天(实际编译后表现为 3563 天),属于安全保守设计,并非国密算法本身的缺陷。RFC 5280 也建议 CA 签发证书有效期不宜超过 20 年。
对业务的影响:
| 场景 | 影响 |
|---|---|
| 根证书 / 自签名 CA | 通常期望 15~20 年,3563 天无法满足,需每 10 年更换一次根,带来全链路信任更新成本 |
| 嵌入式 / 物联网 | 设备生命周期可能长达 15 年,证书到期后 OTA 更新困难,易导致设备离线 |
| 离线分发 | 一次性烧录后无法联网更新,超长有效期需求迫切 |
应对策略:
X509_MAX_VALIDITY_PERIOD 宏的可行性(需做安全评估与回归测试)。安装安全版数据库软件后初始化实例(示例):
./dminit path=/dbdata/dmdata port_num=5236 page_size=32
把 dm.ini 中的 ENABLE_ENCRYPT 改为 3 并保存:
ENABLE_ENCRYPT = 3
cp -r client_gmssl server_gmssl libgmssl.so* /home/dmdba/dm/dmdbms/bin chown -R dmdba:dinstall /home/dmdba/dm/dmdbms/
证书目录规划原则:路径要简洁,不要有中文、空格、特殊符号。
:3 模式启动时必须传入 signkey_pass 和 enckey_pass,否则连接会失败。
前台方式:
./dmserver /dbdata/dmdata/DAMENG/dm.ini signkey_pass=dm1234 enckey_pass=dm1234
脚本方式:在服务启动脚本中,给 dmserver 命令同样追加上述两个参数即可。
方式一(默认证书路径):仅 SYSDBA 用户可验证通过,普通用户用这种方式会失败。
方式二(指定证书路径):显式指定客户端证书路径并配置 ENABLE_ENCRYPT 参数验证,普通用户可用。
在达梦管理工具的连接配置中启用 GMSSL 并指定客户端证书目录与密钥库密码即可。
若为主备集群环境,需要把 signkey_pass 和 enckey_pass 追加到 dmwatcher.ini 的 INST_STARTUP_CMD 参数后面,否则备库/守护进程拉起实例时拿不到密钥口令。
dm_svc.conf 配置(推荐的服务名方式)通过 SSL_CONFIG 参数可以为不同登录用户指定各自的证书路径与密码:
TIME_ZONE=(480)
LANGUAGE=(cn)
SSL_CONFIG=((USER=(SYSDBA) SSL_PATH=(/home/dmdba/dmdbms/bin/client_gmssl) SSL_PWD=(dm1234)))
SSL_CONFIG=((USER=(GMTEST) SSL_PATH=(/home/dmdba/dmdbms/bin/client_gmssl) SSL_PWD=(dm1234)))
GMTEST=(192.168.60.132:5236,192.168.60.131:5236)
配好之后,Java 程序里直接连服务名即可:jdbc:dm://GMTEST。
| 项目 | 说明 |
|---|---|
| 驱动版本 | DmJdbcDriver8.jar(DM8 及以上;部分环境为 DmJdbcDriver18.jar,以实际版本包为准) |
| 驱动类名 | dm.jdbc.driver.DmDriver |
| 连接协议 | 支持 TLS 1.2 及国密 TLCP |
| 依赖环境 | 需正确配置 dm_svc.conf 的 SSL 参数,并在客户端部署相应证书 |
jdbc:dm://IP:5236?gmsslenable=true&sslfilespath=/home/bin/client_gmssl&sslkeystorepass=dm1234
| 参数 | 示例值 | 说明 |
|---|---|---|
gmsslenable |
true |
启用 GMSSL 加密 |
sslfilespath |
/home/bin/client_gmssl |
客户端证书及密钥文件所在路径 |
sslkeystorepass |
dm1234 |
密钥库密码(与生成证书时一致) |
LogLevel |
info |
日志级别:off 不记录 / assert 断言 / eror 仅错误 / warm 警告 / sql SQL 执行 / info 全部 |
logDir |
日志目录 | JDBC 过程文件生成目录,默认 JVM 当前工作目录 |
(一)驱动加载方式
确保 DmJdbcDriver8.jar 在 classpath 中,且 GMSSL 的 JNI 依赖(libjnigecApi.so、libgmssl.so 等)能被 JVM 找到。
方式 A(推荐,最稳妥)——显式指定原生库路径:
java -cp /home/bin/DmJdbcDriver8.jar:/app.jar \ -Djava.library.path=/home/bin \ com.xxx.Main
方式 B——环境变量式:
export LD_LIBRARY_PATH=/home/bin:$LD_LIBRARY_PATH
java -cp /home/bin/DmJdbcDriver8.jar:/app.jar com.xxx.Main
注意:若启动脚本里重置了
JAVA_OPTS,可能把路径清掉,需检查脚本逻辑。
(二)动态库加载失败排查顺序
JVM 报 UnsatisfiedLinkError 或找不到 libcrypto.so 时,按以下顺序排查:
LD_LIBRARY_PATH 与 -Djava.library.path 均已配置,且指向实际存在的目录;.so 权限:ls -la /home/bin/*.so,确保运行用户有读 + 执行权限;file libgmssl.so,与 JVM 位数(32/64 位)一致;ldd libgmssl.so 检查二级依赖,确认无 missing 项。步骤一:上传依赖包与客户端证书
/home/);/home/bin/ 下包含达梦依赖包、GMSSL 依赖包以及客户端证书文件。步骤二:配置环境变量
方式一(业务用户级,推荐):
# 编辑 ~/.bash_profile 或 ~/.bashrc,添加:
export LD_LIBRARY_PATH=/home/bin:$LD_LIBRARY_PATH
# 保存后执行
source ~/.bash_profile
方式二(系统全局级):
# 编辑 /etc/profile,末尾添加:
export LD_LIBRARY_PATH=/home/bin:$LD_LIBRARY_PATH
# 保存后执行
source /etc/profile
步骤三:调整连接字符串 —— 按 6.3 的格式改写 JDBC URL。
步骤四:启动应用并验证 —— 重启应用服务后检查日志,连接成功且无报错即配置完成。
(一)XML 里的连接串 & 必须转义
在 TongWeb 的 datasource.xml、context.xml 或控制台数据源配置页中配置 JDBC 串时,URL 中的 & 属于 XML 特殊字符,必须转义,否则报:
The reference to entity "gmsslenable" must end with the ';' delimiter
jdbc:dm://127.0.0.1:5236?gmsslenable=true&sslfilespath=/home/bin/client_gmssl&sslkeystorepass=dm1234 jdbc:dm://127.0.0.1:5236?gmsslenable=true&sslfilespath=/home/bin/client_gmssl&sslkeystorepass=dm1234
建议:凡是出现在 XML 配置文件中的 JDBC URL,一律使用
&作为参数分隔符。
(二)LD_LIBRARY_PATH 不够,必须加 -Djava.library.path
TongWeb 在启动阶段就把 JVM 的 java.library.path 固化了,仅配系统环境变量 LD_LIBRARY_PATH 覆盖不了 JVM 运行时的动态库搜索路径,典型报错:
UnsatisfiedLinkError: no libxxx in java.library.path
解决方法(任选其一):
# 1) 在 TongWeb/bin/startserver.sh 的 JAVA_OPTS 中追加
-Djava.library.path=/home/bin
# 2) 在 TongWeb 控制台「服务器配置 → JVM 参数」中填写
-Djava.library.path=/home/bin
# 3) Spring Boot 内嵌 TongWeb:在 application.properties 或启动脚本中加
-Djava.library.path=/home/bin
两者作用层级不同,建议同时配置、互补不冲突:
| 变量 / 参数 | 作用层级 | 管理对象 |
|---|---|---|
LD_LIBRARY_PATH |
Linux 动态链接器(OS 层) | C/C++ 层 dlopen 找 .so,以及 .so 再依赖 .so 的链路 |
-Djava.library.path |
JVM 属性(Java 层) | Java 代码 System.loadLibrary() 去哪找 libxxx.so |
(三)驱动版本兼容性
GMSSL 通信是达梦后期增强特性,低版本 DmJdbcDriver8.jar 可能不识别 gmsslenable,表现为:
No suitable driver found;排查步骤:
$JAVA_HOME/jre/lib/ext、TongWeb/lib、WEB-INF/lib,删除旧版 DmJdbcDriver*.jar,避免多版本共存;jar tf DmJdbcDriver8.jar | grep Gmssl 确认是否包含 GMSSL 相关类;Windows 下缺少 Linux 那样统一的动态库搜索机制,GMSSL 依赖的原生 DLL 又多,容易报 UnsatisfiedLinkError / NoClassDefFoundError。以下是实测可用的完整步骤。
步骤一:下载并放置 GMSSL 依赖包
从官方渠道获取 Windows 版 GMSSL 依赖包,解压后确认含 gmssl.dll 及相关依赖 DLL,放到达梦安装目录的 bin 下(默认 D:\dm8\bin)。
步骤二:用 Dependencies 工具扫描 gmssl.dll 的缺失依赖
打开 D:\dm8\bin\gmssl.dll,查看依赖树中是否有红色问号/叉号标记。常见缺失:
VCRUNTIME140D.dll(Visual C++ 2015-2022 调试版运行时)ucrtbased.dll(Universal C Runtime 调试版)MSVCR120.dll、VCRUNTIME140.dll步骤三:补全缺失 DLL(注意位数匹配)
从微软官网或可信渠道下载缺失文件。位数必须与达梦管理工具一致:64 位工具配 64 位 DLL。可通过「右键 DLL → 属性 → 详细信息」查看架构(PE32 为 32 位,PE32+ 为 64 位)。
步骤四:放入系统目录
| DLL 位数 | 目标路径 |
|---|---|
| 64 位 | C:\Windows\System32\ |
| 32 位 | C:\Windows\SysWOW64\ |
同时建议再复制一份到 D:\dm8\bin\ 作为双保险,完成后重启电脑刷新 DLL 缓存。
步骤五:配置 PATH(放最前面)
把 D:\dm8\bin 加到系统 Path 变量列表最顶部,防止与其他数据库客户端的同名 DLL 冲突:
「此电脑」→ 属性 → 高级系统设置 → 环境变量 → 系统变量 Path → 新建 D:\dm8\bin → 上移到顶部 → 确定保存 → 重启管理工具。
步骤六:连接配置
| 配置项 | 填写内容 |
|---|---|
| 主机 | 数据库服务器 IP(如 192.168.154.148) |
| 端口 | 5236(达梦默认端口) |
| 用户名 | SYSDBA |
| 密码 | 对应数据库用户密码 |
| 启用 GMSSL | 勾选(连接串会自动附加 gmsslenable=true) |
| SSL 证书路径 | D:\dm8\bin\client_gmssl |
| SSL 密钥库密码 | dm1234(与证书生成时一致) |
步骤七:验证
连接成功即可正常打开对象浏览器。若仍报错,查看 D:\dm8\tool\ 目录下的日志,对照第九章速查表排查。
配置完只是"以为对了",抓包才是"确认对了"。
DM8 默认使用 TLSv1.2 加密传输。TLSv1.2 用于在两个通信应用之间提供加密支持,通过安全 hash 函数计算消息认证码,保证数据的机密性、完整性与真实性。
抓包可见 DM8 改用国密 TLCP 传输。TLCP(Transport Layer Cryptography Protocol)是基于 TLS/SSL 协议改造的国密加密传输协议,采用 SM 系列密码算法与数字证书,保障传输层的机密性、完整性、身份认证与抗攻击能力。
实操建议:每次环境变更后都抓一次包,尤其要确认协议从
TLSv1.2变成了TLCP——否则很可能只是"连接成功但没走国密"。
三个放置位置:
server_gmssl → 数据库服务 bin/ 下;client_gmssl → 数据库服务 bin/ 下(服务端本机用 ssl 认证登录用);client_gmssl → 应用服务器的规划目录 + 客户端 bin/ 下(应用端/客户端走 GMSSL 通信登录用)。重启规则(很重要):
| 变更内容 | 是否需要重启 |
|---|---|
| 服务端证书变更 | ✅ 必须重启数据库服务 |
| 新增客户端证书 | ❌ 不需要重启 |
| 客户端证书重做(服务端未动) | ❌ 不需要重启 |
主备集群改 dmwatcher.ini |
✅ 按集群规范重启守护进程 |
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
Connection refused |
服务端未启动 GMSSL 或端口未监听 | 确认 dm.ini 中 ENABLE_ENCRYPT=3,且启动时已传 signkey_pass 和 enckey_pass |
| 连接成功但查询报错 | 证书有效期过期 | 检查证书有效期,过期则重新生成并替换;-days 建议不超过 3563 |
SSL handshake failed |
TLCP 协议版本不匹配 | 确认客户端与服务端均使用 GMSSL 3.1.1,且 ENABLE_ENCRYPT=3 |
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
No suitable driver found |
驱动版本过低,不支持 GMSSL | 升级至 V8.1.3.62+ 配套驱动,清理旧版 jar,验证 jar 内含 Gmssl 类 |
UnsatisfiedLinkError: no libxxx |
JVM 找不到 GMSSL 依赖库 | 启动参数加 -Djava.library.path=/home/bin,并确认 LD_LIBRARY_PATH 已配置 |
libcrypto.so 找不到 |
动态库路径未继承或权限不足 | 检查 .so 权限(读+执行),确认启动用户能访问 /home/bin |
驱动加载成功但 gmsslenable 不生效 |
实际生效的是旧版驱动 | 排查 $JAVA_HOME/jre/lib/ext、TongWeb/lib 等目录,删除旧版驱动 |
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
XML 解析报错 The reference to entity must end with ';' |
JDBC URL 中的 & 未转义 |
将 XML 中 JDBC URL 的所有 & 替换为 & |
| TongWeb 启动后仍读旧依赖路径 | JVM 的 java.library.path 启动时被固化 |
在启动脚本 JAVA_OPTS 或控制台 JVM 参数中显式加 -Djava.library.path=/home/bin |
| 数据源配置保存后不生效 | 数据源缓存未刷新或驱动未加载 | 重启 TongWeb 实例,确认驱动 jar 放在正确目录(优先 TongWeb/lib) |
ENABLE_ENCRYPT=3 不会生效。ENABLE_ENCRYPT=3 有版本门槛(V8.1.3.62 起),升级前先确认。signkey_pass / enckey_pass,脚本启动也一样,主备集群别忘了 dmwatcher.ini。& 一律写 &。LD_LIBRARY_PATH 不够,TongWeb / Java 应用都要显式加 -Djava.library.path。Wireshark 抓包确认协议是 TLCP。jre/lib/ext、TongWeb/lib、WEB-INF/lib 中的旧驱动。参考文档
外部链接
文章
阅读量
获赞
