今天在segmentfault上和某人探讨了一下这个https的握手流程,其实我一开始也不是很清楚,也没有好好去思考过,通过回答这个问题,对https有了更深的认识。
首先我搜索到的流程正规说法是:
用户浏览器将其SSL版本号、加密设置参数、与session有关的数据以及其它一些必要信息发送到服务器。
服务器将其SSL版本号、加密设置参数、与session有关的数据以及其它一些必要信息发送给浏览器,同时发给浏览器的还有服务器的证书。如果配置服务器的SSL需要验证用户身份,还要发出请求要求浏览器提供用户证书。
客户端检查服务器证书,如果检查失败,提示不能建立SSL连接。如果成功,那么继续。
客户端浏览器为本次会话生成pre-master secret,并将其用服务器公钥加密后发送给服务器。
如果服务器要求鉴别客户身份,客户端还要再对另外一些数据签名后并将其与客户端证书一起发送给服务器。
如果服务器要求鉴别客户身份,则检查签署客户证书的CA是否可信。如果不在信任列表中,结束本次会话。如果检查通过,服务器用自己的私钥解密收到的pre-master secret,并用它通过某些算法生成本次会话的master secret。
客户端与服务器均使用此master secret生成本次会话的会话密钥(对称密钥)。在双方SSL握手结束后传递任何消息均使用此会话密钥。这样做的主要原因是对称加密比非对称加密的运算量低一个数量级以上,能够显著提高双方会话时的运算速度。
客户端通知服务器此后发送的消息都使用这个会话密钥进行加密。并通知服务器客户端已经完成本次SSL握手。
服务器通知客户端此后发送的消息都使用这个会话密钥进行加密。并通知客户端服务器已经完成本次SSL握手。
本次握手过程结束,会话已经建立。双方使用同一个会话密钥分别对发送以及接受的信息进行加、解密。
我理解的简化说法是:
c端请求,s端响应并提供证书;
c端检查接收后生成pre-master-securet使用s端发过来的公钥加密;
s端接收到后使用私钥解密,并最终通过某种算法生成master-securet;
后续的通信中s和c端均使用这个master-securet生成的密钥。
其中,提问者有一个疑问,为什么要有2个master-securet. 对此,最后我们得出的结论是
握手过程中服务器生成私钥和公钥,将公钥发给客户端,所以握手过程中为非对称加密。
最终使用master-securet生成密钥,使用对称加密通信。
前面使用非对称,后面使用对称加密,是因为对称加密效率高。
由于不信任机器生成的随机数,所以需要客户端生成pre-master-securet,然后再由服务端加密,最后得到master-securet,减少被猜中的可能。