HTTP 协议(二)HTTPS

1. HTTPS 概述

HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版。即 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL。其所用的端口号是 443。
SSL: SSL(Secure Socket Layer,安全套接字层),是 netscape 公司设计的主要用于 web 的安全传输协议。这种协议在 WEB 上获得了广泛的应用。通过证书认证来确保客户端和网站服务器之间的通信数据是加密安全的。 SSL 协议位于 TCP/IP 协议与各种应用层协议之间,为数据通讯提供安全支持。SSL 协议可分为两层:
SSL 记录协议(SSL Record Protocol):它建立在可靠的传输协议(如 TCP )之上,为高层协议提供数据封装、压缩、加密等基本功能的支持。
SSL 握手协议(SSL Handshake Protocol):它建立在 SSL 记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。
TLS: TLS(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。
TLS 1.0是IETF(Internet Engineering Task Force,Internet工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本,可以理解为SSL 3.1(可简单理解为同一事物不同阶段的不同称呼),它是写入了 RFC 的。该协议由两层组成: TLS 记录协议(TLS Record)和 TLS 握手协议(TLS Handshake)。较低的层为 TLS 记录协议,位于某个可靠的传输协议(例如 TCP)上面。
SSL和TLS的主要区别? TLS 的主要目标是使 SSL 更安全,并使协议的规范更精确和完善。另外,TLS 版本号也与 SSL 的不同(TLS的版本1.0使用的版本号为SSLv3.1).

2. 加解密算法

2.1. 加解密算法类型

对称加密(symmetrcic encryption): 密钥只有一个,加密解密为同一个密码,且加解密速度快,典型的对称加密算法有 DES、AES,RC5,3DES 等;例如我们使用 WinRAR 创建一个带密码(口令)的加密压缩包。当你下次要把这个压缩文件解开的时候,你需要输入【同样的】密码。在这个例子中,密码/口令就如同刚才说的”密钥”。
对称加密主要问题是共享秘钥,除你的计算机(客户端)知道另外一台计算机(服务器)的私钥秘钥,否则无法对通信流进行加密解密。解决这个问题的方案非对称秘钥。
非对称加密: 使用两个秘钥:公共秘钥和私有秘钥。私有秘钥由一方密码保存(一般是服务器保存),另一方任何人都可以获得公共秘钥。一般来说指:加密时使用公钥,解密时使用私钥。
这种密钥成对出现(且根据公钥无法推知私钥,根据私钥也无法推知公钥),加密解密使用不同密钥(公钥加密需要私钥解密,私钥加密需要公钥解密),相对对称加密速度较慢,典型的非对称加密算法有 RSA、DSA 等。

2.1. 非对称加密算法 RSA 的加密解密原理

在这里插入图片描述

  • 每个用户都有一对私钥和公钥。
    私钥用来进行解密和签名,是给自己用的。
    公钥由本人公开,用于加密和验证签名,是给别人用的。
  • 当该用户发送文件时,用私钥签名,别人用他给的公钥解密,可以保证该信息是由他发送的。即数字签名。
  • 当该用户接受文件时,别人用他的公钥加密,他用私钥解密,可以保证该信息只能由他看到。即安全传输。

3. HTTPS 的单向认证通信过程

非对称加密很耗时,不可能对实际的数据都非对称加密来传输。HTTPS 采用的是处理信息的方式是:结合对称加密+非对称加密这两种方式。我们可以用非对称加密的方式来传输对称加密过程中的密钥,之后我们就可以采取对称加密的方式来传输数据了。
简单工作过程如下:
1、客户端请求公钥:服务器用明文的方式给客户端发送自己的公钥(对应的私钥还在服务端手上,没有泄露)。
2、客户端生成随机数密钥:客户端收到公钥之后,会生成一个随机数密钥(对称加密用的),然后用公钥对这个随机数密钥进行加密,之后再把随机数密钥传输给服务器。
3、服务器使用私钥解密随机数密钥:服务器收到随机数密钥之后用私钥解密得到随机数解密,此时,客户端和服务端都拥有了这个随机数密钥,并且它没有被泄露。即使黑客截取了公钥或者加密后的随机数都无法解密(因为公钥加密的随机数只能用私钥解密)
4、对称加密传输:最后服务器安全得到这把随机数密钥了,而客户端也有同样一把随机数密钥,他们就可以进行对称加密传输数据了。
在这里插入图片描述
过程大致如下:"握手阶段"涉及四次通信,我们一个个来看。需要注意的是,"握手阶段"的所有通信都是明文的。
在这里插入图片描述

3.1. 客户端发出 TSL 请求(ClientHello)

由于客户端(如浏览器)对一些加解密算法的支持程度不一样,但是在 TLS 协议传输过程中必须使用同一套加解密算法才能保证数据能够正常的加解密。在 TLS 握手阶段,客户端首先要告知服务端,自己支持哪些加密算法,所以客户端需要将本地支持的加密套件(Cipher Suite)的列表传送给服务端。除此之外,客户端还要产生一个随机数,这个随机数一方面需要在客户端保存,另一方面需要传送给服务端,客户端的随机数需要跟服务端产生的随机数结合起来产生后面要讲到的 Master Secret 。
综上,在这一步,客户端主要向服务器提供以下信息:

  • 支持 TLS/SSL 协议版本,比如 TLS 1.0 版
  • 一个客户端生成的随机数 ClientRnd (第1个随机数),稍后用于生成”对话密钥”
  • 支持的加密算法,比如 RSA 公钥加密
  • 支持的压缩方法

3.2. 服务器回应(SeverHello->Server Hello Done)

server_hello: 服务端返回协商的信息结果,包括选择使用的协议版本 version,选择的加密套件 cipher suite,选择的压缩算法 compression method、随机数 ServerRnd 等,其中随机数用于后续的密钥协商;
server_certificates: 服务器端配置对应的证书链,用于身份验证与密钥交换;
server_hello_done: 通知客户端 server_hello 信息发送结束;
从 Server Hello 到 Server Done,有些服务端的实现是每条单独发送,有服务端实现是合并到一起发送。Sever Hello 和 Server Done 都是只有头没有内容的数据。从抓包图中,数据包是分段发送的:
在这里插入图片描述
服务端在接收到客户端的 Client Hello 之后,服务端需要将自己的证书发送给客户端。这个证书是对于服务端的一种认证。例如,客户端收到了一个来自于称自己是 www.aliyun.com 的数据,但是如何证明对方是合法的aliyun呢?这就是证书的作用,aliyun的证书可以证明它是aliyun,而不是其他云。证书是需要申请,并由专门的数字证书认证机构(CA)通过非常严格的审核之后颁发的电子证书。颁发证书的同时会产生一个私钥和公钥。私钥由服务端自己保存,不可泄漏。公钥则是附带在证书的信息中,可以公开的。证书本身也附带一个证书电子签名,这个签名用来验证证书的完整性和真实性,可以防止证书被串改。另外,证书还有个有效期。
在服务端向客户端发送的证书中没有提供足够的信息(证书公钥)的时候,还可以向客户端发送一个 Server Key Exchange
此外,对于非常重要的保密数据,服务端还需要对客户端进行验证,以保证数据传送给了安全的合法的客户端。服务端可以向客户端发出 Cerficate Request 消息,要求客户端发送证书对客户端的合法性进行验证。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供 USB 密钥,里面就包含了一张客户端证书。
跟客户端一样,服务端也需要产生一个随机数发送给客户端。客户端和服务端都需要使用这两个随机数来产生 Master Secret。
最后服务端会发送一个 Server Hello Done 消息给客户端,表示 Server Hello 消息结束了。
综上,在这一步,服务器的回应包含以下内容:

  • 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信
  • 一个服务器生成的随机数ServerRnd(第2个随机数),稍后用于生成”对话密钥”
  • 确认使用的加密算法,比如RSA公钥加密
  • 服务器证书:证书包含服务器信息:域名/服务地址、公钥、证书的CA

3.3. 客户端回应(Certificate Verify)

client_key_exchange + change_cipher_spec + encrypted_handshake_message
Client Key Exchange:
如果服务端需要对客户端进行验证,在客户端收到服务端的 Server Hello 消息之后,首先需要向服务端发送客户端的证书,让服务端来验证客户端的合法性。
Certificate Verify (验证证书的合法性):
接着,客户端需要对服务端的证书进行检查:颁发证书的机构是否合法、证书中的域名与实际域名不一致、证书已经过期等等。如果是浏览器客户端,若证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示。
如果证书没有问题,客户端就会从服务器证书中取出服务器的公钥。然后,向服务器发送下面几项项信息:

  • 生成随机数(对称秘钥 PreMasterSecret ,整个过程中第 3 个随机数):客户端并使用证书带的公钥将 PreMasterSecret 进行加密. 它是客户端使用一些加密算法(例如:RSA, Diffie-Hellman)产生一个48个字节的 Key,这个 Key 叫 PreMaster Secret,很多材料上也被称作 PreMaster Key。
  • 编码改变通知ChangeCipherSpec: 表示随后的信息都将用双方商定的加密算法和密钥发送
  • ClientHash 值: 通过之前交换的数据(前面发送的所有内容)生成一个 ClientHash 值,用来供服务器校验。
  • 客户端握手结束通知,表示客户端的握手阶段已经结束。
    此时客户端已经获取全部的计算协商密钥需要的信息:两个明文随机数 ClientRnd 和 ServerRnd 与自己计算产生的 PreMasterSecret ,计算得到协商密钥;
    enc_key(SessionSecret)=Fuc(ClientRnd, ServerRnd, PreMasterSecret )
    Change Cipher Spec:
    Change Cipher Spec 客户端通知服务器后续的通信都采用协商的通信密钥和加密算法进行加密通信;
    Change Cipher Spec 是一个独立的协议,体现在数据包中就是一个字节的数据,用于告知服务端,客户端已经切换到之前协商好的加密套件(Cipher Suite)的状态,准备使用之前协商好的加密套件加密数据并传输了。
    Encrypted Handshake Message:
    在 Change cipher Spec 传输完毕之后,通过之前交换的数据(前面发送的所有内容)生成一个 ClientHash 数据。 客户端会使用之前协商好的加密算法和 SessionSecret 加密 ClientHash 数据传送给服务端,此 ClientHash 数据是为了在正式传输应用数据之前对刚刚握手建立起来的加解密通道进行验证。

3.4. 服务器的最后回应(Server Finish)

使用自己证书的私钥解密出 PreMasterSecret
生成SessionSecret:
服务端根据之前的随机数(ClientRnd ,ServerRnd,PreMasterSecret )和约定的加密算法,生成用于加密后续传输数据的会话密钥 SessionSecret。
enc_key=Fuc(ClientRnd, ServerRnd, PreMasterSecret )
校验 clientHash (确认不是假的客户端)和密钥SessionSecret正确性:
计算之前所有接收信息的 hash 值,即为serverHash。然后解密客户端发送encrypted_handshake_message的ClientHash,验证数据和密钥正确性(即serverHash ==ClientHash 是否为true);
Change Cipher Spec确认变更编码:
会给客户端发送一个 ChangeCipherSpec,告知客户端已经切换到协商过的加密套件状态,准备使用加密套件和 Session Secret加密数据了。
Encrypted Handshake Message Finish信息:
服务器也结合所有当前的通信参数信息生成一段Finish消息数据,并采用协商密钥SessionSecret 与算法加密并发送到客户端, 以验证之前通过握手建立起来的加解密通道是否成功。

3.5. 握手结束

客户端计算所有接收信息的 hash 值,并采用协商密钥解密 encrypted_handshake_message,验证服务器发送的数据和密钥,验证通过则握手完成;

3.6. 数据传输:

根据之前的握手信息,如果客户端和服务端都能对 Finish 信息进行正常加解密且消息正确的被验证,则说明握手通道已经建立成功,接下来,双方可以使用上面产生的 Session Secret 对数据进行加密传输了。
在这个过程中,有几个关键点:

  • 前两次的随机数(客户端随机数、服务端随机数)是明文传输的
  • 非对称密钥算法只被使用了一次,即客户端使用证书公钥加密 PreMasterSecret,服务端使用证书私钥解密出 PreMasterSecret
  • 应用数据的传输使用的是对称密钥算法,客户端/服务端都使用会话密钥进行加/解密
    在握手阶段,安全与否的关键在于 PreMasterSecret 是否能够被破解,虽然理论上通过 RSA 算法加密是比较安全的,但还是有破解的可能性。最安全的做法是不发送 PreMasterSecret,而是根据一系列参数由客户端和服务端分别计算出 PreMasterSecret,这个算法就是迪菲-赫尔曼密钥交换。
    有了 PreMasterSecret 以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把"会话密钥"。至于为什么一定要用三个随机数,来生成"会话密钥",dog250解释得很好:
    “不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。
    对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。
    pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。”

4. 数字证书和 CA

数字证书(Digital Certificate)是用来证明公钥(非对称密钥算法中用于加密的密钥)所有者身份的。
1、数字证书是 CA 对公钥签名:数字证书则是由证书认证机构(CA)对证书申请者真实身份验证之后,用 CA 的根证书对申请人的一些基本信息以及申请人的公钥进行签名(相当于加盖发证书机构的公章)后形成的一个数字文件。
2、数字证书公开的:CA 完成签发证书后,会将证书发布在 CA 的证书库(目录服务器)中,任何人都可以查询和下载,因此数字证书和公钥一样是公开的。实际上,数字证书就是经过 CA 认证过的公钥。
3、如何认证公钥可靠:我们人人都可以自己生成一个公钥,但是这个公钥是否能代表是你的,这个认证的过程需要一个权威机构执行,这个机构就是证书授权中心。
证书授权中心(Certificate Authority)负责证书颁发。CA 是行业内信得过的组织机构,它具有权威性,由它颁发的证书大家都相信是可靠的。
一般我们自己也生成 HTTPS 证书,但是自己生成的 HTTPS 证书却是不能用的。因为浏览器只会承认受信任 CA 所签发出来的证书,其他个人自签的 HTTPS 证书浏览器是不会承认的,一律会显示“此网站不安全”的安全提示。所以不要尝试自己去生成 HTTPS 证书,需要HTTPS 证书我们就去找受信任的 CA 机构进行申请。

4.1. CA 认证流程

在这里插入图片描述
SSL双向认证步骤:

  1. 服务端申请证书:HTTPS 通信双方的服务器端向 CA 机构申请证书,CA 机构是可信的第三方机构,它可以是一个公认的权威的企业,也可以是企业自身。企业内部系统一般都使用企业自身的认证系统。CA 机构下发根证书、服务端证书及私钥给申请者;
  2. 客户端向 CA 机构申请证书,CA 机构下发根证书、客户端证书及私钥个申请者;
  3. 客户端向服务器端发起请求,服务端下发服务端证书给客户端。客户端接收到证书后,通过私钥解密证书,并利用服务器端证书中的公钥认证证书信息比较证书里的消息,例如域名和公钥与服务器刚刚发送的相关消息是否一致,如果一致,则客户端认为这个服务器的合法身份;
  4. 客户端发送客户端证书给服务器端,服务端接收到证书后,通过私钥解密证书,获得客户端的证书公钥,并用该公钥认证证书信息,确认客户端是否合法;
  5. 客户端通过随机秘钥加密信息,并发送加密后的信息给服务端。服务器端和客户端协商好加密方案后,客户端会产生一个随机的秘钥,客户端通过协商好的加密方案,加密该随机秘钥,并发送该随机秘钥到服务器端。服务器端接收这个秘钥后,双方通信的所有内容都都通过该随机秘钥加密;
    通过上述介绍,我们得知使用 SSL/TLS 需要做如下准备:
    下面我们针对自建 CA 做一个完整的示例(证书相关使用 Linux 的 openssl 命令,客户端、服务端使用 Golang)。
    数字证书:可以找权威的证书授权中心颁发证书(有付费的,也有免费的),也可以自己做 CA,然后自己给自己颁发证书
    服务端使用证书,比如配置 NGINX 来使用
    客户端使用 SSL/TLS 协议和服务端进行通讯,如果是自己的 CA 颁发的证书,还需要在客户端导入 CA 的根证书
建立 CA
生成 CA 私钥:openssl genrsa -out ca.key 2048
生成 CA 根证书:openssl req -new -x509 -days 3650-key ca.key -out ca.crt

颁发证书
生成证书私钥:openssl genrsa -out auto.pem 1024
生成证书公钥:openssl rsa -in auto.pem -out auto.key
生成签名请求:openssl req -new -key auto.pem -out auto.csr,其中的 Common Name 一定要填写客户端访问时的域名,并且不能是 IP
CA 签名(颁发)证书:openssl x509 -req -sha256 -in auto.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -out auto.crt
最终我们需要的就是公钥 auto.key 以及证书 auto.crt。

4.2. 浏览器内置常用证书

一个重要的问题是,如何安全转交认证机构的公钥是一件很困难的事,因此,大多数浏览器开发商发布版本时,会事先植入常用认证机关的公钥。
我们可以 Google Chrome 为例:打开浏览器的设置选项,选择高级,可以看到隐私设置和安全性下面的一些设置,其中管理证书就可以看到谷歌浏览器一些内置证书,如图:
在这里插入图片描述

4.3. 双向认证

双向认证和单向认证原理基本差不多,主要区别是除了客户端需要认证服务端以外,服务端对客户端也需要认证。什么场景下需要验证客户端呢?比如一些银行业务,银行会要求客户必须在电脑上插入它们签发的U盾之类的东西,或者安装什么控件,这里就类似客户端证书的概念,没有这个证书的人无法使用银行提供的业务。
在这里插入图片描述

5. HTTP各种长度限制

5.1. URL长度限制

在 Http1.1协议中并没有提出针对 URL 的长度进行限制,RFC 协议里面是这样描述的,HTTP 协议并不对URI的长度做任何的限制,服务器端必须能够处理任何它们所提供服务多能接受的URI,并且能够处理无限长度的 URI,如果服务器不能处理过长的URI,那么应该返回414状态码。
虽然Http协议规定了,但是Web服务器和浏览器对URI都有自己的长度限制。
服务器的限制:我接触的最多的服务器类型就是Nginx和Tomcat,对于url的长度限制,它们都是通过控制http请求头的长度来进行限制的,nginx的配置参数为large_client_header_buffers,tomcat的请求配置参数为maxHttpHeaderSize,都是可以自己去进行设置。
浏览器的限制:每种浏览器也会对url的长度有所限制,下面是几种常见浏览器的url长度限制:(单位:字符)
IE : 2803
Firefox:65536
Chrome:8182
Safari:80000
Opera:190000
对于get请求,在url的长度限制范围之内,请求的参数个数没有限制。

5.2. Post数据的长度限制

Post数据的长度限制与url长度限制类似,也是在Http协议中没有规定长度限制,长度限制可以在服务器端配置最大http请求头长度的方式来实现。

5.3. Cookie的长度限制

Cookie的长度限制分这么几个方面来总结。
(1) 浏览器所允许的每个域下的最大cookie数目,没有去自己测试,从网上找到的资料大概是这么个情况
IE :原先为20个,后来升级为50个
Firefox: 50个
Opera:30个
Chrome:180个
Safari:无限制
当Cookie数超过限制数时浏览器的行为:IE和Opera会采用LRU算法将老的不常使用的Cookie清除掉,Firefox的行为是随机踢出某些Cookie的值。当然无论怎样的策略,还是尽量不要让Cookie数目超过浏览器所允许的范围。
(2) 浏览器所允许的每个Cookie的最大长度
Firefox和Safari:4079字节
Opera:4096字节
IE:4095字节
(3) 服务器中Http请求头长度的限制。Cookie会被附在每次http请求头中传递给服务器,因此还会受到服务器请求头长度的影响。

5.4. Html5 LocalStorage

Html5提供了本地存储机制来供Web应用在客户端存储数据,尽管这个并不属于Http协议的一部分,但是随着Html5的流行,我们可能需要越来越多使用LocalStorage,甚至当它普及的时候跟它打交道就会同今天我们跟Cookie打交道一样多。
对于LocalStorage的长度限制,同Cookie的限制类似,也是浏览器针对域来限制,只不过cookie限制的是个数,LocalStorage限制的是长度:
Firefox\Chrome\Opera都是允许每个域的最大长度为5MB
但是这次IE比较大方,允许的最大长度是10MB

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值