SSL研究报告

什么是SSL

SSL是SecureSocketLayer的缩写,即安全套接层协议。是由网景(Netscape)公司推出的一种安全通信协议,它能够对信用卡和个人信息提供较强的保护。SSL是对计算机之间整个会话进行加密的协议。

SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(TransportLayer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密。

SSL协议执行过程

第一阶段,客户端向服务器发出SSL连接请求,并附上一段随机产生的信息,服务器端在通讯之前会向证书颁发组织申请并获得自己的公钥、私钥以及证书。

第二阶段,服务器收到客户端的连接请求后,把收到的随机信息用私钥加密,然后连同公钥和身份信息发回给客户端。

第三阶段,客户端收到服务器端的回应后,将先用从服务器端发来的公钥解密信息,还原后与自己之前产生的随机信息比较异同,从而验证服务器端的身份。在服务器端身份得到验证后,客户端将产生一个对称密钥,用于加密真正的传输信息,并将该对称密钥用公钥加密后发给服务器端。

第四阶段,服务器端得到信息后,用自己私钥解密并获得该对称密钥,之后客户端和服务器之间就可以用这个对称密钥进行加密通讯了。

什么是 SSL 证书?如何检查网站是否部署了 SSL 证书?

什么是 SSL 证书? SSL 证书就是遵守 SSL 安全套接层协议的服务器数字证书。

如果您能使用 https:// 来访问某个网站,就表示此网站是部署了 SSL 证书。一般来讲,如果此网站部署了 SSL 证书,则在需要加密的页面会自动从 http:// 变为 https:// ,如果没有变,你认为此页面应该加密,您也可以尝试直接手动在浏览器地址栏的 http 后面加上一个英文字母“ s ”后回车,如果能正常访问并出现安全锁,则表明此网站实际上是部署了 SSL 证书,只是此页面没有做 https:// 链接;如果不能访问,则表明此网站没有部署  SSL 证书。

它是在传输通信协议 (TCP/IP) 上实现的一种安全协议,采用公开密钥技术,它为 TCP/IP 连接提供数据加密、服务器认证、消息完整性以及可选的客户机认证。

技术实现细节

Client 处理和回应 ServerHello 阶段

收到 ServerHello

在 server hello 阶段连续的发了多个消息,最先发出的是 server hello , client 收到后将 SSL 会话 ID ,服务器端的一个随机数,协商出的 SSL 协议版本号以及密钥套件放到会话缓存中。

收到 ServerCertificates

接下来收到的应该是 server 端的证书消息了,取出所有的消息,最头上的是 server 证书,最末端的 CA 根证书。在 SUN JDK JSSE 中实现的 SSL 是这样处理的:

从 SSLContex 中取出 trust manager ,如果用过 java SSL 编程的同学应该知道,可以自己实现 X509TrustManager 和 X509KeyManager 两个接口来定制对证书的验证, sun jdk 中就是调用这个 trust manager 的验证方法来验证证书(在解决浏览器检测到证书是自签名的时候跳出警告框的问题就是可以自己实现这个 trust manager 来让浏览器不跳出警告框)。

JDK 当然也有默认的证书验证实现,就是验证签名有效性,验证证书是否过期等。证书签名的有效性验证是在取证书链中某证书中的公钥验证前一个证书的签名,这样第一个证书就是用第二个证书的公钥来验证,那有人可能会问最后的根 CA 的证书谁来验证?根 CA 的证书是自签名的,就是自己给自己签名,没人管的了, JDK 中某个文件中有存储一堆可信任的证书发行机构的证书列表,如果你的根 CA 在那个列表中并对比后确实是那个根 CA 的证书那就 OK ,验证通过,这个可信任的机构也可以自己实现那个 trust manager 来添加设置。

收到 Server KeyExchange 消息

RSA 方式密钥交换消息则把消息中的加密用公钥放入会话缓存中,作为客户端这边握手阶段的写密钥而不是用服务器证书中的公钥。

DH 方式的消息就把消息中的 p,g,Ys 三个参数记录下来,有这些client 端就可以计算出 pre-master 了,只要回头再把自己这边的Yc 参数发过去, server 端就也能计算出相同的 pre-maseter 了。

收到 serverCerttificats Request 消息

将消息中的证书类型列表和可信任证书发行机构列表保存下来,可在后面发送客户端证书时候拿来筛选证书用。

收到 ServerHello Done 消息

收到这个消息后 client 端开始向 server 发消息了

发送 ClientCertificates 消息

如果是 server 端要求客户端认证就会发这个消息,否则不发。客户端可能会有多个证书,在 JSSE 里头多个客户端证书存储在 keystore 里头,选哪个发过去呢?这时候要用到 server 端之前发的 cert request 消息中的支持的证书类型列表和信任的根 CA 列表,满足这个两个条件的第一个证书链就会被选中作为客户端证书。

发送 Client KeyExchange 消息

若是 RSA 方式密钥交换,则产生一个 48 位随机数作为 pre-master 并用服务器公钥加密后发出去

若是 DH 方式的密钥交换,则根据 sever 的 g,p,Ys ,产生 Xa 和 Yc , Xa 和 Ys 能计算出 pre-master ,把产生的 Yc 放入消息中发给 server ,这样 server 用它的 Xb 和 Yc 也能计算出 pre-master 了。计算出预主密码后就顺便把主密码 (master secret) 给算出来了。算出主密码就把对称密钥产生出来了。

发送Certificate verify 消息

这个消息是可选的,只有在客户端发送了自己证书到服务器端,这个消息才需要发送。发这个消息的目的是让服务器验证发消息的客户端和客户端证书的真实所有者。这个消息中要包含一个签名,签名里头内容就是从 client hello 开始到目前为止所有握手消息(不包括本消息)的摘要,主密码,若是 RSA 方式则要把这些内容分别用 MD5 和 SHA1 计算一遍,两种摘要算法算得的摘要拼接起来用客户端证书中公钥对应的私钥加密就获得了签名。到时候服务器端会用收到的证书中的公钥来验证签名。

发送 changecipher spec 消息

发送这个消息,然后把 session 的写密钥设置成计算得到得对称密钥,从此消息之后再发送消息就会用这个写密钥来加密消息。

发送 clientFinished 消息

Client 端的 Finished 消息一般都是紧随change cipher spec 消息发送出去,标志着本方的 SSL 协商成功结束。消息中包含两个个摘要,是分别用 MD5 和 SHA 算法计算当前收到所有握手消息和主密码的摘要,不包括本消息和 change cipher spec( 因为不属于握手消息 ) 。

该消息是SSL握手中的最后要互传的消息,包含一个所有握手消息的摘要值,这是为了防止中间人将强度较大的CipherSuite在client hello消息中删除,使得server不得不选择强度较小的CipherSuite,然而这非client所愿。问题是这个摘要不可以被中间人更改吗?想象一下这时共享对称密钥已经协商好了,ChangeCipherSpec已经经过,所以这些消息本身是加过密的。

Server 处理和回应 cleintFinished 阶段

Server 收到 client 的证书链后验证证书,并验证certificatie verify 中的签名,验证通过了也就确认了 client 的身份,如假包换。收到 client key exchange 消息从中拿出 Pre-master 计算出 master ,生成对称密钥。收到 client 的 change cert spec 后将会话的读密钥设置为刚产生的对称密钥。

处理完这些 server 会发送自己的 change cipher spec 消息并把会话的写密钥设置为生成的对称密钥,最后发送 server Finished 消息, client 端收到 server 端的 change cipher spec 消息将会话的读密钥设置为生成的对称密钥。到此握手过程圆满结束,接下来的应用消息将使用设置好的读写密钥对数据加解密。

相关推荐