今天我们来一起学习一下 HTTPS 。
首先问你一个问题,为什么有了 HTTP
之后,还需要有 HTTPS
?
一个新技术的出现必定是为了解决某种问题的,那么 HTTPS
解决了 HTTP
的什么问题呢?
简单来说,HTTP 请求是遵循 HTTP 协议的一系列文本行。GET 请求可能如下所示:
GET /hello.txt HTTP/1.1
User-Agent: curl/7.63.0 libcurl/7.63.0 OpenSSL/1.1.l zlib/1.2.11
Host: www.example.com
Accept-Language: en
用户浏览器生成的这部分文本将通过 Internet
发送。而问题在于,它是明文形式发送的,监视连接的任何人都能读取它。(不熟悉 HTTP 协议的人可能觉得此文本难以理解,但任何对协议的命令和语法有基本了解的人都能轻松读懂。)
当用户通过网站或 Web 应用程序提交敏感数据时,这尤其是一个问题。敏感数据可能是密码、信用卡号,或在表单中输入的任何其他数据。而且在 HTTP
中,所有这些数据都以明文形式发送,任何人都能读取。(当用户提交表单时,浏览器会将其转换为 HTTP POST 请求,而不是 HTTP GET请求。)
源站服务器收到 HTTP 请求时,将发送 HTTP 响应,其类似于:
HTTP/1.1 200 OK
Date: Wed, 30 Jan 2019 12:14:39 GMT
Server: Apache
Last-Modified: Mon, 28 Jan 2019 11:17:01 GMT
Accept-Ranges: bytes
Content-Length: 12
Vary: Accept-Encoding
Content-Type: text/plain
Hello World!
如果网站使用 HTTP
而非 HTTPS
,则监视会话的任何人都可以读取所有请求和响应。本质上,恶意行为者可以只读取请求或响应中的文本,就能知道某人正在索取、发送或接收的确切信息。
总结一下 HTTP
的问题:
没有用户验证
;不会验证报文的完整性
。综上,为了解决上述问题,HTTPS 应用而生。
HTTPS 中的 S 代表“安全”。HTTPS 使用 TLS(或 SSL)来加密 HTTP 请求和响应,因此在上例中,攻击者看到的不是其文本,而是一堆看似随机的字符。
攻击者不会看到:
GET /hello.txt HTTP/1.1
User-Agent: curl/7.63.0 libcurl/7.63.0 OpenSSL/1.1.l zlib/1.2.11
Host: www.example.com
Accept-Language: en
而会看到类似如下:
t8Fw6T8UV81pQfyhDkhebbz7+oiwldr1j2gHBB3L3RFTRsQCpaSnSBZ78Vme+DpDVJPvZdZUZHpzbbcqmSW1+3xXGsERHg9YDmpYk0VVDiRvw1H5miNieJeJ/FNUjgH0BmVRWII6+T4MnDwmCMZUI/orxP3HGwYCSIvyzS3MpmmSe4iaWKCOHQ==
HTTPS 是 HTTP 协议的一种扩展,它本身并不保传输的证安全性,那么谁来保证安全性呢?在 HTTPS 中,使用传输层安全性(TLS)
或安全套接字层(SSL)
对通信协议进行加密。也就是 HTTP + SSL(TLS) = HTTPS。
HTTPS 协议提供了三个关键的指标
加密(Encryption)
, HTTPS 通过对数据加密来使其免受窃听者对数据的监听,这就意味着当用户在浏览网站时,没有人能够监听他和网站之间的信息交换,或者跟踪用户的活动,访问记录等,从而窃取用户信息。数据一致性(Data integrity)
,数据在传输的过程中不会被窃听者所修改,用户发送的数据会完整
的传输到服务端,保证用户发的是什么,服务器接收的就是什么。身份认证(Authentication)
,是指确认对方的真实身份,也就是证明你是你
(可以比作人脸识别),它可以防止中间人攻击并建立用户信任。有了上面三个关键指标的保证,用户就可以和服务器进行安全的交换信息了。在Chrome中,我们可以直接通过网址左侧的提示,识别网站是用 HTTPS 的还是 HTTP 的:
HTTPS 协议其实非常简单,RFC 文档很小,只有短短的 7 页,里面规定了新的协议名,默认端口号443
,至于其他的应答模式、报文结构、请求方法、URI、头字段、连接管理等等都完全沿用 HTTP,没有任何新的东西。
也就是说,除了协议名称和默认端口号外(HTTP 默认端口 80),HTTPS 协议在语法、语义上和 HTTP 一样,HTTP 有的,HTTPS 也照单全收。那么,HTTPS 如何做到 HTTP 所不能做到的安全性呢
?关键在于这个 S
也就是 SSL/TLS
。
SSL(Secure Socket Layer
,安全套接字层):1994年为 Netscape
所研发,SSL 协议位于 TCP/IP
协议与各种应用层协议之间,为数据通讯提供安全支持。
SSL 在 1999 年被 IETF(互联网工程组)
更名为 TLS
,即传输安全层
。
TLS(Transport Layer Security
,传输层安全):其前身是 SSL,它最初的几个版本(SSL 1.0
、SSL 2.0
、SSL 3.0
)由网景公司开发,1999年从 3.1 开始被 IETF
标准化并改名,发展至今已经有 TLS 1.0
、TLS 1.1
、TLS 1.2
三个版本。SSL3.0
和TLS1.0
由于存在安全漏洞,已经很少被使用到。TLS 1.3
的改动比较大,2014年开始草案,2018年才正式发布。目前使用最广泛的是TLS 1.1
、TLS 1.2
。
所以说TLS(Transport Layer Security)
是 SSL(Secure Socket Layer)
的后续版本,它们是用于在互联网两台计算机之间用于身份验证
和加密
的一种协议。
HTTPS 并不是一项新的应用层协议,只是 HTTP 通信接口部分由 SSL 和 TLS 替代而已。
通常情况下,HTTP 会先直接和 TCP 进行通信。在使用 SSL 的 HTTPS 后,则会先演变为和 SSL 进行通信,然后再由 SSL 和 TCP 进行通信。也就是说,HTTPS 就是身披了一层 SSL 的 HTTP。
HTTPS 协议的主要功能基本都依赖于 TLS/SSL
协议,TLS/SSL
的功能实现主要依赖于三类基本算法:对称加密、非对称加密和摘要算法:
这种方式加密和解密同用一个密钥。加密和解密都会用到密钥。
没有密钥就无法对密码解密,反过来说,任何人只要持有密钥就能解密了。
以对称加密方式加密时必须将密钥也发给对方。可究竟怎样才能安全地转交?在互联网上转发密钥时,如果通信被监听那么密钥就可会落人攻击者之手,同时也就失去了加密的意义。另外还得设法安全地保管接收到的密钥。
非对称加密(Asymmetrical Encryption)
也被称为公钥加密
,相对于对称加密来说,非对称加密是一种新的改良加密方式。
公开密钥加密使用一对非对称的密钥:一把叫做私有密钥,另一把叫做公开密钥。
使用公开密钥加密方式,发送密文的一方使用对方的公开密钥进行加密处理,对方收到被加密的信息后,再使用自己的私有密钥进行解密。利用这种方式,不需要发送用来解密的私有密钥,也不必担心密钥被攻击者窃听而盗走。
顾名思义,私有密钥不能让其他任何人知道,而公开密钥则可以随意发布,任何人都可以获得。
密钥通过网络传输交换,它能够确保及时密钥被拦截,也不会暴露数据信息。
非对称加密中有两个密钥,一个是公钥,一个是私钥,公钥进行加密,私钥进行解密。公开密钥可供任何人使用,私钥只有你自己能够知道。
这种方式有以下缺点:
使用对称密钥的好处是解密的效率比较快,使用非对称密钥的好处是可以使得传输的内容不能被破解,因为就算你拦截到了数据,但是没有对应的私钥,也是不能破解内容的。
那我们就将对称加密与非对称加密结合起来,充分利用两者各自的优势,在交换密钥环节使用非对称加密方式,之后的建立通信交换报文阶段则使用对称加密方式。
具体做法是:发送密文的一方使用对方的公钥进行加密处理“对称的密钥”,然后对方用自己的私钥解密拿到“对称的密钥”,这样可以确保交换的密钥是安全的前提下,使用对称加密方式进行通信。
HTTPS采用也是对称加密和非对称加密两者并用的混合加密机制。在通信刚开始的时候使用非对称算法,比如 RSA
、ECDHE
,首先解决密钥交换
的问题。然后用随机数产生对称算法使用的会话密钥(session key)
,再用公钥加密
。对方拿到密文后用私钥解密
,取出会话密钥。这样,双方就实现了对称密钥的安全交换。
现在我们使用混合加密的方式实现了机密性,是不是就能够安全的传输数据了呢?还不够,在机密性的基础上还要加上完整性
、身份认证
的特性,才能实现真正的安全。而实现完整性的主要手段是 摘要算法(Digest Algorithm)
网络传输过程中需要经过很多中间节点,虽然数据无法被解密,但可能被篡改,那如何校验数据的完整性呢?
我们先介绍下摘要:
摘要是一种单向函数,主要用于将无限的输入值转换为有限的浓缩输出值。比如常见的摘要函数
MD5
,会将任意长度的字节序列转换为一个 128 位的摘要。
摘要算法会输入根据数据的微小变化会得到完全不同的hash值,相同的数据会得到相同的值。就是由于摘要算法的这个特性,验证数据的完整性。
所以在TSL中,主要是基于摘要算法实现数据完整性验证。
大家熟悉的MD5
和SHA
都是历史悠久的摘要算法。
其实你可以把Hash算法理解成一种特殊的压缩算法,它能够把任意长度的数据压缩
成一种固定长度的字符串,这就好像是给数据加了一把锁。
我们在上面解决了完整性的问题,那么就只剩下一个问题了,那就是认证
。
认证怎么做的呢?我们再向服务器发送数据的过程中,黑客(攻击者)有可能伪装成任何一方来窃取信息。它可以伪装成你,来向服务器发送信息,也可以伪装称为服务器,接受你发送的信息。那么怎么解决这个问题呢?
这就要靠数字签名了。
数字签名有两种功效:
我们在上面的文章出现过公钥加密,私钥解密的这个概念。提到的私钥只有你一个人所有,能够辨别唯一性,所以我们可以把顺序调换一下,变成私钥加密,公钥解密。使用私钥再加上摘要算法,就能够实现数字签名
,从而实现认证。
到现在,综合使用对称加密、非对称加密和摘要算法,我们已经实现了加密、数据认证、认证,那么是不是就安全了呢?非也,这里还存在一个数字签名的认证问题。因为私钥是是自己的,公钥是谁都可以发布,所以必须发布经过认证的公钥,才能解决公钥的信任问题。
所以引入了 CA
,CA 的全称是 Certificate Authority
,证书认证机构,你必须让 CA 颁布具有认证过的公钥,才能解决公钥的信任问题。
全世界具有认证的 CA 就几家,分别颁布了 DV、OV、EV 三种,区别在于可信程度。DV 是最低的,只是域名级别的可信,EV 是最高的,经过了法律和审计的严格核查,可以证明网站拥有者的身份(在浏览器地址栏会显示出公司的名字,例如 Apple、GitHub 的网站)。不同的信任等级的机构一起形成了层级关系。
通常情况下,数字证书的申请人将生成由私钥和公钥以及证书签名请求(CSR)
组成的密钥对。CSR是一个编码的文本文件,其中包含公钥和其他将包含在证书中的信息(例如域名,组织,电子邮件地址等)。密钥对和 CSR生成通常在将要安装证书的服务器上完成,并且 CSR 中包含的信息类型取决于证书的验证级别。与公钥不同,申请人的私钥是安全的,永远不要向 CA(或其他任何人)展示。
生成 CSR 后,申请人将其发送给 CA,CA 会验证其包含的信息是否正确,如果正确,则使用颁发的私钥对证书进行数字签名,然后将其发送给申请人。
我们再来用一张图,整体回顾一下 https 连接的完整流程:
觉得本文有用的小伙伴,可以帮忙点个“在看”,让更多的朋友看到咱们的文章。
最后,再给“前端面试题宝典”的辅导服务打下广告,目前有面试全流程辅导、简历指导和模拟面试的增值服务,如果有感兴趣的伙伴,可以联系小助手(微信号:interview-fe)了解详情哦~