简单记录一下近日学习HTTPS、TLS等协议的收获和心得。
在介绍HTTPS之前,首先来说一下加密算法。加密算法有双向和单向之分,双向加(解)密算法指明文和密文可相互转化,单向加密算法则只能由明文转化为密文,无法逆向转化。下图是两种分类所主要用到的算法。
其中来着重介绍对称加密和非对称加密,以及二者的结合。
可以用一组公式来总结:
f1(k,data)=encrypted_dataf2(k,encrypted_data)=data其中f1,f2分别为加密,解密算法。k为密钥,data为明文数据,encrypted_data为加密数据。
流程:客户端和服务器共同协商出一个密钥和一个对称加密算法,后面传输数据时利用密钥和对称加密算法对数据进行加密,另一端收到后,利用解密算法得到原始明文数据。
非对称加密有公钥(public_key)和私钥(private_key),二者一一对应,在生成私钥的同时也生成对应公钥。
公式总结如下:
f(pub_key,data1)=encrypted_data1f(pri_key,encrypted_data1)=data1-------------------------------------f(pri_key,data2)=encrypted_data2f(pub_key,encrypted_data2)=data2其中pub_key,pri_key分别为公钥和私钥。通过公钥和私钥都可以给数据加密,且使用对应的私钥/公钥可对数据解密。
流程:客户端向服务器发出请求索要公钥,服务器返回公钥。客户端将数据通过公钥加密后发给服务器,服务器通过私钥进行解密;服务器通过私钥对数据加密后发给客户端,客户端利用公钥解密。
非对称加密的效率,对称加密的安全性是其二者的缺点,所以可以将二者结合,实现取长补短。
流程:客户端向服务器发出请求索要公钥,服务器返回公钥。客户端随机生成一个随机数num,num通过公钥加密后发送给服务器,服务器利用私钥解密,得到num。这时,客户端和服务器将num共同视为对称加密的密钥,后面传输的数据通过此密钥加/解密。
在接收到数据包时,会出现一个问题:如何确定此数据包是不是真正目的服务器所发出的(中间人攻击会冒充服务器,向客户端发送数据包、公钥)。这时就需要「数字签名」和「数字证书」技术来验证文件内容的一致性与服务器的身份(安全性更高的场景还需要验者客户端的身份)。数字签名算法主要有RSA(哈希算法+RSA加密算法),DSA,ECDSA。
TCP三次握手结束和服务器成功连接后,客户端就开始发起TLS连接,首先会进入**TLS握手阶段**。
TLS握手阶段目的:
TLS握手阶段一般流程(TLS握手的流程并不是一成不变的,根据实际的应用场景来,主要有三种):
TLS握手机制图解
在Wireshark软件中捕获了访问知乎网页数据包,追踪TCP流得到第一个TLS包
服务端下发证书,客户端验证服务端的身份,并且取出证书携带的公钥,这个公钥是交换加密算法的公钥。也就是在ServerHello阶段指定的ECDHE(ECDiffie-Hellman)算法,也是通常说的DH加密。
这个Certificate消息下发了从携带自己公钥的数字证书和CA证书的证书链,在Certificates字段中:
由字段信息可知,证书链中共有3个数字证书。分别为服务端(zhihu.com)证书->中间CA证书->根CA证书。首先看服务端证书
首先是signedCertificate字段的内容,即数字证书的数据
然后是证书颁发机构的签名信息:
密钥交换阶段,这个步骤是可选步骤,对Certificate阶段的补充,只有在这几个场景存在:
通知客户端,版本和加密套件协商结束。
这里,客户端不直接生成加密密钥,而是通过之前客户端和服务端生成的随机数又再生成一个随机数,使用前面协商好的用ECDiffie-Hellman算法进行加密传输给服务端。这个值又被称为“premastersecret“。
服务端收到这个报文后,会使用自己的私钥解开这个随机数。在这个阶段过后,服务端和客户端都有三个随机数:客户端随机数、服务端随机数和预备主密钥。在服务端收到了ClientKeyExchange消息后,两端都按照相应的算法生成了主密钥,加密密钥交换完成。交换完了,因为主密钥是两个端按照约定好的算法产生的,如何保证这个主密钥是正确的?这时候会进入下一个阶段。客户端和服务端会对握手信息使用SHA做个摘要,用AES加密算法和主密钥加密,传递给对方验证。这种方式也称为消息认证。就是下面的过程:
客户端通知服务端,后续的报文将会被加密。
这里就是客户端的ClientFinished消息。也是整个SSL过程中,发送给服务端的第一个加密消息。服务端接收后,服务端用同样的方式计算出已交互的握手消息的摘要,与用主密钥解密后的消息进行对比,一致的话,说明两端生成的主密钥一致,完成了密钥交换。
服务端通知客户端,后续的报文将会被加密。
这里就是服务端的ServerFinish消息。和上面的客户端的EncryptedHandshakeMessage一样,是服务端发出的第一条加密信息。客户端按照协商好的主密钥解密并验证正确后,SSL握手阶段完成。
应用数据传输消息。因为这里是HTTPS,所以可以对HTTP应用协议数据加密然后传输了。