SSL&TlS握手

SSL/TLS简介

•SSL:安全套接字层(secure socket layer)
•TLS:传输层安全协议(transport layer security)

SSL和TLS都是加密协议,旨在基于不安全的基础设施提供安全通信,比如可以用ssl协议对HTTP协议进行加密变成HTTPS。

SSL/TLS在OSI层中的位置:

ssl协议在网络分层中处于表示层。

SSL/TLS协议组成:

SSL协议是一种记录协议,协议组成包括:

1字节的content type:握手协议报文、数据协议报文、告警协议报文;

2字节的version:ssl3.0、tls1.0、tls1.1、tls1.2;

1字节的data length:表示负载数据的大小;

负载数据:ssl协议的负载数据。可以是握手数据或者是加密后的应用层数据。

扫描二维码关注公众号,回复: 1831727 查看本文章

SSL/TLS的历史  :

  SSL协议由网景(Netscape Communications Corporation)公司开发,第一个版本从未发布。

  第二版本于1994年11月发布,第一次部署是在Netscape Navigator1.1浏览器上,发行于1995年3月。但是由于SSL2.0的开发基本上没有与Netscape以外的安全专家进行商讨,所以有严重的缺点,最终退出历史舞台。

  第三版本于1995年年底发布,SSL3.0是完全重新设计的协议,一直沿用到今天。

  1996年5月,TLS工作组成立,开始将SSL从Netscape迁移至IETF。由于Microsoft和Netscape当时正在为Web的统治权争得不可开交,整个迁移过程进行得非常缓慢、艰难。最终,TLS 1.0于1999年1月问世。

  2006年4月,下一个版本TLS 1.1才问世。

  2008年8月,TLS 1.2发布。

  2016年年中,TLS 1.3草案已经经历了15次迭代,基本确定了版本号和协商。

  2017年2月,Chrome和Firefox都开始为其客户提供TLS 1.3。

一个通信过程加密的演化

    ssl握手的过程及其复杂,下面在说ssl握手之前,先看一个通信过程加密的演化过程。如果能理解了这个过程,那么ssl协议的握手也就不那么复杂。在这过程中会引入一些密码学的基本概念。

第一阶段:明文通信

    最典型的明文通信就是我们大家都熟知的http协议。但是明文通信会存在一下问题:

  • 明文的数据很容易被第三方截获,只要拿到了通信的报文,就知道了通讯的所有内容;
  • 无法进行通信双方的身份认证,任何一个人都可以冒充另一方进行通信。 

    所以明文通信是很不安全的,那么我们就把通信数据进行加密吧,以密文的方式进行传输,对数据进行加密有两种方式:对称加密和非对称加密。

  • 对称加密:加密和解密使用同一个密钥。所以只要拿到了密钥就能解密两个方向的报文。
  • 非对称加密:加密和解密使用不同的密钥。密钥分为公钥和密钥。公钥对外公开,私钥自己保有。用公钥加密的数据只能用私钥进行解密,用私钥加密的数据只能用公钥进行解密。

    由上述的定义来看,非对称加密比对称加密的强加密强度要高,那么我们接下来就用非对称加密的方式对数据进行加密。

第二阶段:非对称加密数据

    在这个阶段中,前三个报文任然是明文,但是第四个报文"你好,我是服务器"用服务器自己的私钥进行加密。客户端拥有服务器的公钥,收到报文后,用公钥进行解密,就拿到了解密后的报文"你好,我是服务器"。

由于公钥只能解密用私钥加密的数据,而私钥只有服务器拥有。所以客户端在成功用服务器的公钥解密后,就对服务器的身份进行了初步的认证:你是我拥有公钥的服务器。注意在这,客户端只能证明你是我拥有公钥的服务器。至于这个是不是真正的服务器,还并不能完全确定。

因为到目前为止客户端还无法证明自己拥有的公钥是真正服务器的公钥。这个认证过程在后续展开。但是最起码从上面的过程看来,我们已经成功的对服务器发出的报文进行了非对称加密。然后再接下来看一下后续的通讯过程:

    在这个通信过程中,在完成对服务器的认证后,客户端把''把我的余额发给我看看"用服务器的公钥进行加密。发给服务器,由于只有服务器拥有私钥,所以只有服务器能够解密这个报文。然后将客户端余额用私钥进行加密发给客户端。

在这最后一个报文出现了问题。因为,服务器是用自己私钥对余额信息进行加密的。所以只要有服务器的公钥,就能解密。而服务器的公钥又是对外公开的,所以这个方向的报文就不再安全。为了解决这个问题,我们又引入了对称加密。

第三阶段:用对称加密加密数据,用非对称加密对称加密的密钥

    在这个阶段中,客户端在确认了服务器的身份后,客户端自己选择一个对称加密算法和一个密钥,把这个对称加密算法和密钥一起用公钥加密后发送给服务器。由于对称加密算法和密钥是用公钥加密的,

就算这个加密后的内容被黑客截获了,由于没有私钥,黑客也无从知道对称加密算法和密钥的内容。然后后续的通信内容就用对称加密的密钥进行加密,这样后续的报文就不会被人解密。

  但是在第二阶段就说过,非对称加密时对服务器的认证是不完全的,只能证明,当前服务器是我拥有公钥的服务器。而不能完全证明你就是我要通信的服务器。因为还无法证明,我拥有的公钥是我客户端要连接服务器

的公钥。所以我们只要能保证当前的公钥是真正的服务器的公钥,客户端就能完全认证服务器。也就是说服务器如何正确的把自己的公钥发给客户端。所以在这里又引入了数字证书。服务器把自己的公钥放在证书里,然后在通信时把证书发给客户端。

那么为什么不直接把公钥发给客户端呢?

因为客户端会接受的任何人的公钥,不能证明当前收到的公钥就是真正服务器的公钥,黑客可以自己生成一个公钥发给客户端,冒充服务器完成上述的过程。

那么为什么证书就能证明当前的证书的公钥是真正服务器的呢?下面来看下证书的组成。

◆Issuer (证书的发布机构):指出是什么机构发布的这个证书,也就是指明这个证书是哪个公司创建的(只是创建证书,不是指证书的使用者)。

◆Valid from , Valid to (证书的有效期):证书的有效时间,或者说证书的使用期限。 过了有效期限,证书就会作废,不能使用了。

◆Public key (公钥):使用者的公钥。

◆Subject (主题):这个证书是发布给谁的,或者说证书的所有者,一般是某个人或者某个公司名称、机构的名称、公司网站的网址等。

◆Signature algorithm (签名所使用的算法):就是指的这个数字证书的数字签名所使用的加密算法,这样就可以使用证书发布机构的证书里面的公钥,根据这个算法对指纹进行解密。

◆Thumbprint, Thumbprint algorithm (指纹以及指纹算法):用来保证证书的完整性的。

  当前证书的合法性,也就是当前证书里的公钥是属于证书的拥有者的。这一特性是由证书的发布机构(CA)来证明的。在现实中CA拥有很高的权威性,能够受到广大范围的信任。CA在给网站颁发证书前,会在现实中对网站进行各种资质的调查。

如果调查的结果符合他的标准,CA机构才会颁发给网站证书,表示我能证明你是可以被信任的网站。当然这个信任也不是永久的,这就是证书的有效期。CA只能证明在这个有效期内,这个网站是被信任的。所以客户端,只要能够信任这个CA,那么这个CA

信任的网站也是可以信任的。证书就是通过这种间接证明的方式来对服务器端进行认证的。

   但是在这还是存在一个问题,客户端在收到证书后,是如何确定当前证书是信任的CA签发的呢?下面我们来看一下客户端校验证书的过程:

    在CA颁发证书时,会用CA自己的私钥进行签名,并把签名后的指纹放在证书里。签名的算法也会用CA的私钥进行加密放在证书中。而CA的公钥是放在CA自己的证书里,CA的证书会直接写在操作系统中。所以客户端能从操作系统中

拿到CA的公钥从而对当前收到的server证书里的签名算法进行解密,从而最后计算出指纹,与证书中的指纹进行比对,判断证书的合法性。

  但是在实际中,一般网站不是向客户端发送一个证书,而是一个证书链。

    在证书链中,第一个证书是最终的实体证书,也就是要访问网站的证书,这个网站的证书是用另一个中间证书进行签发的,可能这个中间证书不是当前客户端能够信任的(没写进操作系统),但是这个中间证书是由一个根证书进行签发的,而只要客户端的操作系统中有根证书的公钥。

那么客户端就能信任根证书,从而信任根证书签发的中间证书,也就能够信任中间证书签发的最终实体证书。   其中,中间证书可能有多个。也就是说在一个证书链中,只要根证书是信任的,那么这个证书链中的所有证书都是信任的。

  到目前为止,我们通过证书链,已经解决了通信加密中的认证问题,现在通信过程就演化到了第四阶段。

第四阶段:用证书链传输服务器端的公钥

    到在这个阶段为止就已经解决了对明文的加密和对服务器端的认证问题。我们所推演出的第四阶段的加密通信过程其实就是RSA认证的过程。通过这个过程大家应该就已经知道对一个通信过程进行加密的关键点是加密密钥的传输,服务器端的认证。

总结下,在上述的演化过程中,我们用对称加密的方式加密要传输的数据。而为了保证密钥的安全性,我们用非对称加密的方式传输对称加密的密钥,而非对称加密涉及到的服务器端的认证,我们用证书链的方式来解决。

 根据上述的演化过程,下面来看下SSL和TLS的的握手过程。

SSL握手流程

在握手过程中的报文介绍如下:

ClientHello报文中主要包含以下内容:

     客户端支持的最高tls版本;

    支持的加密套件的列表;

    如果过支持报文压缩的话,支持的压缩算法列表;

   一个客户端产生的32字节的随机数,用来计算密钥

ServerHello报文中主要包含以下内容:

    服务器选定的本次通信所采用的ssl版本,一般是客户端和服务器支持的最高版本的较小那个,保证双方都支持。

    服务器选定的本次通信所采用的加密套件,客户端和服务器端都支持的加密套件。

    如果过支持报文压缩的话,选定的压缩算法;

    一个服务器端生成的32 字节的随机数。

Certificate:

   可选报文,发送服务器端的证书链。

ServerKeyExchange:

    可选报文,发送用于加密的其他数据。

ServerHelloDone:

   服务器端在把用于握手的所有数据发送完毕后会发送这个报文。

ClientKeyExchange:

  客户端根据选定的加密套件,提供加密套件加密需要的客户端的参数。

ChangeCipherSpec:

   这个报文并不属于ssl协议,当客户端生成用于后续加密的密钥后会发送这个报文给服务器,告知我已准备好。可进行后续的机密通信。服务器在生成密钥后也会发送这个报文,告知客户端,我也准备好了。

finished:

   这个报文中存在 verify_data,是用主密钥、finishedlabel(一个特定的字符串)和之前握手过程的所有报文(不包含ChangeCipherSpec)为参数生成的一个随机hash值,用来验证握手的完整性。

在握手过程中对称加密密钥的生成过程:

在clienthello和serverhello传输生成的两个随机数和协商的加密套件,服务器利用ServerKeyExchange传输用于加密的其他服务器端参数。客户端利用clientkeyexchange 提供加密套件需要的客户单端参数。在这时,客户端和服务器端都保有用于生成主密钥master_secret的所有参数。在客户端和服务器端

各自生成主密钥master_secret。再由主密钥master_secret、两个随机数的和、字符串"key expansion"进一步生成最终的密钥key_block。key_block是后续对称加密的密钥。

当选用不同的加密套件时,ssl握手阶段的报文是有区别的。下面简单说下以RSA认证的SSL握手流程和密钥生成的过程。

首先客户端在clienthello报文中提供一个32 字节的随机数。

服务器在serverhello报文中提供一个32字节的随机数。

服务器把自己的证书链放在Certificate报文中发给客户端,选用RSA认证时服务器端不会发送ServerKeyExchange报文。而是在发送完证书链后发送serverhellodone。

客户端在收到服务器产生的随机数和证书链后,会在本地用clienthello报文中的随机数和serverhello中的随机数生成一个预主密钥pre_master_secret,把预祝密钥用服务器公钥加密在ClientKeyExchange报文中发给服务器。

客户端进一步以预主密钥pre_master_secret、字符串"master secret"、两个随机数的和为参数再生成一个hash值为主密钥master_secret。在以主密钥master_secret和两个随机数的和、字符串"key expansion"为参数生成一个hash值,为最终的密钥key_block,用于后续的对称加密。

当客户端生成密钥key_block后,会发送ChangeCipherSpec报文,通知服务器自己可以进行对称加密了。

然后,客户端以主密钥master_secret、finshedlabel(一个特定的字符串)和之前握手阶段的所有报文数据(不包含ChangeCipherSpec)为参数生成一个hash值为verify_data,然后对verify_data用生成的密钥进行对称加密放在finished报文发给服务器。

服务器在收到客户端发出的ClientKeyExchange报文后,用自己的私钥进行解密。拿到预主密钥pre_master_secret,用预主密钥pre_master_secret、两个随机数的和、字符串"master secret"为参数生成hash值为主密钥master_secret,再用master_secret、两个随机数的和、"key expansion"为参数生成hash值为最终的密钥key_block。

当服务器端也生成密钥后会发送ChangeCipherSpec告知客户端自己可以进行对称加密了。

然后服务器在收到客户端发出的finished报文后,用自己生成的密钥key_block解密。解密后拿到verify_data,进行验证。验证的方式是服务器自己按照相同的方式生成一个hash值与verify_data进行比较。如过相同,则证明之前的握手报文是完整的,没有被篡改过。

服务器用自己的主密钥master_secret、finishedlabel(一个特定的字符串)和之前握手数据报文(不包含ChangeCipherSpec)生成一个hash值verify_data,把verify_data用服务器生成的密钥key_block进行加密,在finished报文发给客户端。

客户端在收到服务器端发的finishe报文解密后校验verify_data来验证握手阶段的完整性。

注意:

      因为在生成密钥过程中参数都是相同的,所以最后生成的hash值密钥key_block也是相同的。

  

猜你喜欢

转载自www.cnblogs.com/zsheng/p/9252764.html