HTTPS 让数据传输更安全
http 存在的安全问题
在 http
将数据提交给 tcp
层之后,数据会经过用户电脑、 wifi
路由、运营商和目标服务器,在这中间的每个环节中,数据都有可能被窃取或篡改。比如用户电脑被黑客安装了恶意软件,能够抓取和篡改发出的 http
请求的内容。或者用户不小心连上钓鱼 wifi
,那数据也可能被盗取监听。
在 http 协议栈中引入安全层
鉴于 http
的明文传输使得传输过程毫无安全性可言,制约了网上购物、在线转账等场景,于是引入 加密方案 。
从 http
协议栈来看,在 tcp
和 http
之间插入一个 安全层,所有经过安全层的数据都会被 加密 或 解密 :
https
并非一个新的协议,安全层的主要职责是: 对发起 http
请求的数据进行加密,对接收到的 http
内容进行解密。
那如何实现一个从简单到复杂的 https
协议。
第一版 使用对称加密
对称加密: 加密 和 解密 都使用的是 相同 的 密钥。
要在 服务器 和 浏览器 分别加密同一个文件,至少双方都要知道 解密方式 和 密钥,因此在 https
发送数据之前,服务器 和 浏览器 之间需要协商 加密方式 和 密钥,协商过程如下:
简易流程描述如下:
- 浏览器 发送它所支持的 加密套件列表 和 一个随机数
client-random
,这里的 加密套件 是指 加密的方法(如AES
),加密套件列表是指浏览器能支持多少中加密方法列表; - 服务器 会从加密套件列表中选取一个加密套件,然后生成一个随机数
service-random
,并将service-random
和 加密套件列表 返回给浏览器; - 最后浏览器和服务器分别返回确认消息。
浏览器 和 服务器 分别都有相同的 client-random
和 service-random
了,然后它们再使用相同的方法将两个随机数混合起来生成一个密钥 master-secret
, 有了 密钥 master-secret
和 加密套件 之后,双方就可以进行数据的机密传输了。
对称加密应用于安全层上就实现了第一个版本的 https
的加密方法,但是其中传输 client-random
和 service-random
的过程却是明文的,这意味着黑客也可以拿到协商的 加密套件 和 双方的随机数,由于利用随机数合成密钥的算法是 公开 的,所以黑客拿到随机数之后,也可以合成密钥,这样数据依然可以被破解,那么黑客也就可以使用密钥来伪造或篡改数据了。
第二版 非对称加密
和 对称加密 只有一个密钥不同,非对称加密算法 有 A、B 两把密钥,它们的加解密关系如下:
- 用 A 密钥来加密的数据,只能使用 B 密钥来解密;
- 用 B 密钥来加密的数据,只能使用 A 密钥来解密。
在 https
中,服务器会将其中的一个密钥通过明文的形式 发送 给 浏览器,即 公钥,服务器自己留下的密钥为 私钥。公钥 每个人都能从获取到,但 私钥 只有服务器知道,不对任何人公开。
简易流程描述如下:
- 浏览器 发送 加密套件列表 给 服务器;
- 服务器 选择一个 加密套件(如
RSA
),不过和 对称加密 不同的是,使用 非对称加密 时,服务器上需要有用于浏览器加密的 公钥 和 服务器 解密http
数据的 私钥,由于 公钥 是给浏览器使用的,因此 服务器会将 加密套件 和 公钥 一起发送给浏览器; - 最后就是 浏览器 和 服务器返回确认消息。
这样浏览器就有了公钥,服务器有私钥,双方通信就可以通过公钥、私钥来加密、解密。即使黑客截获了数据和公钥,也无法使用公钥来解密数据。
- 第一个是非对称加密效率太低。这会严重影响加解密数据的速度,进而影响用户打开页面的书速度;
- 第二个无法保证服务器发送给浏览器的数据安全。虽然浏览器端可以使用公钥来加密,但是服务器只能采用私钥来加密,私钥加密只有公钥能解密,但是黑客也是可以得到公钥的,这样就不能保证服务器端数据的安全了。
第三版 对称加密和非对称加密搭配使用
基于以上两点原因,最终选择一个更加完美的方案,那就是 在传输数据阶段依然采用 对称加密,但是 对称加密的密钥 采用 非对称加密 来传输。
简易描述流程如下:
- 浏览器 向 服务器 发送 对称加密套件列表、非对称加密套件列表 和 随机数
client-random
; - 服务器 保存随机数
client-random
,选择对称加密 和 非对称加密 的套件,然后生成 随机数service-random
, 向浏览器发送选择的 加密套件 、service-random
和 公钥; - 浏览器 保存 公钥,并利用
client-random
和service-random
计算出来pre-master
,然后利用 公钥 对pre-master
加密,并向服务器发送加密后的数据,并带上确认消息; - 最后服务器拿出自己的 私钥,解密出
pre-master
数据,并返回确认消息。
到此为止,服务器和浏览器就有了共同的 client-random
、service-random
和 pre-master
,然后服务器和浏览器会使用这三组随机数生成 对称密钥,因为服务器和浏览器使用同一套方法来生成密钥,所以最终生成的密钥也是相同的。
有了对称加密的密钥之后,双方就可以使用对称加密的方式来传输数据了。
需要特别注意的一点,pre-master
是经过 公钥加密 之后传输的,所以黑客无法获取到 pre-master
,这样黑客就无法生成 密钥,也就保证了黑客无法破解传输过程中的数据了
第四版 添加数字证书
通过对称和非对称混合方式,我们完美地实现了数据的加密传输。不过这种方式依然存在着问题,比如黑客通过 DNS
劫持将网站的 IP
地址替换成了黑客的 IP
地址,这样我访问的其实是黑客的服务器了,黑客就可以在自己的服务器上实现公钥和私钥,而对浏览器来说,它完全不知道现在访问的是个黑客的站点。
所以我们还需要服务器向浏览器提供证明“我就是我”,那怎么证明呢?
这里我们结合实际生活中的一个例子,比如你要买房子,首先你需要给房管局提交你买房的材料,包括银行流水、银行证明、身份证等,然后房管局工作人员在验证无误后,会发给你一本盖了章的房产证,房产证上包含了你的名字、身份证号、房产地址、实际面积、公摊面积等信息。
在这个例子中,你之所以能证明房子是你自己的,是因为引进了房管局这个权威机构,并通过这个权威机构给你颁发一个证书
对于浏览器来说,数字证书有两个作用:一个是通过数字证书向浏览器证明服务器的身份,另一个是数字证书里面包含了服务器公钥。
相比第三版 https 协议,主要改变两点:
- 服务器 没有直接返回公钥给 浏览器,而是返回了 数字证书,而公钥正是包含在 数字证书 中的;
- 在浏览器端 多了一个 证书验证 的操作,验证了证书之后,才继续后续流程。
通过引入数字证书,我们就实现了服务器的身份认证功能,这样即便黑客伪造了服务器,但是由于证书是没有办法伪造的,所以依然无法欺骗用户。
数字证书的申请和验证
在第四版的 HTTPS 中,我们提到过,有了数字证书,黑客就无法欺骗用户了,不过我们并没有解释清楚如何通过数字证书来证明用户身份,所以接下来我们再来把这个问题解释清楚。
如何申请数字证书
我们先来看看如何向 CA 申请证书。比如极客时间需要向某个 CA 去申请数字证书,通常的申请流程分以下几步:
- 首先极客时间需要准备一套私钥和公钥,私钥留着自己使用;
- 然后极客时间向 CA 机构提交公钥、公司、站点等信息并等待认证,这个认证过程可能是收费的;
- CA 通过线上、线下等多种渠道来验证极客时间所提供信息的真实性,如公司是否存在、企业是否合法、域名是否归属该企业等;
- 如信息审核通过,CA 会向极客时间签发认证的数字证书,包含了极客时间的公钥、组织信息、CA 的信息、有效时间、证书序列号等,这些信息都是明文的,同时包含一个 CA 生成的签名。
这样我们就完成了极客时间数字证书的申请过程。前面几步都很好理解,不过最后一步数字签名的过程还需要解释下:首先 CA 使用Hash 函数来计算极客时间提交的明文信息,并得出信息摘要;然后 CA 再使用它的私钥对信息摘要进行加密,加密后的密文就是 CA 颁给极客时间的数字签名。这就相当于房管局在房产证上盖的章,这个章是可以去验证的,同样我们也可以通过数字签名来验证是否是该 CA 颁发的。
浏览器如何验证数字证书
有了 CA 签名过的数字证书,当浏览器向极客时间服务器发出请求时,服务器会返回数字证书给浏览器。
浏览器接收到数字证书之后,会对数字证书进行验证。首先浏览器读取证书中相关的明文信息,采用 CA 签名时相同的 Hash 函数来计算并得到信息摘要 A;然后再利用对应 CA 的公钥解密签名数据,得到信息摘要 B;对比信息摘要 A 和信息摘要 B,如果一致,则可以确认证书是合法的,即证明了这个服务器是极客时间的;同时浏览器还会验证证书相关的域名信息、有效时间等信息。
这时候相当于验证了 CA 是谁,但是这个 CA 可能比较小众,浏览器不知道该不该信任它,然后浏览器会继续查找给这个 CA 颁发证书的 CA,再以同样的方式验证它上级 CA 的可靠性。通常情况下,操作系统中会内置信任的顶级 CA 的证书信息(包含公钥),如果这个 CA 链中没有找到浏览器内置的顶级的 CA,证书也会被判定非法。
另外,在申请和使用证书的过程中,还需要注意以下三点:
- 申请数字证书是不需要提供私钥的,要确保私钥永远只能由服务器掌握;
- 数字证书最核心的是 CA 使用它的私钥生成的数字签名;
- 内置 CA 对应的证书称为根证书,根证书是最权威的机构,它们自己为自己签名,我们把这称为自签名证书。