Netty集成国密开源基础密码库Tongsuo

这篇具有很好参考价值的文章主要介绍了Netty集成国密开源基础密码库Tongsuo。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、Tongsuo是啥?

二、为什么选择Tongsuo?

三、Netty的实现

四、编译方法

 1.Netty

 2.Netty-tcnative

 3.Tongsuo

五、集成过程

 1.Netty-tcnative编译Tongsuo密码库

 2.Netty-tcnative调用Tongsuo密码库

 3.Netty调用Netty-tcnative

六、测试TLCP协议

总结


前言

        当前的软件形势来看,国密和信创都是大势所趋。项目组中也越来越多场景要求使用通道加密。维护的项目中大多用到netty框架,netty默认支持SSL/TLS,但都是国际算法,当前openssl对国密算法支持仅限于基础算法层面,还没有涉及到通道加密。记录一下Netty适配国密SSL通道加密的过程,避免遗忘,也算是让自己这段时间的成果不白费。


一、Tongsuo是啥?铜锁开源密码库 · 语雀铜锁/Tongsuo(原BabaSSL)是一个提供现代...https://www.yuque.com/tsdoc

二、为什么选择Tongsuo?

        简单粗暴,选择Tongsuo是因为他获得了国密资质,了解这个东西的人估计都会选择Tongsuo吧。

三、Netty的实现

        Netty调用Netty-tcnative组件,Netty-tcnative调用集成Openssl算法库的JNI动态库。集成思路:将Openssl替换为Tongsuo。

        Netty编译需要依赖Netty-tcnative组件。Netty-tcnative使用Maven编译时会去下载密码库代码,编译密码库组件,并将密码库的库文件静态依赖到JNI动态库中。由此完成Netty到密码库的通道加密的调用。

四、编译方法

 1.Netty

mvnw clean install \
 -DskipTests \
 -Dmaven.test.skip=true \
 -Dcheckstyle.skip=true 

 2.Netty-tcnative

mvnw clean install

 3.Tongsuo

config -O3 -fno-omit-frame-pointer -fPIC \
no-ssl3 no-shared no-comp \
-DOPENSSL_NO_HEARTBEATS \
--strict-warnings enable-ntls \
--prefix=${opensslHome} --openssldir=${opensslHome}

make -j

make install

五、集成过程

 1.Netty-tcnative编译Tongsuo密码库

        Netty-tcnative主要分为openssl-classes(JNI Java类模块)、openssl-dynamic(JNI 动态库C代码模块)、openssl-static(动态库集成密码库模块),其他的两个模块boringssl-static和libressl-static没用过,没有深入了解。maven编译时直接注释了。

openssl-static pom.xml中编译openssl有windows、linux、mac不同系统的profile,对应替换Tongsuo下载路径:

<configuration>
  <target>
	<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
	<if>
	  <available file="${opensslSourceDir}" />
	  <then>
		<echo message="OpenSSL was already downloaded, skipping the build step." />
	  </then>
	  <else>
		<echo message="Downloading Tongsuo" />
		<mkdir dir="${opensslSourceDir}" />
		<get 
src="https://codeload.github.com/Tongsuo-Project/Tongsuo/zip/refs/heads/master" 
dest="${project.build.directory}/tongsuo-${opensslVersion}.zip" verbose="on" />
		<exec executable="unzip" failonerror="true" 
dir="${project.build.directory}/" resolveexecutable="true">
		   <arg line="tongsuo-${opensslVersion}.zip" />
		 </exec>
		<move file="${project.build.directory}/Tongsuo-master"
 tofile="${opensslSourceDir}" />
	  </else>
	</if>
  </target>
</configuration>

替换Tongsuo编译方式,只进行了Linux的测试:

<configuration>
  <target>
	<taskdef resource="net/sf/antcontrib/antcontrib.properties" />

	<if>
	  <available file="${opensslHome}" />
	  <then>
		<echo message="OpenSSL was already build, skipping the build step." />
	  </then>
	  <else>
		<echo message="Building OpenSSL" />
		<mkdir dir="${opensslHome}" />
		<exec executable="config" failonerror="true" dir="${opensslSourceDir}" 
resolveexecutable="true">
		  <arg line="-O3 -fno-omit-frame-pointer -fPIC 
no-ssl3 no-shared no-comp -DOPENSSL_NO_HEARTBEATS
		  --strict-warnings enable-ntls
		  --prefix=${opensslHome} --openssldir=${opensslHome}" />
		</exec>
		<exec executable="make" failonerror="true" dir="${opensslSourceDir}" 
resolveexecutable="true">
		  <arg value="depend" />
		</exec>
		<exec executable="make" failonerror="true" dir="${opensslSourceDir}" 
resolveexecutable="true" />
		<exec executable="make" failonerror="true" dir="${opensslSourceDir}" 
resolveexecutable="true">
		  <!-- Don't install manpages to make things as fast a possible -->
		  <arg value="install_sw" />
		</exec>
	  </else>
	</if>
  </target>
</configuration>

  2.Netty-tcnative调用Tongsuo密码库

        调用方式参考Tongsuo文档《NTLS 使用手册》:

NTLS 使用手册 · 语雀编译 NTLS 功能NTLS 在 Tongsuo 的术...https://www.yuque.com/tsdoc/ts/hedgqf        修改openssl-dynamic中sslcontent.c文件中的make方法中更换为NTLS的握手方式;扩展setCertificate方法和setCertificateBio方法增加对国密双证的支持。

TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jint protocol, jint mode)
{
...
    if (mode == SSL_MODE_CLIENT) {
        ctx = SSL_CTX_new(NTLS_client_method());
        SSL_CTX_enable_ntls(ctx);
    } else if (mode == SSL_MODE_SERVER) {
        ctx = SSL_CTX_new(NTLS_server_method());
        SSL_CTX_enable_ntls(ctx);
    } else {
        ctx = SSL_CTX_new(TLS_method());
    }
...
}
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificate)
(TCN_STDARGS, jlong ctx,jstring enccert, jstring enckey,
jstring signcert, jstring signkey, jstring password)
{
...
    enc_key_file  = J2S(enckey);
    enc_cert_file = J2S(enccert);
    sign_key_file  = J2S(signkey);
    sign_cert_file = J2S(signcert);
    if (!enc_key_file) {
        enc_key_file = enc_cert_file;
    }
    if (!sign_key_file) {
        sign_key_file = sign_cert_file;
    }
    if (!enc_key_file || !enc_cert_file) {
        tcn_Throw(e, "No Enc Certificate file specified or invalid file format");
        rv = JNI_FALSE;
        goto cleanup;
    }
    if (!sign_key_file || !sign_cert_file) {
        tcn_Throw(e, "No Sign Certificate file specified or invalid file format");
        rv = JNI_FALSE;
        goto cleanup;
    }
    if ((p = strrchr(enc_cert_file, '.')) != NULL && strcmp(p, ".pkcs12") == 0) {
        if (!ssl_load_pkcs12(c, enc_cert_file, &encpkey, &encxcert, 0)) {
            ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
            tcn_Throw(e, "Unable to load certificate %s (%s)",
                      enc_cert_file, err);
            rv = JNI_FALSE;
            goto cleanup;
        }
    } else {
        if ((encpkey = load_pem_key(c, enc_key_file)) == NULL) {
            ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
            tcn_Throw(e, "Unable to load certificate key %s (%s)",
                      enc_key_file, err);
            rv = JNI_FALSE;
            goto cleanup;
        }
        if ((encxcert = load_pem_cert(c, enc_cert_file)) == NULL) {
            ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
            tcn_Throw(e, "Unable to load certificate %s (%s)",
                      enc_cert_file, err);
            rv = JNI_FALSE;
            goto cleanup;
        }
    }
    if ((p = strrchr(sign_cert_file, '.')) != NULL && strcmp(p, ".pkcs12") == 0) {
        if (!ssl_load_pkcs12(c, sign_cert_file, &signpkey, &signxcert, 0)) {
            ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
            tcn_Throw(e, "Unable to load certificate %s (%s)",
                      sign_cert_file, err);
            rv = JNI_FALSE;
            goto cleanup;
        }
    } else {
        if ((signpkey = load_pem_key(c, sign_key_file)) == NULL) {
            ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
            tcn_Throw(e, "Unable to load certificate key %s (%s)",
                      sign_key_file, err);
            rv = JNI_FALSE;
            goto cleanup;
        }
        if ((signxcert = load_pem_cert(c, sign_cert_file)) == NULL) {
            ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
            tcn_Throw(e, "Unable to load certificate %s (%s)",
                      sign_cert_file, err);
            rv = JNI_FALSE;
            goto cleanup;
        }
    }
    if (SSL_CTX_use_enc_certificate(c->ctx, encxcert) <= 0) {
        ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
        tcn_Throw(e, "Error setting enc certificate (%s)", err);
        rv = JNI_FALSE;
        goto cleanup;
    }
    if (SSL_CTX_use_sign_certificate(c->ctx, signxcert) <= 0) {
        ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
        tcn_Throw(e, "Error setting sign certificate (%s)", err);
        rv = JNI_FALSE;
        goto cleanup;
    }
    if (SSL_CTX_use_enc_PrivateKey(c->ctx, encpkey) <= 0) {
        ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
        tcn_Throw(e, "Error setting enc private key (%s)", err);
        rv = JNI_FALSE;
        goto cleanup;
    }
    if (SSL_CTX_use_sign_PrivateKey(c->ctx, signpkey) <= 0) {
        ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
        tcn_Throw(e, "Error setting sign private key (%s)", err);
        rv = JNI_FALSE;
        goto cleanup;
    }
...
}
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificateBio)
(TCN_STDARGS, jlong ctx,jlong enccert, jlong enckey,
jlong signcert, jlong signkey,jstring password)
{
...
    if (!enckey) {
        enckey = enccert;
    }
    if (!enccert || !enckey) {
        tcn_Throw(e, "No Enc Certificate file specified or invalid file format");
        rv = JNI_FALSE;
        goto cleanup;
    }
    if (!signkey) {
        signkey = signcert;
    }
    if (!signcert || !signkey) {
        tcn_Throw(e, "No Sign Certificate file specified or invalid file format");
        rv = JNI_FALSE;
        goto cleanup;
    }
    if ((enc_pkey = tcn_load_pem_key_bio(c->password, enc_key_bio)) == NULL) {
        ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
        ERR_clear_error();
        tcn_Throw(e, "Unable to load Enc certificate key (%s)",err);
        rv = JNI_FALSE;
        goto cleanup;
    }
    if ((enc_xcert = tcn_load_pem_cert_bio(c->password, enc_cert_bio)) == NULL) {
        ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
        ERR_clear_error();
        tcn_Throw(e, "Unable to load Enc certificate (%s) ", err);
        rv = JNI_FALSE;
        goto cleanup;
    }
    if ((sign_pkey = tcn_load_pem_key_bio(c->password, sign_key_bio)) == NULL) {
        ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
        ERR_clear_error();
        tcn_Throw(e, "Unable to load Sign certificate key (%s)",err);
        rv = JNI_FALSE;
        goto cleanup;
    }
    if ((sign_xcert = tcn_load_pem_cert_bio(c->password, sign_cert_bio)) == NULL) {
        ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
        ERR_clear_error();
        tcn_Throw(e, "Unable to load Sign certificate (%s) ", err);
        rv = JNI_FALSE;
        goto cleanup;
    }
    if (SSL_CTX_use_enc_certificate(c->ctx, enc_xcert) <= 0) {
        ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
        ERR_clear_error();
        tcn_Throw(e, "Error setting enc certificate (%s)", err);
        rv = JNI_FALSE;
        goto cleanup;
    }
    if (SSL_CTX_use_sign_certificate(c->ctx, sign_xcert) <= 0) {
        ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
        ERR_clear_error();
        tcn_Throw(e, "Error setting sign certificate (%s)", err);
        rv = JNI_FALSE;
        goto cleanup;
    }
    if (SSL_CTX_use_enc_PrivateKey(c->ctx, enc_pkey) <= 0) {
        ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
        ERR_clear_error();
        tcn_Throw(e, "Error setting enc private key (%s)", err);
        rv = JNI_FALSE;
        goto cleanup;
    }
    if (SSL_CTX_use_sign_PrivateKey(c->ctx, sign_pkey) <= 0) {
        ERR_error_string_n(ERR_get_error(), err, ERR_LEN);
        ERR_clear_error();
        tcn_Throw(e, "Error setting sign private key (%s)", err);
        rv = JNI_FALSE;
        goto cleanup;
    }
...
}

  3.Netty调用Netty-tcnative

        Netty的改动主要是对应国密双证的支持。握手通过SSLContext.make方法完成。改动内容在handler模块ssl包中。

CipherSuiteConverter.java 添加国密套件映射。Java中使用下滑线的套件名,需要映射到Openssl的连字符的套件名。反正是个名字,我给他重新定义了一下:

 TLCP_ECDHE_SM4_CBC_SM3 >> ECDHE-SM2-SM4-CBC-SM3
 TLCP_ECDHE_SM4_GCM_SM3 >> ECDHE-SM2-SM4-GCM-SM3
 TLCP_ECC_SM4_CBC_SM3 >> ECC-SM2-SM4-CBC-SM3
 TLCP_ECC_SM4_GCM_SM3 >> ECC-SM2-SM4-GCM-SM3

SslContextBuilder.java 增加国密双证的支持。

SslUtils.java        添加国密套件。

 ReferenceCountedOpenSslClientContext.java、ReferenceCountedOpenSslServerContext.java客户端和服务端握手类,添加国密双证的支持。

六、测试TLCP协议

final SslContext sslCtx = SslContextGMBuilder.forClient().protocols()
		.trustManager(SysConfigMangrClient.TRUST_CERT)
		.keyManager(SysConfigMangrClient.ENC_CERT, SysConfigMangrClient.ENC_KEY,
				SysConfigMangrClient.SIGN_CERT, SysConfigMangrClient.SIGN_KEY,
				SysConfigMangrClient.KEY_PASSWORD == null ? null
						: new String(SysConfigMangrClient.KEY_PASSWORD),
				new String[]{SysConfigMangrClient.ROOT_CERT})
        // 客户端控制国密套件
		.ciphers(Arrays.asList("TLCP_ECDHE_SM4_CBC_SM3"))
		.build();

代码参见:

fury_fox · master · t-camp · AtomGit


总结

        本次完成了Tongsuo TLCP协议的四种国密套件;X86架构的编译。

待完成的工作:

  1. TLSv1.3的TLS_SM4_GCM_SM3套件的支持。
  2. ARM架构、PPC架构、Windows的编译。mac系统一般服务器环境没有应用场景,有能力的小伙伴可以帮忙测试一下。

时代的车轮在加速的运转,在有限的视野里也要不断地追赶。文章来源地址https://www.toymoban.com/news/detail-444491.html

到了这里,关于Netty集成国密开源基础密码库Tongsuo的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 金融数据密码机国密标准GMT0045-2016

            金融数据密码机是在金融领域内,用于确保金融数据安全,并符合金融磁条卡、IC卡月特定的,主要实现PIN加密、PIN转加密、MAC产生和校验、数据加解密、签名验证以及密钥管理等密码服务功能的密码设备,也称为HSM主机加密机。相关标准包括:         GMT 0045

    2024年02月13日
    浏览(7)
  • 国密算法 SM4 对称加密 分组密码 python实现完整代码

    国密算法 SM4 对称加密 分组密码 python实现完整代码

    目前,python实现的国密算法库主要是 python-gmssl 库和 snowland-smx ( pysmx )库,二者都对SM2(仅公钥加解密和数字签名)、SM3、SM4进行了细致而优雅的实现。 GMSSL. https://github.com/duanhongyi/gmssl snowland-smx. https://gitee.com/snowlandltd/ snowland-smx-python PyCryptodome. https://www.pycryptodome.org 最近用

    2024年02月06日
    浏览(16)
  • 国密商用密码SM3杂凑算法原理分析与Java实现

    国密商用密码SM3杂凑算法原理分析与Java实现

    国密SM3算法是我国自研设计的商用密码杂凑算法,是在SHA-256的基础上进行改造的,其安全性与SHA-256相当。《SM3密码杂凑算法》于2010年12月份由国家密码管理局首次发布。后于2012年发布为密码行业标准《GM/T 0004-2012 SM3密码杂凑算法》,2016年发布为国家密码杂凑算法标准《GB

    2024年02月04日
    浏览(36)
  • 商用密码应用与安全性评估要点笔记(不公开的国密算法)

    国密算法中SM1、SM7算法不公开,调用该算法时,需要通过加密芯片的接口进行调用。 1、SM1国密算法         SM1 算法是分组密码算法,分组长度为128位,密钥长度都为 128 比特,算法安全保密强度及相关软硬件实现性能与 AES 相当,算法不公开, 仅以IP核的形式存在于芯片

    2024年02月12日
    浏览(8)
  • 国密算法概述、及算法的集成应用(sm2、sm3、sm4)

    国密算法概述、及算法的集成应用(sm2、sm3、sm4)

    由于项目的需求,需要集成国密加解密,于是对国密又温故知新了一遍。同时整理了一下国密的一些算法。 本文主要从国密相关算法的简介、应用系统的集成、工具类的封装等方面入手,对国密进行深入的学习。 为了保障商用密码的安全性,国家密码局制定了一系列密码标

    2024年02月14日
    浏览(15)
  • SpringBoot 2.7 集成 Netty 4 实现 UDP 通讯

    Netty 作为异步通讯框架,支持多种协议。本文将介绍基于 SpringBoot 2.7 整合 Netty 4 实现 UDP 通讯。 netty 版本: 3.1 服务端事务处理器(DemoUdpNettyServerHandler) 代码说明: 这里使用线程池来异步处理事务,提高系统并发性能 3.2 服务端连接类(InitUdpNettyServer) 代码说明: UDP 协议需要使用

    2024年02月03日
    浏览(9)
  • 商用密码应用安全性评估中的密评分析工具,WireShark3.7.1的国密版本

    商用密码应用安全性评估中的密评分析工具,WireShark3.7.1的国密版本

    工具之一:通信信道密码算法分析工具。 这里一般指的是WireShark类的抓包分析工具,它可以抓取常见的网络协议数据报文,然后用于离线分析。 随着商用密码体系建设的完善和推进,分析商用密码算法和协议成为密评工作中重要的一环。 电信数智密评中心,根据工作需要研

    2024年02月09日
    浏览(21)
  • Python实现国家商用密码算法sm2/sm3/sm4/sm9(国密)

    2010 年开始,我国国家密码管理局就已经开始陆续发布了一系列国产加密算法,这其中就包括 SM1、SM2、SM3 、SM4、SM7、SM9、ZUC(祖冲之加密算法)等,SM 代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。SM1 和 SM7 的算法不公开,其余算法都已成为 ISO/IEC

    2024年02月15日
    浏览(16)
  • 若依 springboot集成 netty 实现tcp监听 设备板 数据 传输

    若依 springboot集成 netty 实现tcp监听 设备板 数据 传输

    也不知道说什么   也是记录一下所用到的东西     因为  我得数据板  发送得是   tcp 10进制数据   所以  在监听端口上传信息时   要进行一此转换  10 进制  转换  16进制    下面是  所用到得所有类    MyNettyServer 类    然后  util   就是 所用的  工具类了    具体

    2024年01月22日
    浏览(13)
  • 新手入门 | 掌握国密算法:新手指南: SM2 / SM3 / SM4密码算法详解

    在密码学领域,有多种加密与签名算法,它们在信息安全领域发挥着举足轻重的作用。如今,随着互联网的快速发展,网络安全已经成为各类信息系统完整性、可用性、保密性的重要保障,越来越多的国产密码算法得到了广泛的应用与关注。在本文中,我们将重点介绍三个经

    2024年02月12日
    浏览(12)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包