SSL(Secure Sockets Layer,安全套接层)协议最初是网景公司为了保障网上交易安全而开发的,SSL协议在直接位于TCP上一层的应用层被实现。SSL不会影响上层协议(HTTP),但能够保证上层协议的网络通信安全。
IETF后来在标准化SSL协议时,将其改名为TLS(Transport Layer Security,传输层安全)。TLS1.0和SSL3.0版本的区别并不大。
TLS协议的目标是为在它之上运行的应用提供三个基本服务:加密、身份验证和数据完整性。从技术角度讲,并不是所有情况下都需要同时使用这三个服务。
这三种机制为Web通信构建了一个安全的环境。所有现代Web浏览器都支持多种加密套件,能够验证客户端和服务器,并能对每条记录进行消息完整性检查。
客户端与服务器在通过TLS交换数据之前,必须协商建立加密信道。协商内容包括TLS版本、加密套件,必要时还会验证证书。然而,协商过程的每一步都需要一个分组在客户端和服务器之间往返一次,因而所有TLS连接启动时都要经历一定的延迟。
公钥加密只在建立TLS信道的回话中使用。再次期间,服务器向客户端提供它的公钥,客户端生成对称密钥并使用服务器的公钥对其进行加密,然后再将加密之后的对称密钥返回服务器。服务器继而用自己的私钥解密出客户端发来的对称密钥。
接下来,客户端和服务器之间的通信就会全部使用客户端生成的共享密钥加密,这就是对称加密。之所以这样设计,很大程度是处于性能考虑,因为公钥加密需要很大的计算量。
协商建立TLS安全信道是一个复杂的过程,很容易出错,好在服务器和浏览器会替我们做这些工作。总之,尽管我们的Web应用不一定参与上述过程,但最重要的是知道每一个TLS连接在TCP握手基础上最多还需要两次额外的往返。这些都会增加实际交换数据之前的等待时间。
完整的TLS握手会带来额外的延迟和计算量,从而给所有依赖安全通信的应用造成严重的性能损失。为了挽回某些损失,TLS提供了恢复功能,即在多个连接间共享协商后的安全密钥。
最早的会话标识符是在SSL2.0中引入的,支持服务器创建32位的会话标识符。在内部,服务器会为每个客户端保存一个会话ID和协商后的会话参数。相应地,客户端也可以保存会话ID,并将该ID包含在后续会话消息中,从而告诉服务器自己还记着上次握手协商后的加密套件和密钥,这些都可以重用。
借用会话标识符可以节省一次往返,还可以节省掉用于协商共享密钥的公钥加密计算。由于重用了之前协商过的会话数据,就可以迅速建立一个加密连接,而且同样安全。
由于服务器必须为每个客户端都创建和维护一端会话缓存,特别是用户量很大的情况下,问题就变得复杂起来,因此需要一套会话ID缓存和清除策略。
为了解决上述服务器端TLS会话缓存的问题,会话记录单机制应运而生,该机制不用服务器保存每个客户端的会话状态。相反,如果客户端表明其支持会话记录单,则服务器可以在完整TLS握手的最后一次交换数据中添加一条新会话记录单记录,包含只有服务器知道的安全密钥加密过得所有会话数据。
然后客户端将这个会话记录单保存起来,在后续会话的消息中,可以将其包含在内。这样,所有会话数据只保存在客户端,而由于数据被加密过,且密钥只有服务器知道,因此仍然是安全的。
身份验证是建立每个TLS连接必不可少的部分。毕竟,加密信道两端可以是任何机器,包括攻击者的机器。下面我以张三和李四之间的验证为例:
信任是上述交流的关键。公钥加密可以让我们使用发送端的公钥验证消息是否使用了正确的私钥签名,但认可发送端仍然是基于信任。在上述交流中,张三和李四可以当面交换自己的密钥,因为他们互相认识,能够保证不被冒名顶替。可以说,他们已经通过之前安全的握手确认了对方。
接下来,张三收到王五发来的一条消息。张三从未见过王五,但王五自称是李四的朋友。事实上,王五为了证明自己是李四的朋友,王五还请李四用李四的私钥签署了自己的公钥,并在消息中附上了签名。此时,张三首先检查王五公钥中李四的签名。他知道李四的私钥,因而可以验证李四确实签署了王五的公钥。由于他信任李四对王五的签名,所以就接收了王五的消息,并对消息进行完整性检查,以确保消息确实来自王五。
刚才这个过程建立了一个信任链:张三信任李四,李四信任王五,通过信任的传递,张三信任王五。只要这条链上的人不会被冒名顶替,我们就可以继续扩展这个信任网络。在Web应用中如何信任?信任谁?
有时候,出于种种原因,证书颁发者需要撤销或作废证书,比如证书的私钥不再安全、证书颁发机构本身被冒名顶替,或者其他各种正常的原因,像以旧换新更替等。为此,证书本身会包含如何检测其是否过期的指令。为确保信任链不被破坏,通信的任何一端都可以根据嵌入的指令和签名检查信任链中每个证书的状态。
CRL(Certificate Revocation List,证书撤销名单)是RFC 5280规定的一种检查所有证书状态的简单机制:每个证书颁发机构维护并定期发布已撤销证书的序列号名单。这样任何想验证证书的人都可以下载撤销名单,检查相应证书是否榜上有名。 CRL也会有一些问题:
为了解决CRL的问题,RFC 2560定义了OCSP(Online Certificate Status Protocol,在线证书状态协议),提供了一种实时检查证书状态的机制。与CRL包含被撤销证书的序列号不同,OCSP支持验证端直接查询证书数据库中的序列号,从而验证证书是否有效。
与位于其下的IP或TCP没有什么不同,TLS会话中交换的所有数据同样使用规格明确的协议进行分帧。TLS记录协议负责识别不同的消息类型(握手、警告或数据,通过“内容类型”字段),以及每条消息的安全和完整性验证。
交付应用程序数据的典型流程如下:
以上几步完成后,加密数据就会被交给TCP传输。接收端的流程相同,顺序相反:使用商定的加密套件解密、验证MAC、提取并把数据转交给上层的应用。
鉴于网络协议的分层结构,在TLS之上运行应用与直接通过TCP通信没有什么不同。正因为如此,只需要对应用进行很少改动甚至不需要改动就可以支持TLS通信。