在我理解下:HTTP + 加密 + 认证 + 完整性保护 = HTTPS
HTTP安全
首先我们要从HTTP的明文传输说起,起初设计HTTP的目的很单纯,就是为了传输协议,那时候一直保持着明文传输的特征。这样的话数据在传输过程中就有可能被窃取或者篡改。
从上面可以看出,我们使用HTTP传输的内容容易被中间人窃取,篡改和伪造。这就叫中间人攻击
具体来讲,在将 HTTP 数据提交给 TCP 层之后,数据会经过用户电脑、WiFi 路由器、运营商和目标服务器,在这中间的每个环节中,数据都有可能被窃取或篡改。比如用户电脑被黑客安装了恶意软件,那么恶意软件就能抓取和篡改所发出的 HTTP 请求的内容。或者用户一不小心连接上了 WiFi 钓鱼路由器,那么数据也都能被黑客抓取或篡改。
在HTTP协议栈中引入安全层
因为要保障传输安全,所以就要在加入加密方案。
从上面我们能看出,HTTPS不是一个新的协议,它的核心是引入了安全层。它不会影响到上面的HTTP协议,也不会影响到下面的TCP协议。
总的来说安全层的职责就是:对HTTP请求的数据进行加密操作和对接收到的HTTP内容进行解密
HTTP建立连接
当你在浏览器地址栏里键入“https”开头的 URI,再按下回车,会发生什么呢?浏览器首先要从 URI 里提取出协议名和域名。因为协议名是“https”,所以浏览器就知道了端口号是默认的 443,它再用 DNS 解析域名,得到目标的 IP 地址,然后就可以使用三次握手与网站建立 TCP 连接了。在 HTTP 协议里,建立连接后,浏览器会立即发送请求报文。但现在是 HTTPS 协议,它需要再用另外一个“握手”过程,在 TCP 上建立安全连接,之后才是收发 HTTP 报文。这个“握手”过程与 TCP 有些类似,是 HTTPS 和 TLS 协议里最重要、最核心的部分,懂了它,你就可以自豪地说自己“掌握了 HTTPS”。
HTTPS握手工作原理
关于随机数和公钥私钥,我真的看了好久,终于找到了好理解的:
最关键的总结:非对称加密生成密钥,然后再用密钥进行对称加密
详细一点
先上一张详细的图:
- 在TCP建立连接后,浏览器会先跟服务器打招呼Client Hello。里面有客户端版本号,支持的密码套件,还有一个随机数(client random) ,用于后续生成会话密钥。
- 服务器接收到招呼以后,会回应招呼,把版本号对一下,也给出一个随机数(server random) ,然后从客户端给出的密码套件列表里面选出一个套件。
- 随后为了证明自己的身份,就把证书也发给了浏览器。
- 然后服务器发送Server Hello Done通知客户端第一次握手协商结束(两个 TCP 包)。
- 第一次握手结束后,客户端会对发过来的证书进行验证,如果验证成功,解密取出证书的公钥。
- 然后服务器和浏览器现在都拥有了client random,server random,加密套件,然后两者把client random和server random丢进服务器选择的加密套件里面计算得出pre-master(也是随机的,置于为什么后面会讲),然后使用公钥加密pre-master
- 随后浏览器把使用公钥加密的pre-master发送给服务器。
- 现在客户端和服务器手里有了三个随机数:Client Random、Server Random 和 Pre-Master。用这三个作为原始材料,就可以生成用于加密会话的主密钥(session key),叫“Master Secret”。而黑客因为拿不到“Pre-Master”,所以也就得不到主密钥。
- 有了主密钥和派生的会话密钥,握手就快结束了。客户端发一个“Change Cipher Spec”,然后再发一个“Finished”消息,把之前所有发送的数据做个摘要,再加密一下,让服务器做个验证。
- 意思就是告诉服务器:“后面都改用对称算法加密通信了啊,用的就是打招呼时说的 AES,加密对不对还得你测一下。”服务器也是同样的操作,发“Change Cipher Spec”和“Finished”消息,双方都验证加密解密 OK,握手正式结束,后面就收发被加密的 HTTP 请求和响应了。
session的恢复(与session 的联系)
握手阶段来建立SSL连接,如果由于某种原因断开,就需要重新握手。
有两种方法可以恢复原来会话用的session key。一种是session id,一种是session ticket
session ID的思想很简单,就是每一次对话都有一个编号(session ID)。如果对话中断,下次重连的时候,只要客户端给出这个编号,且服务器有这个编号的记录,双方就可以重新使用已有的"对话密钥",而不必重新生成一把。
上图中,客户端给出session ID,服务器确认该编号存在,双方就不再进行握手阶段剩余的步骤,而直接用已有的对话密钥进行加密通信。session ID是目前所有浏览器都支持的方法,但是它的缺点在于session ID往往只保留在一台服务器上。所以,如果客户端的请求发到另一台服务器,就无法恢复对话。session ticket就是为了解决这个问题而诞生的,目前只有Firefox和Chrome浏览器支持。
上图中,客户端不再发送session ID,而是发送一个服务器在上一次对话中发送过来的session ticket。这个session ticket是加密的,只有服务器才能解密,其中包括本次对话的主要信息,比如对话密钥和加密方法。当服务器收到session ticket以后,解密后就不必重新生成对话密钥了。
疑问
1. 再讲下套件,随机数的作用
服务端和浏览器当其解密获得了Pre-master secret之后,会结合原来的A、B随机数,用DH算法计算出一个master secret,紧接着根据这个master secret推导出hash secret和session secret。这两个东西有什么用后面会讲。
由于在客户端和服务端的master secret是依据三个随机数推导出来的,它是不会在网络上传输的,只有双方知道,不会有第三者知道。同时,客户端推导出来的session secret和hash secret与服务端也是完全一样的。
2. 为什么是三个随机数
这就必须说 TLS 的设计者考虑得非常周到了,他们不信任客户端或服务器伪随机数的可靠性,为了保证真正的“完全随机”“不可预测”,把三个不可靠的随机数混合起来,那么“随机”的程度就非常高了,足够让黑客难以猜测。
3. 前面说到了HTTP + 加密 + 认证 + 完整性保护 = HTTPS,完整性保护在哪
双方使用对称加密算法进行加密,用hash secret对HTTP报文做一次运算生成一个MAC,附在HTTP报文的后面,然后用session-secret加密所有数据(HTTP+MAC),然后发送。
接收方则先用session-secret解密数据,然后得到HTTP+MAC,再用相同的算法计算出自己的MAC,如果两个MAC相等,证明数据没有被篡改。
MAC(Message Authentication Code)称为报文摘要,能够查知报文是否遭到篡改,从而保护报文的完整性。签名
这里看上去好像很抽象的样子。其实我们可以结合JWT(json web token)来看看它到底是怎么工作的。
jwt是什么就不用重复了,在其他文章可以找到。
jwt样子长这样:
里面依次存的数据是:
- header,头部,放着签名的算法,
- payload,负载,放着要传递的数据
- signature,签名,由负载里的数据经头部的算法加密生成,用于防止数据被篡改。
它是这样工作的:
加密过程:首先用头部里面的算法对要传递的数据进行加密做成签名然后附到报文后面,然后整体通过加密生成jwt密文。 解密过程:首先解密jwt密文,然后通过头部的算法加密传递的数据,看与签名是否相等来判断数据有没有被篡改。
看到这里,套上前面的hash secret和session-secret就好理解多了。
一定要用HTTPS吗?
不一定。
当HTTP加了一层SSL后,加入了很多验证机制。虽然安全性提升了但是处理速度会变慢。
协商时候的通信量和解密加密都需要时间。
而且要用HTTPS的话就要购买CA证书。
所以大部分网站使用了折中的方法,对于一些要隐藏的,私密的东西就使用j加密,而普通的信息不加密,以节省资源。
参考:
segmentfault.com/a/119000001… www.cnblogs.com/huansky/p/1… www.ruanyifeng.com/blog/2014/0… www.runoob.com/w3cnote/htt…