目前互联网大量web的应用层协议从http迁移到了https,https已经在越来越多的场合替换http协议。近期由于业务需要,我们通过Wireshark对https的请求进行了一次抓包分析,同时也了解了更多https相关知识,整理出来和大家一起学习。
到底什么是HTTPS呢?简单而言,HTTPS是使用TLS/SSL加密的HTTP协议。HTTP协议通过明文进行信息传输,存在信息窃听、信息篡改和身份冒充的风险,而协议TLS/SSL具有信息加密、完整性校验和身份验证的功能,可以避免此类问题。
TLS/SSL全称为:安全传输层协议(Transport Layer Security),是介于TCP和HTTP之间的一层安全协议,不影响原有的TCP协议和HTTP协议,所以使用HTTPS基本上不需要对HTTP页面进行太多的改造。
(注:大多数人将HTTPS和SSL(Secure Sockets Layer)联系起来,SSL是Netscape公司在90年代中期发明的。随着时间的推移这种说法就渐渐变得不准确了。由于Netscape失去了市场份额,它将SSL的维护工作移交给因特网工程任务组(IETF)。第一个后Netscape版本被重新命名为安全传输层协议(TLS),TLS1.0是在1999年1月份发布的。由于TLS诞生都10年了, 所以真正的“SSL”传输其实是几乎见不到.)
下面是我们抓包数据中的一次https请求的建立过程:
很明显,前3条消息对应的是TCP通信的三次握手的过程。(需要说明的是,根据RFC2818,一旦出现“https”就意味着TCP需要连接目标端的443号端口)
Client Hello
从这条消息开始,开始TLS协议的握手过程
我们可以在Client Hello消息中,看到两个Version信息,根据RFC5246它们分别是:第一处表示本次通信使用的TLS版本为1.0;第二处表示客户端期望使用的TLS版本为1.2。(注:版本协商,客户端会提供它能支持的最高的TLS版本,由服务端确认最终使用的TLS版本)
前面的四个字节是当前时间,它的格式是Unix时间戳。跟随其后是28字节的随机数,它将在后面过程中使用。
在这里它是空值或者是null。如果在几秒前连接过该服务,它就可能继续使用之前的会话,不需要重新执行整个“握手”过程。在我们的抓包内容中,由于是第一次连接,所以Session ID长度为0。
它是请求发送端所支持的密码算法的一个列表。这里看到请求发起方提供了22个可供选择的选项。关于CipherSuite的解释,我们在后面篇章会有更详细的介绍。
这个字段包含了我们请求要发往的服务器的域名信息,它作用有些类似HTTP协议header中的“Host”,这样就允许了Internet公司出于成本的考虑将上百个网站绑定在同一IP 地址上。
ServerHello
其中有服务端对Client Hello回应的一些关键信息:
同Client Hello类似,它返回了服务端的当前时间,以及服务端产生的一个28字节随机数
服务端确认通信使用的TLS版本:TLS1.2
服务端选择的通信使用的加密协议套件:
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
建立的会话标识ID,有了它,随后重连服务器就不需要再执行一个完整的握手过程了。
Certificate&Server Key Exchange&Server Hello Done
在同一条消息中包含了:服务端返回证书,交换公钥以及“Server Hello”结束三部分内容。客户端收到服务证书后,会先验证证书的合法性,如果验证通过才会进行后续通信。
Client Key Exchange&Change Cipher Spec、Encrypted Handshake Message(Finished)
这里三条客户端发送的消息:交换公钥,编码改变通知 和 握手结束消息。 ChangeCipher Spec 、Multipiple Handshake Messages(Finished)
这是TLS握手过程的最后一条消息,内容为:服务端编码改变通知 和 握手结束消息。至此,TLS通信的整个握手过程已经完成。
要注意,在Finished消息中包含两部分信息,finish标识和hash校验信息。但是无论客户端还是服务端,在Change Cipher Spec之后的内容都已经通过加密方式传输了,所以Finished中具体内容已经无法通过Wireshark直接查看。 TLS通信过程可以总结为:
在基本了解TLS的通信过程之后,我们再来了解一下CipherSuite的概念。每一个CipherSuite都是4个算法类型的组合:
显然,这4个算法是用于实现信息加密、完整性校验 和 身份验证的功能
从我们的抓包内容中可以看到:服务端最终选择的加密套件为:
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
对应到CipherSuite算法类型后:
CipherSuite算法类型 | 示例中对应算法 | 常见算法名称 |
---|---|---|
认证算法 | RSA | RSA(主流),DSA,ECDSA |
加密算法 | AES_256_GCM | AES128/256 bit,加密模式gcm/ cbc/ ecbRC4和3DES(不推荐),DES(已淘汰) |
MAC算法 | SHA384 | SHA256, SHA384, SHA1 |
密钥交换算法 | ECDHE | DHE,ECDHE |
(注:关于cipher suite中各算法的流行趋势,感兴趣的同学可以自行检索)
关于CipherSuite协商过程:https消息内容是通过CipherSuite来指定过程中使用的算法的服务端大多数情况下,会从客户端Cipher Suites中按排列顺序从上往下进行选择,因为排列靠前意味着安全性越高算法的选择会一定程度上影响https连接的性能,在某些场景下服务端可以综合考虑安全性和效率问题,选择更加合适的算法组合。
对称加密 和 非对称加密
对称密码编码技术,它的特点是文件加密和解密使用相同的密钥,即加密密钥也可以用作解密密钥,这种方法在密码学中叫做对称加密算法。相应的非对称加密算法中加密和解密使用两种不同的密钥,其中,公钥是公开的,私钥由个人持有,必须保密。
HTTPS 的通信过程中只在握手阶段使用了非对称加密,后面的通信过程均使用的对称加密。尽管非对称加密相比对称加密更加安全,但也存在两个明显缺点:
非对称密钥交换算法是整个 HTTPS 得以安全的基石,充分理解非对称密钥交换算法是理解 HTTPS 协议和功能的关键。下面我们选取其中常见的两种非对称算法进行介绍:
1977年,三位数学家Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字命名,叫做RSA算法。从那时直到现在,RSA算法一直是最广为使用的"非对称加密算法"。
公钥与密钥的产生
假设Alice想要通过一个不可靠的媒体接收Bob的一条私人讯息。她可以用以下的方式来产生一个公钥和一个私钥:
随意选择两个大的质数p和q,p不等于q,计算N=pq。
根据欧拉函数,求得r =φ(N)=φ(p)φ(q)= (p-1)(q-1)
选择一个小于 r 的整数 e,求得 e 关于模 r 的模反元素,命名为d。(模反元素存在,当且仅当e与r互质)
将 p 和 q 的记录销毁。
(N,e)是公钥,(N,d)是私钥。Alice将她的公钥(N,e)传给Bob,而将她的私钥(N,d)藏起来。
加密消息
假设Bob想给Alice送一个消息m,他知道Alice产生的N和e。他使用起先与Alice约好的格式将m转换为一个小于N,且与N互质的整数n,比如他可以将每一个字转换为这个字的Unicode码,然后将这些数字连在一起组成一个数字。假如他的信息非常长的话,他可以将这个信息分为几段,然后将每一段转换为n。用下面这个公式他可以将n加密为c: n^e ≡ c (mod N)
计算c并不复杂。Bob算出c后就可以将它传递给Alice。
解密消息
Alice得到Bob的消息c后就可以利用她的密钥d来解码。她可以用以下这个公式来将c转换为n:
c^d ≡ n (mod N)
得到n后,她可以将原来的信息m重新复原。
解码的原理是
c^d ≡ n^(e·d)(mod N)
已知e·d ≡ 1 (mod r),即e·d =1 +hφ(N)。由欧拉定理可得:
n ^(e·d) =n^ (1 +hφ(N))=n·((n^φ(N))^h)≡(n(1)^h)(modN) ≡ n (mod N)
签名消息
RSA也可以用来为一个消息署名。假如Alice想给Bob传递一个署名的消息的话,那么她可以为她的消息计算一个散列值(Message digest),然后用她的私钥加密这个散列值并将这个“署名”加在消息的后面。这个消息只有用她的公钥才能被解密。Bob获得这个消息后可以用Alice的公钥解密这个散列值,然后将这个数据与他自己为这个消息计算的散列值相比较。假如两者相符的话,那么他就可以知道发信人持有甲的密钥,以及这个消息在传播路径上没有被篡改过。
通过一次简单实践更好的了解RSA
1. 假设p = 2,q = 5(p,q都是素数即可),则N = pq = 10;
2. 得到:r = (p-1)(q-1) = (2-1)(5-1) = 4;
3. 根据模反元素公式,可以得出,e·d ≡ 1 (mod 4),即e·d = 4n+1 (n为正整数);
4. 假设n=5,则e·d = 21,且e、d为正整数,并且e与r互质,则e = 7,d = 3;
5. 获得公钥和密钥:公钥为(N, e) = (10, 7),密钥为(N, d) = (10, 3);
6. 假设要传输的数字为2,通过公钥加密后为:(2^7)(mod 10) = 8;
7. 通过密钥解密:(8^3)(mod 10) = 512(mod 10) = 2,即获得结果;
目前大部分 HTTPS 流量是使用 ECDHE进行密钥交换。
在介绍ECDHE之前,先来看一下ECDH,它其实是使用椭圆曲线加密技术(ECC)的 DH密钥交换(Diffie-Hellman)算法。DH密钥交换算法,可以让交换双方在不共享任何秘密的情况下协商出一个密钥。ECC则是建立在基于椭圆曲线的离散对数问题上的密码体制,在相同的密钥长度下,其安全性比RSA更高。
而ECDHE则是ECDH的Ephemeral version,它会为每次握手过程分配一个不同的DH key,从而提供前向安全性。实际上,在HTTP/2中允许使用的Cipher Suite必须采用具有前向安全性的密钥交换算法。
https实际就是在TCP层与http层之间加入了TLS/SSL来解决安全问题的。
在进行应用数据传输之前,TLS需要通过握手过程来协商安全通信所需的相关参数。
整个通信过程中主要用到散列、对称加密、非对称加密和证书等相关技术,来解决客户端与服务器数据传输中各种安全风险问题,从而达到保证整个通信过程的安全。
http://www.infoq.com/cn/articles/HTTPS-Connection-Jeff-Moser
https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/
https://tools.ietf.org/html/rfc5246
https://blog.helong.info/blog/2015/01/23/ssl_tls_ciphersuite_intro/