赞
踩
通过阅读openssl源码具体分析ssl握手中的报文交互流程,包括发送和处理每个报文所做的主要事情。同时分析ssl协议中的一些主要问题,包括tls和gmssl的区别、单向认证和双向认证、两种会话复用方式对比,调用openssl接口实现ssl客户端和服务端之间的通信。
注意:
TLS1.2中密钥交换算法为RSA、gmssl的密钥交换算法有ECC、ECDHE,RSA密钥交换算法没有server key exchange。
双向认证才有服务端给客户端发送的certificate request,和客户端给服务端发送的certificate和certificate verify。
TLS1.2为国际协议,使用单证书,certificate中只有一个证书,gmssl为国密协议使用的是双证书,certificate中有两个证书,一个签名证书、一个加密证书。
1.TLS1.2属于国际协议,所有算法套件都为国际算法。gmssl属于国密协议,所用算法都为国密算法。
国际算法套件:
国密算法套件:
2.TLS1.2国际算法使用的是单证书,签名证书和加密证书是同一个证书;gmssl使用的是双证书,分为签名证书和加密证书,签名用签名证书,加密使用加密证书。
**单证书体系:**本地生成公私钥对,将相关的证书信息和公钥提交给CA机构,CA审核通过后用私钥进行签名,将签名和公钥组合成数字证书,本地保存数字证书,CA不保管证书。
双证书体系: gmssl要求使用双证书,包括签名证书和加密证书。签名证书在签名使用,仅仅用来验证身份使用,其公私钥均由服务器自己产生,并且由自己保管,CA不负责保管;加密证书在加密时使用,其公私钥均由CA产生,并由CA保管。公钥加密私钥解密,一旦私钥遗失,则数据就无法还原了,所以CA一般会备份私钥。
双证书的优势:
1.从道理来说两个密钥具有不同的属性,逻辑上应该分开处理。其最主要的原因是国家要保证必要的时候有能力对某些通信进行监控,如果采用单证书,除了自己谁也无法解密,因为CA机构没有保存证书对应的私钥;如果是双证书由于加密的公私钥都是在CA产生的,CA保存了私钥,所以就能对加密的通信进行监控,因此国家法律规定使用双证书。
2.一份用公钥加密过后的数据(由于数据都是二进制我们并不能辨别这是经过公钥加密过的数据)进行签名就会造成解密,然后将以为是签名的数据发送出去就会造成信息泄露。
单向认证是客户端验证服务端的合法性,大多数应用都是单向认证。
双向认证不光是客户端要验证服务端的合法性,服务端也要验证客户端的合法性。双向认证较为严格,需要服务端加载签发客户端的ca证书,只有某些特定的场合才会使用。
会话复用:在前一次TLS完成后,断开链接的较短时间间隔后重新建立TLS链接,这时可以不用走TLS完整的握手流程,可以通过上图中进行简化握手流程,能够极大提升握手的效率。
**sessionid:**客户端想要恢复session,需要在client hello包中加入本地保存的session id,发送给服务端进行解析,服务端在session cache中查找客户端发送过来的session id,如果找到则服务端恢复session id对应的session,并将session id封装到server hello 包当中发送给客户端,客户端解析服务端的session id如果与客户端发送的一致则客户端将本地保存的session恢复;如果没有找到,服务端则随机生成一个session id发送给客户端,客户端解析后发现与自己发送的session id不一致,则重走整个握手流程。
**SessionTicket:**客户端在client hello中设置一个SessionTicket扩展来标志自己支持sessionticket。如果服务器希望使用sessionticket机制,服务器把本地的session状态存入ticket中,ticket会被加密并mac保护,无法篡改,然后封装到server hello当中发送给客户端。客户端把收到的ticket缓存起来。当客户端希望恢复会话时,就把保存的ticket封装到client hello包中的session ticket中发送给服务端,服务端收到后解密ticket,并计算mac确认没被篡改,从解密的ticket当中获取session,恢复session。
SessionTicket是一种不需要服务器状态,恢复TLS session的一种方式,使用这种方式可将用于恢复会话的参数保存到客户端,用于减轻大型服务端的缓存压力。
下面这些场景当中尤其有用:
1.用户量巨大,session id的方式耗费服务器内存过多。
2.服务器希望长时间缓存session。
下图是用openssl接口实现的简易客户端和服务端的基本流程图,函数接口基于Gmssl_gmbrowser-v0.1开源国密openssl实现的国密ssl客户端和服务端。不同openssl版本的实现接口可能会不一样,但是大致的流程都是一致的。
**SSL_set_verify:**如果不调用该函数,则本端不会验证对端发过来的证书,这样就不能判断对端的合法性就能建立ssl通道,存在风险。
双向认证客户端和服务端都需要调用函数 SSL_set_verify(con, SSL_VERIFY_PEER, NULL)。
**SSL_CTX_set_security_level:**最新的openssl在使用接口SSL_CTX_use_certificate_file会调用ssl_security_cert来判断密钥的安全性,如果密钥不安全则不能加载上证书。
SSL_CTX_set_security_level(c_ctx, 0); 表明不做对密钥做安全性检查,能够兼容老版本。
设置协议版本:
ssl_ctx_options=SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3
SSL_CTX_set_options(ctx, ssl_ctx_options); //表示不使用国际算法,只发送国密算法套件,如果不设置就会发送默认的国际算法套件
加载证书:
国密需要加载双证书,国际协议只加载单证书,也可以调用加载国密证书的接口,因为该函数会对证书进行区分加载。
也可以使用接口加载私钥:SSL_CTX_use_RSAPrivateKey_file
设置算法套件:
国密协议使用国密算法套件,国密算法,对称加密算法:sm1、sm4;非对称加密算法:sm2;摘要算法:sm3
国密算法组合成的算法套件如下:
GMTLS_SM2_WITH_SMS4_SM3
GMTLS_SM2DHE_WITH_SMS4_SM3
GMTLS_SM2_WITH_SM1_SM3
国际协议使用国际算法套件,国际算法,对称算法:AES、DES等;非对称算法:rsa;摘要算法:sha系列,MD5
国际算法组合成的算法套件为:
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_DH_RSA_WITH_AES_128_CBC_SHA
每一版的openssl的算法套件可能名称不一样。
初始化ssl连接中的meth:
国密SSL_METHOD
__owur const SSL_METHOD *gmtls_method(void); //客户端和服务端都可以用
__owur const SSL_METHOD *gmtls_server_method(void); //服务端用
__owur const SSL_METHOD *gmtls_client_method(void); //客户端用
国际SSL_METHOD
tls1.2的method
__owur const SSL_METHOD *tlsv1_2_method(void);
__owur const SSL_METHOD *tlsv1_2_server_method(void);
__owur const SSL_METHOD *tlsv1_2_client_method(void);
tls1.3的method
__owur const SSL_METHOD *sslv3_method(void);
__owur const SSL_METHOD *sslv3_server_method(void);
__owur const SSL_METHOD *sslv3_client_method(void);
本篇文章梳理了tls1.2和gmssl的具体握手流程和算法实现,只进行了宏观层面的大致分析,openssl当中还有许多的细节需要在后续文章中继续分析。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。