HTTP学习笔记06 - 安全的HTTP的好帮手


SSL协议背景

在互联网设计之初,设计者并没有太过于考虑安全方面的问题,因此,在网络上传输的数据都是明文的,也就意味着,任何一个恶意的攻击者都可以得到我们提交的任何数据,这会带来3类风险:

  1. 数据窃听(eavesdropping): 第三方可以获知信息内容
  2. 数据篡改(tampering): 第三方可以修改通信内容
  3. 身份冒充(pretending): 第三方可以冒充他人身份参与通信

SSL&TLS协议的出现正是为了解决这3类问题,希望可以达到:

  1. 所有信息都是加密传输,第三方无法窃听
  2. 具有校验机制,一旦被篡改,通信双方会立刻发现
  3. 具备身份证书,防止身份被冒充 从而实现在“不安全”的网络设备上做到安全的数据传输这一目的。 虽然现在SSL协议已经发展成为TLS协议,但是SSL这个名字相对认知度更高一些,所以在本文中会使用SSL来表示SSL/TLS协议。

SSL协议历史

互联网加密通信协议的历史,几乎与互联网一样长。

  • 1994年,NetScape公司设计并实现了SSL协议(Secure Sockets Layer)的1.0版本,但是并没有正式对外发布。
  • 1995年,NetScape公司发布了SSL协议2.0版本,并集成到自家的Netscape Navigator1.1中,但是很快被发现有严重的安全漏洞。
  • 1996年,SSL协议3.0版本正式发布,并得到大规模应用。虽然新版本协议延续了SSL协议这个名字,但是可以这么说:3.0和2.0是完全不同的协议。
  • 1999年,IETF发布SSL的升级版TLS协议1.0版本。(SSL协议的开发维护工作从NetScape迁移到IEFT这项工作从1996年就开始了,但是直到1999年IETF正式发布了TLS协议1.0版本,这项迁移工作才算是正式完成)
  • 2006年和2008年,TLS进行了2次升级,分别是TLS1.1和TLS1.2。
  • 2018年8月份,tls1.3正式发布。

TLS1.0通常在SSL握手流程中被标注的版本是SSL3.1, TLS1.1为SSL3.2, TLS1.2为SSL3.3。

基本的运行过程

SSL协议的基本思路是使用非对称加密算法来协商一个对称加密的密钥,之后数据通信使用对称加密来保证安全。这是由于非对称加密算法计算量非常大,但是可以相对好的解决密钥交换的问题。所以可以由双方协商一个对称加密的密钥,这样来实现既能提供高安全性,又能节省资源的目的。

SSL角色

SSL协议为通信双方建立了2个不同的角色:客户端和服务端。这2者之间有非常大的区别。客户端是加密通信的发起者;服务端接受并响应客户端的请求。在比较常见的SSL应用场景:Web服务中,用户的浏览器就是client端,而对应的网站地址就是server端了。

SSL握手流程

SSL通过握手流程在客户端和服务端之间协商会话参数并建立会话。

只验证服务端身份的SSL握手流程

从图中可以看到整个握手流程包括4次通信,具体的流程如下:

1. 客户端发起握手请求:
2. 客户端通过ClientHello消息将它支持的SSL版本、支持的密钥密钥套件、生成的随机数等信息发送给服务端。
3. 服务端响应客户端的握手请求:
  1. 服务端确认后续握手需要使用的SSL版本、加密套件、服务端生成的随机数通过ServerHello消息发送给SSL客户端。如果服务端允许客户端在以后的通信中重用本次会话,则服务端会为本次会话分配会话ID,并通过ServerHello消息发送给客户端。
  2. 服务端将携带自己公钥信息的数字证书通过Certificate消息发送给客户端。
  3. 可选。 如果服务端要验证客户端身份,会返回CertificateRequest消息,该消息会要求客户端返回自己的公钥证书,供服务端验证客户端身份是否合法。
  4. 服务端返回给客户端一个ServerHelloDone消息,通知客户端版本和加密套件协商结束,开始进行密钥交换。
4. 客户端验证服务端身份并进行后续握手流程,操作包括:
  1. 可选。如果服务端返回CertificateRequest消息,那么客户端会将自己的公钥证书通过Certificate消息发送给服务端,服务端会验证证书的有效性。
  2. 客户端验证服务器的证书合法后,利用证书中的公钥加密客户端随机生成的premaster secret,并通过ClientKeyExchange消息发送给服务端。
  3. 可选。如果服务端要求验证客户端身份,客户端在发送完自己的公钥证书之后,会计算已交互的握手信息、主密钥的Hash值,利用自己的私钥对其进行加密,并通过CertificateVerify消息发送给服务器。
  4. 客户端发送给服务端一个ChangeCipherSpec消息,通知服务端后续报文将采用协商好的密钥和加密套件进行加密和MAC计算。
  5. 客户端计算已交互的握手消息(除ChangeCipherSpec消息外所有已交互的消息)的Hash值,利用协商好的密钥和加密套件处理Hash值(计算并添加MAC值、加密等),并通过Finished消息发送给服务器。SSL服务器利用同样的方法计算已交互的握手消息的Hash值,并与Finished消息的解密结果比较,如果二者相同,且MAC值验证成功,则证明密钥和加密套件协商成功。
5. 服务端响应客户端请求,操作包括:
  1. 服务端返回给客户端一个ChangeCipherSpec消息,通知客户端后续报文将采用协商好的密钥和加密套件进行加密和MAC计算。
  2. SSL服务器计算已交互的握手消息、主密钥的Hash值,利用SSL客户端证书中的公钥解密CertificateVerify消息,并将解密结果与计算出的Hash值比较。如果二者相同,则SSL客户端身份验证成功。
  3. 服务端计算已交互的握手消息的Hash值,利用协商好的密钥和加密套件处理Hash值(计算并添加MAC值、加密等),并通过Finished消息发送给客户端。客户端利用同样的方法计算已交互的握手消息的Hash值,并与Finished消息的解密结果比较,如果二者相同,且MAC值验证成功,则证明密钥和加密套件协商成功。

所有的证书都是在Certificate消息中的,通信双方可以通过验证对方证书的有效性来判断对方是否是自己希望交互的目标。

总结

至此,SSL链接的握手已经成功,接下来,客户端与服务端进入加密通信,这些完全是使用普通的HTTP协议,只不过用“会话密钥”对传输的数据进行了加密。