HTTP 协议是无状态的,即每次请求都是独立的,服务器不会保存客户端的任何信息。HTTP 协议也是明文的,即请求和响应的内容都是未加密的,任何人都可以在网络上截获并查看。
这样就导致了 HTTP 协议的几个缺点:
除此之外, HTTP 还有效率低下这一大问题:
HTTP 是一种基于文本的协议,虽然易于理解和实现,但也带来了一些效率方面的问题。例如,HTTP 的首部字段往往包含了大量的冗余信息,增加了数据传输的负担;HTTP 的请求和响应往往需要遵循严格的顺序,导致了队头阻塞(head-of-line blocking)问题;HTTP 的消息主体往往没有进行压缩或二进制编码,导致了数据量过大或解析速度过慢等问题。这些问题在 HTTP/2 中使用了首部压缩(header compression)、流优先级(stream priority)和二进制帧(binary frame)等技术得到了解决,提高了数据传输和处理的效率。
由于 HTTP 本身不具备加密的功能,所以也无法做到对通信整体(使用 HTTP 协议通信的请求和响应的内容)进行加密。即,HTTP 报文使用明文(指未经过加密的报文)方式发送。
所谓互联网,是由能连通到全世界的网络组成的。无论世界哪个角落的服务器在和客户端通信时,在此通信线路上的某些网络设备、光缆、计算机等都不可能是个人的私有物,所以不排除某个环节中会遭到恶意窥视行为。
即使已经过加密处理的通信,也会被窥视到通信内容,这点和未加密的通信是相同的。只是说如果通信经过加密,就有可能让人无法破解报文信息的含义,但加密处理后的报文信息本身还是会被看到的。
例如使用抓包工具就能很方便地获取包含在HTTP请求和响应报文中的用户隐私信息,例如:
HTTP 协议中的请求和响应不会对通信方进行确认。HTTP 协议对请求者来之不拒,任何人都可以发起请求,只要服务端接收到请求不论对方是谁都会返回一个响应(前提是对方不在黑名单中)。
HTTP 协议的实现本身非常简单,因此不确认通信方,会存在以下各种隐患:
作为一个通信协议,保证通信报文的完整性是基本要求(总是丢件的邮局会倒闭的很快),所谓“完整性”指的是信息的准确性,也就是接收者接收到报文时,要和发出者发出时完全一致,否则报文可能就是被篡改了(排除其他客观原因)。
HTTP 协议无法证明通信报文的完整性,因此,在请求或响应送出之后直到对方接收之前的这段时间内,即使请求或响应的内容遭到篡改,也没有办法获悉。所谓“无法证明”,是因为报文的发出者只管发出报文,而接收方只管接收报文,因此不论是报文的接收方还是发出方,都无法知晓报文最终或最初是什么样的。
比如,从某个 Web 网站上下载内容,是无法确定客户端下载的文件和服务器上存放的文件是否前后一致的。文件内容在传输途中可能已经被篡改为其他的内容。即使内容真的已改变,作为接收方的客户端和作为发出方的服务端都是觉察不到的。
像这样,请求或响应在传输途中,遭攻击者拦截并篡改内容的攻击称为中间人攻击(Man-in-the-Middle attack,MITM)。
要防止数据被窃听,就要进行加密处理。加密的对象可以是:
HTTP 协议中没有加密机制,但可以通过和 SSL(Secure Socket Layer,安全套接层)或 TLS(Transport Layer Security,安全层传输协议)的组合使用,加密 HTTP 的通信内容。
用 SSL 建立安全通信线路之后,就可以在这条线路上进行 HTTP 通信了。与 SSL 组合使用的 HTTP 被称为 HTTPS(HTTP Secure,超文本传输安全协议)或 HTTP over SSL。
由于 HTTP 协议中没有加密机制,那么就对 HTTP 协议传输的内容本身加密。即把 HTTP 报文里所含的内容进行加密处理。
在这种情况下,客户端需要对 HTTP 报文进行加密处理后再发送请求。
诚然,为了做到有效的内容加密,前提是要求客户端和服务器同时具备加密和解密机制。主要应用在 Web 服务中。有一点必须引起注意,由于该方式不同于 SSL 或 TLS 将整个通信线路加密处理,所以内容仍有被篡改的风险。
HTTP 协议对请求来之不拒,那么过滤掉不合理的请求就显得十分必要了,这可以通过验证请求者的证书来做到。虽然使用 HTTP 协议无法确定通信方,但如果使用 SSL 则可以。SSL 不仅提供加密处理,而且还使用了一种被称为证书的手段,可用于确定方。
证书由值得信任的第三方机构颁发,用以证明服务器和客户端是实际存在的。另外,伪造证书从技术角度来说是异常困难的一件事。所以只要能够确认通信方(服务器或客户端)持有的证书,即可判断通信方的真实意图。
通过使用证书,以证明通信方就是意料中的服务器。这对使用者个人来讲,也减少了个人信息泄露的危险性。证书就像政府颁发的说明一样,具有权威性,前提是这个机构是绝对权威的。通俗地说,服务器或客户端想要获取证书,都是要法人“实名制”的。在网络上只要实名制,人们就会听话很多:)。
在计算机中,任意一个文件都能通过某种哈希算法得到它的哈希值,HTTPS 使用的就是这种方法,即服务端和客户端都会验证报文发出前和接收后的哈希值,只要保证了哈希算法的正确性,就能校验报文发送前与接收后的哈希值来间接校验报文的完整性。
不同算法有各自的特点,在网络通信中的适用程度也不同,这部分将在后续介绍。
HTTPS 并不是一种全新的应用层协议,而是 HTTP 的安全版本(HTTP Secure),上文已经介绍了 HTTPS 是从哪几方面弥补 HTTP 的缺点,下面将对这三个手段展开叙述。
HTTP + 加密 + 认证 + 完整性校验 = HTTPS:
为了体系地认识 HTTPS 协议,首先介绍以下内容的框架:
TLS 协议是 SSL 协议的后续版本,有更高的安全性和更好的兼容性。TLS 支持更多的加密算法和扩展功能,并且可以降级到 SSL 版本来适应不同的场景。因此在不涉及具体细节的情况下(事实上它们通信的过程基本相同),SSL/TLS 协议和 TLS 协议是等价的。
通常,HTTP 运行在 TCP 之上,它直接和 TCP 通信。当使用 SSL 时,则演变成先和 SSL 通信,再由 SSL 和 TCP 通信了。简言之,所谓 HTTPS,其实就是身披 SSL 协议这层外壳的 HTTP。
在采用 SSL/TLS 后,HTTP 就拥有了 HTTPS 的加密、证书和完整性保护这些功能。
SSL 采用一种叫做公开密钥(yuè)加密(Public-key cryptography)的加密处理方式。近代的加密方法中加密算法是公开的,而密钥却是保密的。通过这种方式得以保持加密方法的安全性。
加密和解密都会用到密钥。没有密钥就无法对密码解密,反过来说,任何人只要持有密钥就能解密了。如果密钥被攻击者获得,那加密也就失去了意义。
加密和解密同用一个密钥的方式称为共享密钥加密(Common key crypto system),也被叫做对称密钥加密。
以共享密钥方式加密时必须将密钥也发给对方。可问题是究竟怎样才能安全地转交?在互联网上转发密钥时,密钥本身也是报文的一部分,如果通信被监听那么密钥就可会落入攻击者之手,同时也就失去了加密的意义。另外还得设法安全地保管接收到的密钥。
对称加密最大的问题在于加密的前提是通信方都知晓加密规则,但事实上在网络上的服务器和客户端很难做到这一点,就好像我们每次出门都会遇到不同的人,想要在通信之前将加密规则告知对方,这本身就是一种未经加密的通信,显然对称加密在原理上合理,但不可取。
公开密钥加密使用一对非对称的密钥。一把叫做私有密钥(private key),另一把叫做公开密钥(public key)。顾名思义,私有密钥不能让其他任何人知道,而公开密钥则可以随意发布,任何人都可以获得。
使用公开密钥加密方式,发送密文的一方使用对方的公开密钥进行加密处理,对方收到被加密的信息后,再使用自己的私有密钥进行解密。利用这种方式,不需要发送用来解密的私有密钥,也不必担心密钥被攻击者窃听而盗走。
另外,要想根据密文和公开密钥,恢复到信息原文是异常困难的,因为解密过程就是在对离散对数进行求值,这并非轻而易举就能办到。因此以现在的技术从成本上可以认为这些哈希算法都是不可逆的。
对称加密和非对称加密通常可以结合使用,以发挥各自的优势。在上面的介绍中我们知道公钥加密的缺点是计算量大,即使采用混合加密,也要尽可能以更小的服务器资源占用来保证同等的安全性。对此,SSL/TLS 协议的解决办法是:
HTTPS 充分利用两者各自的优势,将多种方法组合起来用于通信。在交换密钥环节使用公开密钥加密方式,之后的建立通信交换报文阶段则使用共享密钥加密方式。
总结:
加密机制的安全性可以用算法保证,但问题在于公开密钥加密方式还是存在一些问题的。那就是无法证明公开密钥本身就是货真价实的公开密钥。比如,正准备和某台服务器建立公开密钥加密方式下的通信时,如何证明收到的公开密钥就是原本预想的那台服务器发行的公开密钥。或许在公开密钥传输途中,真正的公开密钥已经被攻击者替换掉了。
这就需要证明公开密钥正确性的证书来帮忙了。
由数字证书认证机构(CA,Certificate Authority)和其相关机关颁发的公开密钥证书可以证明公开密钥正确性。证书是数字签名的技术基础保障,也是网上实体身份的证明,能够证明某一实体的身份及其公钥的合法性,证明该实体与公钥二者之间的匹配关系。
数字证书认证机构处于客户端与服务器双方都可信赖的第三方机构的立场上。数字证书认证机构的业务流程是:
服务器会将这份由数字证书认证机构颁发的公钥证书发送给客户端,以进行公开密钥加密方式通信。公钥证书也可叫做数字证书或直接称为证书。
接到证书的客户端可使用数字证书认证机构的公开密钥,对那张证书上的数字签名进行验证,一旦验证通过,客户端便可明确两件事:一,认证服务器的公开密钥的是真实有效的数字证书认证机构。二,服务器的公开密钥是值得信赖的。
此处认证机关的公开密钥必须安全地转交给客户端。使用通信方式时,如何安全转交是一件很困难的事。
这个问题类似对称加密,让我们回到通信协议(Protocol)加密的本质:通信方按照实现约定的规则通信,那么前提是通信方在通信之前就已经知晓了规则。好在这些公钥都可以内置在浏览器中,相当于客户端默认具备了通信的前提。
例如可以在浏览器查看某个网站的证书(一般通过 HTTPS 通信时,网址框旁边会有一个的标志):
证书的一个作用是证明作为通信一方的服务器是否规范(证明公开密钥正确性),除此之外:
数字签名和数字证书的关系可以简单地概括为:
阮一峰:数字签名是什么?
HTTPS 因 SSL/TLS 协议而具有了安全性,在了解 HTTPS 通信过程之前,首先要了解 SSL/TLS 协议的通信过程。
SSL/TLS 协议的基本过程:
值得注意的是,握手阶段以明文通信。
下面介绍"握手阶段"的具体过程:
RSA 加密算法是一种非对称加密算法,在公开密钥加密和电子商业中被广泛使用。RSA 是由 Ron Rivest、Adi Shamir 和 Leonard Adleman 一起提出的。
在 HTTPS 协议中,包括 4 次 TLS 握手。
首先,客户端(通常是浏览器)先向服务器发出加密通信的请求,称之为 ClientHello 请求。
客户端请求主要向服务器提供以下信息:
这里需要注意的是,客户端发送的信息中不包括服务器的域名。也就是说,理论上服务器只能包含一个网站,否则会分不清应该向客户端提供哪一个网站的数字证书。这就是通常一台服务器只能有一张数字证书的原因。
诸如 “ClientHello” 这样的字符串是一种握手消息,它映射了客户端与服务器之间通信之前的准备步骤。
服务器收到客户端请求后,向客户端发出回应,称之为 SeverHello 响应。
服务器响应主要包含以下内容:
客户端收到服务器回应以后,首先使用 CA 的公钥验证服务器证书。如果解密失败,说明证书不符合要求,会向用户显示警告,但访问与否取决于用户。
客户端回应包含以下内容:
摘要:通信协议中的摘要是一种用于验证数据完整性和身份认证的技术,通常由单向散列函数(如 MD5,SHA-1等)生成。对数据进行摘要,就是用哈希算法对数据求哈希值。
需要注意的是,客户端和服务器通过两次单向的会话,使得它们都同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的"会话密钥"(Master Secret)。
从效果上看,这三个随机数通过算法形成了一个很"随机"的随机数,即"会话密钥"。"随机性"是先进的加密算法不可或缺的一部分,更是保证后续通信时数据安全性的保障。
要用三个随机数来生成"会话密钥"的原因是:
增加安全性和随机性。如果只用一个或两个随机数,那么会话密钥就可能被猜测或重复,导致通信被窃听或篡改。使用三个随机数,可以保证会话密钥的生成过程是双方共同参与的,而且每次通信都会产生不同的会话密钥,从而提高了保密性和完整性。一个伪随机可能完全不随机,可是三个伪随机就十分接近随机了。
服务器生成本次会话所用的"会话密钥"后,向客户端最后发送下面信息:
至此,SSL/TLS 协议的握手阶段结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用"会话密钥"加密内容。
HTTPS 协议通信的过程大部分是 SSL/TLS 协议通信的过程。
https://
来指定使用 SSL/TLS 协议。下面是一个 HTTPS 通信的例子:
值得注意的是,「Change Cipher Spec」之前传输的 TLS 握手数据都是明文,之后都是对称密钥加密的密文。
可见,就通信过程而言,HTTPS = HTTP + SSL/TLS(S)。
其中,对于服务器而言最大的缺点就是效率问题,HTTPS 比 HTTP 要慢 2 到 100 倍。"慢"分两种:
除去和 TCP 连接、发送 HTTP 请求 • 响应以外,还必须进行 SSL 通信,因此整体上处理通信量不可避免会增加。
另一点是 SSL 必须进行加密处理。在服务器和客户端都需要进行加密和解密的运算处理。因此从结果上讲,比起 HTTP 会更多地消耗服务器和客户端的硬件资源,导致负载增强。
这个问题没有根本性解决方案,毕竟目前还没有一个以更低成本实现的安全通信协议,通常情况下,如果是非敏感信息则使用 HTTP 通信,只有在包含个人信息等敏感数据时,才利用 HTTPS 加密通信。
因此有时我们访问一些网站时(尤其是用爱发电的个人网站),浏览器经常会告警,毕竟证书一年要几百元。