系列文章目录
【网络编程】网络编程中的基本概念及Java实现UDP、TCP客户端服务器程序(万字博文)
【网络原理】UDP协议的报文结构 及 校验和字段的错误检测机制(CRC算法、MD5算法)
【网络原理】HTTP 协议的基本格式和 fiddler 抓包工具的用法
目录
[一、HTTPS 是什么?](#一、HTTPS 是什么?)
[三、HTTPS 的工作过程](#三、HTTPS 的工作过程)
一、HTTPS 是什么?
HTTPS(超文本传输安全协议)是一种用于安全传输数据的网络协议,它通过在HTTP上增加SSL/TLS协议来保护数据的完整性和安全性。
HTTP协议内容都是按照文本的方式明文传输的,这就导致在传输过程中出现一些被篡改的情况。
臭名昭著的"运营商劫持"
回想一下我们之前在网站上下载APP,正常点击下载按钮,实际下载的确是另一个APP。这就是运营商劫持后的效果。
点击"下载按钮",其实就是在给服务器发送了一个HTTP请求,获取到的HTTP响应其实就包含了该APP的下载链接。运营商劫持之后,就把这个交给用户的响应的下载链接给篡改了。
要解决明文传输产生的问题,就要对其进行"加密"。HTTPS就是在HTTP基础上进行了加密。
二、"加密"是什么?
加密 就是把 明文 (要传输的信息)进行一系列变换,生成 密文。
解密 就是把 密文 再进行一系列变换,还原成 明文。
在这个加密和解密的过程中,往往需要一个或者多个中间的数据,辅助进行这个过程,这样的数据称为 密钥。
三、HTTPS 的工作过程
加密的方式有很多,但是整体可以分成两大类:对称加密 和 非对称加密
引入对称加密
对称加密即通过同一个"密钥",把明文加密成密文,并且也能把密文解密成明文。
引入对称加密之后,即使数据被截获,由于黑客不知道密钥是什么,因此就无法进行解密,也就不知道请求的真实内容是什么了。
但事情没这么简单,服务器同一时刻其实是给很多客户端提供服务的。这么多客户端,如果都使用相同的密钥,那黑客只要破解一个,其他密钥就形同虚设了;因此,每个客户端所使用的密钥必须是不同的。
服务器要维护每个客户端和每个密钥之间的关联关系 ,这也是个很麻烦的事情。比较理想的做法,就是能在客户端和服务器建立连接的时候,双方协商确定这次的密钥是啥。
但是如果之间把密钥明文传输,那么黑客也就能获得密钥了,此时后续的加密操作也就形同虚设了。
因此,密钥的传输也必须加密传输。
但是,要想对密钥进行对称加密,就仍然需要先协商确定一个"密钥的密钥",而密钥的密钥也是同理......此时,密钥的传输再用对称加密就行不通了,就需要引入非对称加密。
引入非对称加密
非对称加密要用到两个密钥,一个叫做"公钥",一个叫做"私钥"。
最大的缺点就是运算速度非常慢,比对称加密要慢很多。
- 通过公钥对明文加密,变成密文
- 通过私钥对密文解密,变成明文
也可以反着用
- 通过私钥对明文加密,变成密文
- 通过公钥对密文解密,变成明文
使用非对称加密,主要目的是为了对 对称密钥 进行加密。
不使用非对称加密,来加密和解密密文,是因为非对称加密的运算速度非常慢,效率远远低于对称加密。
⾮对称加密的数学原理比较复杂, 涉及到⼀些 数论 相关的知识. 这⾥举⼀个简单的生活上的例子.
A 要给 B ⼀些重要的⽂件, 但是 B 可能不在. 于是 A 和 B 提前做出约定:
B 说: 我桌⼦上有个盒子, 然后我给你⼀把锁, 你把文件放盒子里用锁锁上, 然后我回头拿着钥匙来开锁取文件.
在这个场景中, 这把锁就相当于公钥, 钥匙就是私钥. 公钥给谁都行(不怕泄露), 但是私钥只有 B 自己持有. 持有私钥的人才能解密.
上图过程:
- 客户端在本地生成对称密钥,对称密钥通过公钥加密,发送给服务器
- 黑客手里虽然有公钥,但是密文需要通过私钥才能解密,而私钥黑客是拿不到的,只有服务器才持有私钥。即使其截获了数据,也无法获取到对称密钥,也就无法解密出原文了。
- 服务器通过私钥加密,还原出客户端发送的对称密钥,并且使用这个对称密钥加密给客服端返回的响应数据。
- 客户端和服务器都知道了对称密钥,后续客户端和服务器的通信都只用对称加密即可。
上述操作看似解决了问题,但仍然存在重大的安全漏洞,黑客仍然有办法获取到对称密钥。
中间人攻击
服务器可以创建出一对公钥和私钥,同样的,黑客也可以按照同样的方式,创建出一对公钥和私钥,冒充自己是服务器。
- 服务器具有非对称加密算法的公钥S,私钥S'
- 中间⼈具有非对称加密算法的公钥M,私钥M'
- 客户端向服务器发起请求,服务器明文传送公钥S给客户端
- 中间人劫持数据报文,提取公钥S并保存好,然后将被劫持报文中的公钥S替换成为自己的公钥M, 并将伪造报文发给客户端
- 客户端收到报文,提取公钥M(自己当然不知道公钥被更换过了),自己形成对称密钥X,用公钥M加密X,形成报文发送给服务器
- 中间人劫持后,直接用自己的私钥M'进行解密,得到通信密钥X,再用曾经保存的服务端公钥S加密后,将报文推送给服务器
- 服务器拿到报文,用自己的私钥S'解密,得到通信密钥X
- 双方开始采用X进行对称加密,进行通信。但是一切都在中间人的掌握中,劫持数据,进行窃听甚至修改,都是可以的
针对上述问题,最关键的一点,客户端拿到公钥的时候,要能有办法验证,这个公钥是否是真的,而不是黑客伪造的。
引入证书
服务器在使用HTTPS前,需要向CA机构申领一份数字证书,数字证书里含有证书申请者信息、公钥信息等。服务器把证书传输给浏览器,浏览器从证书里获取公钥就行了,证书就如身份证,证明服务端公钥的权威性。
关键点:证书数据也是经过了黑客设备,但是,黑客无法修改证书中的公钥,因为客户端拿到证书之后,会先对证书验证真伪。
证书可以理解成是一个结构化的字符串,里面包含了以下信息:
- 证书发布机构
- 证书有效期
- 公钥和私钥对
- 证书所有者
- 签名
- ......
证书验证的过程:
证书验证通常包括以下步骤:
-
验证证书的有效性:客户端会检查证书的有效期,确保证书在当前时间内是有效的,没有过期。
-
验证证书的颁发机构(CA)是否受信任:客户端会检查证书中的颁发机构是否在客户端的信任列表中。信任列表中包含了受信任的CA的根证书或者中间证书。
-
验证证书中的域名是否与服务器的域名匹配:客户端会检查证书中包含的域名(通常是服务器的域名)是否与客户端正在连接的服务器的域名匹配。这是为了防止中间人攻击。
-
验证证书的签名:客户端会使用证书中的公钥对证书的签名进行解密,以确保证书在传输过程中没有被篡改。如果解密后的结果与证书的内容相符,则证明证书是真实有效的。
此处的签名是一种用于验证证书真实性和完整性的机制,它确保证书在传输过程中没有被篡改。签名使用数字签名算法对证书的内容进行加密生成,然后由证书的签发机构(CA)使用私钥(证书自己的私钥,和服务器的私钥无关)进行签名(加密)。
验证证书的签名通常使用公钥进行解密,如果解密后的结果与证书的内容相符,则证明证书是由相应的CA签发的,并且证书在传输过程中没有被篡改。
通过以上步骤,客户端可以验证服务器的数字证书的真实性和完整性。如果验证通过,客户端就可以信任服务器,并与之建立安全的通信通道。如果任何一步验证失败,客户端会中止连接,以防止与不受信任的服务器建立通信。
中间人有没有可能篡改证书?
- 由于中间人没有CA机构的私钥,所以无法用私钥加密形成签名,那么也就无法对篡改后的证书形成匹配的的签名
- 如果强行篡改,客户端收到该证书后会发现明文和签名解密后的值不一致,则说明证书已被篡改,证书不可信,从而终止向服务器传输信息,防止信息泄露给中间人。
中间人掉包整个证书?
- 中间人没有CA私钥,所以无法制作假的证书
- 所以中间人只能向CA申请真证书,然后用自己申请的证书进行掉包
- 虽然掉包确实是可以做到的,但是,证书明文中包含了域名等服务器认证信息,此时客户端依旧能够识别出来
经过上述一系列调整,HTTPS 最终的加密过程简单概括为以下步骤:
-
客户端发起HTTPS请求:用户在浏览器中输入HTTPS网址或点击HTTPS链接,浏览器向服务器发起HTTPS请求。
-
服务器发送证书:服务器收到请求后,会将自己的SSL/TLS证书发送给客户端。这个证书包含了服务器的公钥以及其他相关信息。
-
客户端验证证书:客户端收到服务器发送的证书后,会验证证书的真实性和合法性。它会检查证书是否由受信任的证书颁发机构(CA)签发,以及证书是否在有效期内等。
-
客户端生成密钥:如果证书验证通过,客户端会生成一个随机的对称密钥,并使用服务器的公钥加密该密钥。
-
服务器解密密钥:服务器收到客户端发送的加密密钥后,会使用自己的私钥进行解密,从而得到对称密钥。
-
加密通信:客户端和服务器现在都拥有了相同的对称密钥,它们可以使用对称密钥来加密和解密通信中的数据。这样,所有的通信数据都会被加密,确保了数据的安全性和隐私性。
-
数据传输:客户端和服务器之间开始通过加密通道传输数据,包括网页内容、用户信息等。
-
连接关闭:通信完成后,客户端和服务器可以选择关闭连接,或者保持连接以便后续通信。