如何编译启用 SM2/SM3/SM4 的 Erlang 加密模块?
解读
CouchDB 依赖 Erlang/OTP 的 crypto 模块完成 TLS 链路加密、哈希校验与 JWT 签名。国密算法(SM2/SM3/SM4)在 2018 年被写入 GB/T 32918/32905/32907,国内政务、金融、运营商项目强制合规。Erlang/OTP 主线源码默认只携带 OpenSSL 通用算法,SM 套件属于“国密扩展”,必须手动把 OpenSSL 国密补丁或 BabaSSL/Tongsuo 集成进 Erlang 编译链,再重新编译 CouchDB 依赖的 Erlang 运行时。面试时,考官想确认候选人是否理解“国密合规 + Erlang 编译链 + CouchDB 运行时”三层耦合关系,以及能否在国产操作系统(麒麟、统信 UOS、Anolis OS)上给出可落地的编译参数与验证脚本。
知识点
- 国密算法定位:SM2 为非对称签名/密钥交换,SM3 为 256 bit 哈希,SM4 为 128 bit 分组对称加密;三组算法在 EVP 层统一以 NID_sm2、NID_sm3、NID_sm4_ecb 等符号暴露。
- OpenSSL 国密补丁:官方 1.1.1 主线未合并 SM 套件,需使用 BabaSSL-8.3.0 或 Tongsuo-8.3.2(原 BabaSSL 更名),两者保持 API 兼容并新增 EVP_sm4_ecb() 等接口。
- Erlang crypto 模块加载规则:crypto 在启动时通过 dlopen 动态绑定 libcrypto.so,调用 OPENSSL_init_crypto();若找不到对应 NID,则回退报错 “unsupported cipher”。
- CouchDB 版本耦合:CouchDB 3.2+ 强制 OTP-23 及以上;OTP-24/25 已把 crypto 的 NIF 层改为 dirty-scheduler,编译时需打开
--enable-dirty-schedulers。 - 国产 OS 编译链:鲲鹏 920/arm64、龙芯 3C5000/loongarch64 平台需额外指定
CFLAGS="-march=armv8.2-a+crypto"或-march=loongarch64,并确认/usr/lib64/libcrypto.so指向国密版本,防止系统自带 OpenSSL 覆盖。
答案
步骤以 CentOS 8/Anolis OS 8.6 x86_64 为例,其他国产 OS 仅路径差异。
-
准备国密 OpenSSL
git clone -b 8.3.2 https://github.com/Tongsuo-Project/Tongsuo.git cd Tongsuo ./config enable-weak-ssl-ciphers enable-sm2 enable-sm3 enable-sm4 -fPIC -shared make -j$(nproc) sudo make install PREFIX=/opt/tongsuo sudo ln -sf /opt/tongsuo/lib64/libcrypto.so.1.1 /usr/lib64/libcrypto.so sudo ldconfig验证:
/opt/tongsuo/bin/openssl list -digest-algorithms | grep SM3应输出SM3。 -
下载并解压 Erlang/OTP-25.3
wget https://github.com/erlang/otp/releases/download/OTP-25.3/otp_src_25.3.tar.gz tar -xzf otp_src_25.3.tar.gz && cd otp_src_25.3 export ERL_TOP=$(pwd) -
配置并编译
./configure --prefix=/opt/erlang-25.3-sm \ --with-ssl=/opt/tongsuo \ --enable-dirty-schedulers \ CFLAGS="-I/opt/tongsuo/include" \ LDFLAGS="-L/opt/tongsuo/lib64 -Wl,-rpath,/opt/tongsuo/lib64" make -j$(nproc) sudo make install -
验证 crypto 加载国密算法
/opt/erlang-25.3-sm/bin/erl -noshell -eval ' crypto:start(), io:format("SM3:~p~n",[crypto:hash(sm3,<<"abc">>)]), io:format("SM4-ECB:~p~n",[crypto:crypto_one_time(sm4_ecb,<<"0123456789abcdef0123456789abcdef">>,<<"plaintextblock">>,true)]), halt().'若输出 256 bit SM3 哈希值与 16 byte SM4 密文,则 NIF 绑定成功。
-
重新编译 CouchDB
export PATH=/opt/erlang-25.3-sm/bin:$PATH git clone --branch 3.3.2 https://github.com/apache/couchdb.git cd couchdb ./configure --spidermonkey-version 78 make release编译完成后,
rel/couchdb/bin/couchdb -c查看crypto在[kernel]已加载,无 “sm3 unsupported” 警告。 -
国密 TLS 通道(可选)
修改rel/couchdb/etc/local.ini[ssl] enable = true cert_file = /path/sm2_signed_cert.pem key_file = /path/sm2_private_key.pem ciphers = SM2-WITH-SM4-SM3重启 CouchDB,使用
/opt/tongsuo/bin/openssl s_client -connect localhost:6984 -cipher SM2-WITH-SM4-SM3握手成功即完成全链路国密改造。
拓展思考
- 性能调优:SM4 在 armv8 平台有 CE 指令加速,可在 Tongsuo 编译时加
-DSM4_USE_ARM_CE;CouchDB 高并发场景建议把cryptoNIF 调度到 dirty-IO-scheduler,防止哈希计算阻塞 Erlang 调度器。 - 合规审计:国密项目需通过 商用密码产品认证(型号证书),仅算法可用还不够,必须保证密钥管理、随机数发生器符合 GM/T 0005-2021;CouchDB 层需开启
hmac_sm3做日志完整性校验,并对接国密 USBKey 或服务器密码机。 - 容器化交付:麒麟 OS 的 Docker 基础镜像默认不带 Tongsuo,可把步骤 1 编译产物做成
tongsuo:8.3.2基础镜像,再在多阶段构建中复制/opt/tongsuo与/opt/erlang-25.3-sm,保证算法库与运行时版本一致,避免宿主机 OpenSSL 升级导致 ABI 漂移。