1。简介1.1为什么需要加密互联网是一个开放的环境,通信双方都是未知的。为了防止双方的有效信息被第三方窃听、篡改或冒充,需要对信息进行保护。即所有信息加密,避免被第三方窃听;可通过验证机制识别信息是否被篡改,并配备身份认证,防止身份冒充。Internet通信安全基于SSL/TLS协议。1.2SSL/TLS协议的历史1996年,在之前的基础上,SSL3.0版本问世并得到广泛应用;1999年,互联网标准化组织ISOC取代NetScape,发布了SSLTLSversion1.0的升级版本,又称SSL3.1;SSL和TLS指的是同一套加密协议,只是不同时期叫法不同。2006年和2008年,TLS经历了两次升级,分别是TLS1.1和TLS1.2。一般推荐使用TLS1.2,主流浏览器都支持。2.SSL/TLSEvolution熟悉一套技术的演进步骤,比直接看最新版本更容易理解。2.1明文时代,小帅直接明文给小美发消息。缺点很明显。第三方小黑可以轻松窃取信息,还可以修改后发给小美。而且,小美收到后并不知道,还以为是小帅送的。2.2对称加密时代,小帅和小美保存着同一个秘钥。小帅发来的信息先加密,小美收到后用同样的密码解密。这种使用相同密钥进行加密和解密的算法称为对称加密算法。短期内,小黑对加密数据无能为力,但每次更改秘钥,都需要提前协商。如果协商出现问题,当小帅将新密钥告知小美时,密钥被小黑截获,后续密文将给小黑。说,他还可以解密成明文。也可以篡改明文信息,然后用相同的秘钥加密后发送给小美。2.3非对称加密时代由于交换密钥存在风险,小帅和小美采用非对称加密算法。双方分别保存自己的私钥和公钥,并配对。私钥自己保管,公钥由私钥运算生成发送给对方。不能从公钥推导出私钥;但是用公钥加密的密文可以用私钥解密;使用私钥签名,使用公钥验证;这种使用不同密钥的加密和解密算法就变成了非对称加密算法。通信前,双发先将自己的公钥发送给对方,私钥保密;小帅先用小美提供的公钥加密数据,同时用自己的私钥签名标记,打包一起发给小美,小美用自己的私钥解密,然后用小帅的公钥验证,确认收到的信息是否来自小帅。在这种加密通信形式中,公钥被协商和传输。即使被小黑截获,也无法解密后面的信息,因为解密必须要用到私钥。但是,如果小黑子在第一次交换公钥时截获了公钥,截获了小帅发给小美的公钥,然后将自己的假公钥发给小美;截获小美发来的数据,小黑用自己的私钥解密,再用自己的私钥加密后发给小帅。完成了这么一套复杂的加密协议,结果还是存在隐患。2.4公证时代的问题在于公钥的交换。小梅收到了一个公钥。如何证明公钥确实是小帅签发的?比如买房,只有房管部门确认并盖章录入系统的房产证才是真实的。房产证,才能放心交易。公钥的真实性由CA(CertificateAuthority)认证机构保证,公钥的真实性得到保证和公证。CA也是基于非对称加密算法。小帅先把自己的公钥给CA,CA用自己的私钥加密数据。加密后的数据称为小帅的数字证书。之前小帅发给小美的公钥,改为发CA加密的数字证书。小美收到后,通过CA颁发的CA证书(包括CA的公钥)对小帅的数字证书进行解密,从而得到小帅的公钥。问题是小美如何保证CA证书不是小黑伪造的呢?CA证书是预置在浏览器或操作系统中,或者是在嵌入式设备中,不需要在线获取,自然不存在劫持和篡改的问题。虽然小黑仍然可以用公钥截获数字签名证书,但是可以用CA公钥解密其中的内容;但是他没有CA秘钥,所以无法伪造正确的数字签名证书,也就是小帅的真实公钥Black可见,不可更改。如果改了小美,会发现异常,只是公钥没什么价值。2.5TLS协议时代公证时代的解决方案是SSL/TLS协议加密通信的基础。由于使用非对称加密算法比对称加密算法更复杂并且消耗计算资源,因此出于效率的考虑,非对称加密将只用于传输一条信息,即对称加密密钥。确定对称加密的密钥,后续有效信息采用对称加密算法进行网络传输。既保证了网络通信的安全,又不影响效率。SSL/TLS协议的基本过程:1.通过CA系统交换公钥2.使用非对称加密算法交换密钥进行对称加密3.对有效数据使用对称加密算法,密文传输的前两步也是称为“握手阶段”(handshake),是SSL/TLS加密通信的基础。2.6TLS的应用在SSL/TLS出现之前,很多应用层协议(http、ftp、smtp等)都存在网络安全问题。最常见的http协议在传输过程中使用明文信息。一旦传输消息被截获,传输内容将被泄露;如果消息在传输过程中被篡改,对方不容易发现;不能保证消息交换对端身份的可靠性。为了解决此类安全问题,在应用层和传输层之间增加了SSL/TLS协议,并升级为https。SSL/TLS目前广泛应用于数据安全协议中。关于SSL/TLS的开源软件包很多,比如openSSL、mbedtls等,openSSL功能更强大,mbedtls体积更小,更适合嵌入式设备。3.mbedtls随着物联网的发展,设备节点的安全越来越重要。与互联网上的openSSL相比,物联网中的嵌入式设备更适合小型灵活的MbedTLS。它曾经被称为PolarSSL。可按需配置,减少硬件资源消耗。mbedtls内置了大量的加解密和哈希算法源码。即使不使用tls加密,也可以从中挖掘出各种算法,比如AES/RSA/MD5等。但是openSSL有更强大的功能。mbedtls是一个开源软件加密库,采用Apache2.0许可协议,用标准C语言编写;独立的模块设计,降低了模块之间的耦合度。从功能上看,主要包括加密库、X509证书、SSL/TLS协议三部分。3.1软件包进入https://tls.mbed.org/[1],点击下载,在https://github.com/ARMmbed/mbedtls[2]下载源码。Git下载界面上有说明CompilingMbedTLSreleases中目前使用的三个activebuildsystem:GNUMakeCMakeMicrosoftVisualStudio(MicrosoftVisualStudio2013orlater)目前我使用的芯片SDK内置的mbedtls个人接触过v2.4.0、v2。4.2和v2.14.1,把git版本切换到v2.14.1,最后一次提交是2018年。前期我们在电脑上模拟测试,选择了VisualStudio2013。3.2软件结构mbedtls的源码结构如下图mbedtls\include\mbedtls,可以在version.h中查看版本信息,重点是config.h配置,mbedtls是一组加密集,你在实际项目使用中只需要选择一小部分,配置函数宏,削减代码,简化操作。毕竟mbedtls跑一次,一般的arm单片机未必能搞定。programs\ssl下是参考示例、TLS客户端和服务器示例以及DTLS的UDP版本。嵌入式设备多为客户端应用,主要参考ssl_client2.c中的很多配置参数,应用也可以替换ssl_client1.c。测试TLS客户端,首先要准备3个文件,CA证书,客户端公钥数字证书,私钥。一般情况下,命名后缀为:.crtCA证书。pempublickey,CA加密后的公钥,又称数字证书。key私钥有时会和crt、pem混在一起,本质上是CA公钥加密的文件如果没有服务器联调,也可以用自己的ssl_server2.c作为服务器。3.3demo流程分析ssl_client2.c的例子都在main函数里面,大致流程如下:1.首先加载各种证书和秘钥,配置opt结构体成员初始化,比如TLS版本,加密套件类型等2.然后开始连接服务器mbedtls_net_connect3.初始化tls参数mbedtls_ssl_config_defaults,设置网络收发回调函数等4.SSL/TLS握手过程比较复杂。简单来说就是通信双方验证对方的身份,获得对方的公钥,确认加密方式,并对后续数据进行加密或加密。准备解密mbedtls_ssl_handshake5.验证服务器返回的证书mbedtls_ssl_get_verify_result6.如果前面的过程顺利,就可以使用mbedtls_ssl_write,mbedtls_ssl_read收发数据7.测试后清理8.与标准socket编程相比,接口有一定差异对应:4.mbedtls移植首先在电脑端进行模拟测试,确定参数并简化示例中的赋值,因为实际项目参数不会经常变化,优化代码,特别是key加载,嵌入的文件保存在一个数组中,而不是作为文件加载。另外,结合加密级别,确定加密套件类型。仿真测试正常后,移植到ARM平台。主要变化涉及三个方面:网络连接、内存管理和定时器。4.1网络接口mbedtls默认的网络接口,mbedtls/library/net_socket.c,可以在windows下运行。特别注意,默认的socket操作是阻塞模式;一般不适合ARM平台,关闭MBEDTLS_NET_C,结合硬件平台重新实现网络接口。主要包括以下函数:voidmbedtls_net_init(mbedtls_net_context*ctx);intmbedtls_net_connect(mbedtls_net_context*ctx,constchar*host,constchar*port,intproto);intmbedtls_net_recv(void*ctx,unsignedchar*buf,size_tlen);buf,size_tlen,uint32_ttimeout);intmbedtls_net_send(void*ctx,constunsignedchar*buf,size_tlen);voidmbedtls_net_free(mbedtls_net_context*ctx);如果需要DUP版本的DTLS,还需要在该文件下实现其他几个接口。具体过程参考dtls_client。C。对于自定义实现的网络收发接口,需要注册mbedtls_ssl_set_bio来告知底层。mbedtls_ssl_set_bio(&ssl,&server_fd,mbedtls_custom_send,//重写的mbedtls_net_send为底层提供发送接口mbedtls_custom_recv,//为底层提供接收接口mbedtls_custom_recv_timeout)4.2内存管理自定义实现类型如下内存申请和释放接口:void*calloc(unsignedintnum,unsignedintsize)voidfree(void*ptr)实现后,函数注册到底层mbedtls_platform_set_calloc_free(custom_calloc,custom_free)4.3定时器接口DTLS定时器,注册到底层。#ifdefined(__MBEDTLS_DTLS__)//Setdelaystowatchvoidplatform_timing_set_delay(void*data,uint32_tint_ms,uint32_tfin_ms){platform_timing_delay_context*ctx=(platform_timing_delay_context*)data;ctx->int_ms=int_ms;ctxfin->fin_ms=fin_msct!=x->{if(snapshot=custom_get_systicks();}}//获取delaysexpiredintplatform_timing_get_delay(void*data){platform_timing_delay_context*ctx=(platform_timing_delay_context*)data;unsignedlongelapsed_ms;if(ctx->fin_ms==0){return(-1);}elapsed_ms=custom_ticks_to_milli_secs(custom_get_systicks()-ctx->snapshot);//转为毫秒if(elapsed_ms>=ctx->fin_ms){return(2);}if(elapsed_ms>=ctx->int_ms){return(1);}return0;}#endif/*__MBEDTLS_DTLS__*///注册到底层mbedtls_ssl_set_timer_cb(&ssl,&platform_timer,platform_timing_set_delay,platform_timing_get_delay);运行这个函数即可,即使使用阻塞模式也不会有其他问题。实际的嵌入式设备连接到网络,肯定还有其他任务需要被执行。如果设备支持操作系统,你可以单独分配一个线程或任务给mbedtls。推荐使用阻塞机制实现接口,方便调试,尤其是https下载场景。但特殊情况不支持阻塞,重写网络接口时需要特殊处理。例如示例mbedtls_net_connect进行域名解析并连接到服务器。这一步,嵌入式设备的无线网络基本都会返回一个异常,表示被阻塞等待。为了解决这个问题,后续的握手过程需要拆分执行。本来是联网后执行mbedtls_ssl_handshake,等待握手过程结束MBEDTLS_SSL_HANDSHAKE_OVER或while出错,而不是每次收到读消息事件时执行一次或多次mbedtls_ssl_handshake_step。(这个我没有亲自验证)mbedtls_ssl_set_bio注册的读写接口支持非阻塞,mbedtls_ssl_write和mbedtls_ssl_read对应的是应用层接口。底层socket上报read_ready后,判断本次握手已经完成,然后执行mbedtls_ssl_read。4.5证书和密钥测试可以使用mbedtls例子自带的证书、公钥和私钥,但实际项目需要根据服务器域名生成ca证书,以及公钥和私钥双方。源代码programs\pkey下有生成秘钥的代码。作为客户端,需要验证服务器提供的公钥证书,所以本地需要一个CA证书,类似于第一次登录12306时要下载的证书,加上客户端自己的公钥和私钥key,一共有3个文件。gen_key.c生成keyfile.key私钥,默认密钥长度为4096,虽然理论上1024有风险,但是运行速度更快;然后使用openSSL命令行生成公钥。OpenSSL>rsa-inprivate.key-pubout-outpublic.keyopenSSL下载地址https://www.openssl.org/,安装后提示收费,实际使用无异常。秘钥也可以使用openSSL生成OpenSSL>genrsa-outprivate.key2048不知道用法的可以使用help查看说明。至于CA证书,需要在平台端生成,然后提供给设备端。4.6加密套件和配置剪裁确定合适的加密套件,可以屏蔽不用的算法;在计算机运行时瞬间完成,但在实际的arm硬件中可能需要很长时间。例如,在使用RSA时,握手阶段可能需要很长时间。您可以选择ECDSA或缩短的密钥长度。5.Section当前物联网对数据安全的关注度不高。它使用自定义协议以类似于纯文本的方式进行交互,或者使用单一的加密方法。未来智能家居、涉及物业计费的设备节点、特殊行业可能会逐步使用。加密通信,mbedtls是更好的选择之一。即使不使用TLS,也可以选择简单的对称加密。mbedtls也是一个加密算法库,大家可以根据需要提取合适的源码集成。本文转载自微信公众号“嵌入式系统”,可通过以下二维码关注。转载本文请联系EmbeddedSystems公众号。
