当前位置:

Apache APISIX 玩转 Tongsuo 国密插件

访客 2024-02-18 960 0

本文通过解读国密的相关内容与标准,呈现了当下国内技术环境中对于国密功能支持的现状。并从API网关ApacheAPISIX的角度,带来有关国密的探索与功能呈现。

什么是国密

顾名思义,国密就是国产化的密码算法。在我们日常开发过程中会接触到各种各样的密码算法,如RSA、SHA256等等。为了达到更高的安全等级,许多大公司和国家会制定自己的密码算法。国密就是这样一组由中国国家密码管理局制定的密码算法。在国际形势越发复杂多变的今天,密码算法的国产化替代,在一些领域已经成为了一股势不可挡的潮流。

国密的官方名称为国家商用密码,简称商密,拼音缩写是SM。这也是国密标准中SM2/3/4/7/9等算法名称的来源。国密算法的命名方式非常简单直接,就像“绵阳九所”、“二机部”一样,都是“分类序号”的组合。其中SM1和SM4是对称算法,对标AES;SM2是非对称算法,对标RSA、ECDSA;SM3是摘要算法,对标MD5;等等。由于本文并非涉及到国密的实现细节,所以不会讲得非常细,也就科普下国密算法的分类。

在基础的国密算法之上,我们可以构造一个国密的垂直生态,比如实现国密算法的硬件、提供国密支持的密码库、加入国密流程的TLS握手协议等等。正如安全需要纵深防御一样,基于国密的信任链也需要有全软件栈上的支持。

因此,当我们谈论国密支持时,并不仅仅单独指可以用某一种国密算法进行加解密,而是指嵌合入国密的生态,支持某种国密的应用场景。

国密的应用场景

作为国家密码管理局制定的密码算法,国密广泛应用于电子政务(包括国家政务通、警务通等重要领域)、信创及金融业的各个应用领域。

  • 政府和金融的身份认证终端。依照现行有关规定,许多涉及政府和金融的身份认证终端(诸如USBKey、智能IC卡、银行卡终端等)都需要提供对国密的支持。
  • 国产开源操作系统。许多主打国产替代的开源操作系统,会提供基于国密的安全加固功能。比如龙蜥操作系统(AnolisOS)提到自己实现了全栈国密能力;OpenEuler也在做国密相关的一些功能,比如基于国密数字证书扩展了EFI的数字签名。
  • 信创产品。还有许多做信创生意的厂商,围绕国密推出符合相关标准的产品。例如支持使用国密算法做数字签名的PDF工具、支持国密接入标准的音视频软件等等。
  • 基于国密TLS协议的生态。也是在日常开发中接触得最多的。譬如各种国产CA厂商、支持了国密TLS的许许多多密码库和浏览器,以及国密接入的VPN和网关等等。APISIX对国密的探索与支持

ApacheAPISIX是一个动态、实时、高性能的API网关,提供负载均衡、动态上游、灰度发布、精细化路由、限流限速、服务降级、服务熔断、身份认证、可观测性等数百项功能。作为一个发迹于国内环境的API网关,APISIX自然需要考虑下如何接入国密的生态圈。

由于国密更多地用在国内环境中,尚未被OpenSSL等国际主流项目所完全接纳。如果要使用国密的功能,就涉及到更换APISIX默认的OpenSSL库为其他SSL库。

为此,我们考察了以下的项目:

  • GMSSL:北京大学开源的项目。原版基于OpenSSL1.0.2修改而来。新的GMSSL3.0基本上是重新开发,跟OpenSSL的目录结构差别很大。
  • gm-BoringSSL:个人开源项目,在BoringSSL上增加国密支持。已有两年未改动。
  • TaSSL:北京江南天安科技有限公司开源的项目。基于OpenSSL1.1.1修改而来。
  • Tongsuo:蚂蚁集团开源的项目。基于OpenSSL3.0修改而来,项目前身是BabaSSL,现已改名为铜锁/Tongsuo。由于GMSSL3.0并不基于OpenSSL,即使能保证API兼容,也没办法确保能100%替换现有OpenSSL的行为,所以被首先排除。其次gm-BoringSSL疏于维护,也被排除。

在TaSSL和Tongsuo之中,我倾向于选择Tongsuo[1]。因为Tongsuo在标准上拥有更强的话语权,比如RFC8998(TLS1.3中支持SM套件)就是由Tongsuo的开发者制定的。TaSSL则是每出一个版本,就公布一个新的仓库。比如前一个版本[2],感觉不太靠谱。

对于选择Tongsuo,我个人存在一个顾虑,就是他目前基于OpenSSL3.0的版本还没有发布正式的Release版本(第一个版本预计在2023年2月发布)。由于Tongsuo当前还没有一个固定的版本,因此社区决定先把国密相关的功能独立出来,以插件形式存在,有相关需求时可单独启用。

目前已在插件层面实现了服务端一侧国密双证书的支持,感兴趣的读者可以在官网查看gm插件介绍文档插件介绍文档[3],自行完成APISIX的编译和对应插件的安装配置工作。当然,如果想即刻预览该插件的使用过程,也可以直接参考下文内容。

快速参考:APISIX国密插件的使用启用插件

插件要求ApacheAPISIX运行在编译了Tongsuo的APISIX-Base上

首先需要安装Tongsuo(此处我们选择编译出Tongsuo的动态链接库):

#TODO:useafixedreleaseoncetheyhavecreatedone.#Seehttps://github.com/Tongsuo-Project/Tongsuo/issues/318gitclonehttps://github.com/api7/tongsuo--depth1pushdtongsuo./configsharedenable-ntls-g--prefix=/usr/local/tongsuomake-j2sudomakeinstall_sw

其次需要构建APISIX-Base,让它使用Tongsuo作为SSL库:

exportOR_PREFIX=/usr/local/openrestyexportopenssl_prefix=/usr/local/tongsuoexportzlib_prefix=$OR_PREFIX/zlibexportpcre_prefix=$OR_PREFIX/pcreexportcc_opt="-DNGX_LUA_ABORT_AT_PANIC-I${zlib_prefix}/include-I${pcre_prefix}/include-I${openssl_prefix}/include"exportld_opt="-L${zlib_prefix}/lib-L${pcre_prefix}/lib-L${openssl_prefix}/lib64-Wl,-rpath,${zlib_prefix}/lib:${pcre_prefix}/lib:${openssl_prefix}/lib64"./build-apisix-base.sh

该插件默认是禁用状态,你需要将其添加到配置文件./conf/config.yaml中才可以启用它:

plugins:-...-gm

由于APISIX的默认cipher中不包含国密cipher,所以我们还需要在配置文件./conf/config.yaml中设置cipher:

apisix:...ssl:...#可按实际情况调整。错误的cipher会导致“nosharedcipher”或“nociphersavailable”报错。ssl_ciphers:HIGH:!aNULL:!MD5

配置完成后,重新加载APISIX,此时APISIX将会启用国密相关的逻辑。

测试插件

在测试插件之前,需要准备好国密双证书。Tongsuo提供了生成【SM2双证书】的教程[4]。

在下面的例子中,我们将用到如下的证书:

#客户端加密证书和密钥t/certs/client_enc.crtt/certs/client_enc.key#客户端签名证书和密钥t/certs/client_sign.crtt/certs/client_sign.key#CA和中间CA打包在一起的文件,用于设置受信任的CAt/certs/gm_ca.crt#服务端加密证书和密钥t/certs/server_enc.crtt/certs/server_enc.key#服务端签名证书和密钥t/certs/server_sign.crtt/certs/server_sign.key

此外,还需要准备Tongsuo命令行工具。

./configenable-ntls-staticmake-j2#生成的命令行工具在apps目录下mvapps/openssl..

你也可以采用非静态编译的方式,不过就需要根据具体环境,自己解决动态链接库的路径问题了。以下示例展示了如何在指定域名中启用gm插件。要在指定域名中启用gm插件的功能,需要先创建对应的SSL对象:

#!/usr/bin/envpython#coding:utf-8importsys#sudopipinstallrequestsimportrequestsiflen(sys.argv)<=3:print("badargument")sys.exit(1)withopen(sys.argv[1])asf:enc_cert=f.read()withopen(sys.argv[2])asf:enc_key=f.read()withopen(sys.argv[3])asf:sign_cert=f.read()withopen(sys.argv[4])asf:sign_key=f.read()api_key="edd1c9f034335f136f87ad84b625c8f1"resp=requests.put("http://127.0.0.1:9180/apisix/admin/ssls/1",json={"cert":enc_cert,"key":enc_key,"certs":[sign_cert],"keys":[sign_key],"gm":True,"snis":["localhost"],},headers={"X-API-KEY":api_key,})print(resp.status_code)print(resp.text)

然后将上面的脚本保存为./create_gm_ssl.py,运行以下命令:

./create_gm_ssl.pyt/certs/server_enc.crtt/certs/server_enc.keyt/certs/server_sign.crtt/certs/server_sign.key

输出结果如下:

200{"key":"\/apisix\/ssls\/1","value":{"keys":["Yn...

完成上述准备后,可以使用如下命令测试插件是否启用成功:

./openssls_client-connectlocalhost:9443-servernamelocalhost-cipherECDHE-SM2-WITH-SM4-SM3-enable_ntls-ntls-verifyCAfilet/certs/gm_ca.crt-sign_certt/certs/client_sign.crt-sign_keyt/certs/client_sign.key-enc_certt/certs/client_enc.crt-enc_keyt/certs/client_enc.key

其中,./openssl是上文提到的Tongsuo命令行工具,9443是APISIX默认的HTTPS端口。如果一切正常,可以看到连接已经建立了起来,并输出如下信息:

...New,NTLSv1.1,CipherisECDHE-SM2-SM4-CBC-SM3...禁用插件

如果不再使用此插件,可将gm插件从./conf/config.yaml配置文件中移除,然后重启APISIX或者通过插件热加载的接口触发插件的卸载。

相关链接

如果你对该功能或者插件感兴趣,欢迎在随时在社区进行交流。

[1]https://github.com/Tongsuo-Project/Tongsuo

[2]https://github.com/jntass/TASSL-1.1.1k

[3]https://apisix.apache.org/zh/docs/apisix/next/plugins/gm/

[4]https://www.yuque.com/tsdoc/ts/sulazb

发表评论

  • 评论列表
还没有人评论,快来抢沙发吧~