如何编译启用 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)上给出可落地的编译参数与验证脚本。

知识点

  1. 国密算法定位:SM2 为非对称签名/密钥交换,SM3 为 256 bit 哈希,SM4 为 128 bit 分组对称加密;三组算法在 EVP 层统一以 NID_sm2、NID_sm3、NID_sm4_ecb 等符号暴露。
  2. OpenSSL 国密补丁:官方 1.1.1 主线未合并 SM 套件,需使用 BabaSSL-8.3.0Tongsuo-8.3.2(原 BabaSSL 更名),两者保持 API 兼容并新增 EVP_sm4_ecb() 等接口。
  3. Erlang crypto 模块加载规则:crypto 在启动时通过 dlopen 动态绑定 libcrypto.so,调用 OPENSSL_init_crypto();若找不到对应 NID,则回退报错 “unsupported cipher”。
  4. CouchDB 版本耦合:CouchDB 3.2+ 强制 OTP-23 及以上;OTP-24/25 已把 crypto 的 NIF 层改为 dirty-scheduler,编译时需打开 --enable-dirty-schedulers
  5. 国产 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 仅路径差异。

  1. 准备国密 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

  2. 下载并解压 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)
    
  3. 配置并编译

    ./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
    
  4. 验证 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 绑定成功。

  5. 重新编译 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” 警告。

  6. 国密 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 握手成功即完成全链路国密改造。

拓展思考

  1. 性能调优:SM4 在 armv8 平台有 CE 指令加速,可在 Tongsuo 编译时加 -DSM4_USE_ARM_CE;CouchDB 高并发场景建议把 crypto NIF 调度到 dirty-IO-scheduler,防止哈希计算阻塞 Erlang 调度器。
  2. 合规审计:国密项目需通过 商用密码产品认证(型号证书),仅算法可用还不够,必须保证密钥管理、随机数发生器符合 GM/T 0005-2021;CouchDB 层需开启 hmac_sm3 做日志完整性校验,并对接国密 USBKey 或服务器密码机。
  3. 容器化交付:麒麟 OS 的 Docker 基础镜像默认不带 Tongsuo,可把步骤 1 编译产物做成 tongsuo:8.3.2 基础镜像,再在多阶段构建中复制 /opt/tongsuo/opt/erlang-25.3-sm,保证算法库与运行时版本一致,避免宿主机 OpenSSL 升级导致 ABI 漂移。