哈喽,大家好,我是jiaynn~
对于我来说,其实一直比较了解的是 HTTP 协议,对于 HTTPS 一直只有一个大概的了解,只知道他比 HTTP 安全,通过TSL来保证他的安全性,但一直没有很深入的了解,今天,我们就来深入的了解一下 HTTPS,走进 HTTPS 的世界吧~
1、前置知识
TLS协议(Transport Layer Security)
TLS的前生是安全插口层(SSL),TLS通过建立安全连接实现数据在两个应用进程之间的安全传输过程,它实现了两个应用进程之间的双向身份鉴别,保证了传输数据的保密性和完整性
对称加密和非对称加密
对称加密(单钥体制): 指在加密和解密时使用相同密钥的密码算法,他的保密性取决于密钥的保密性,与算法的保密性无关。
非对称加密(公钥密码体制): 在加密和解密的过程中使用两个不同的密钥,其中,一个密钥可以公开,称为公钥,另一个密钥必须保密,称为私钥,由公钥求解私钥的计算是不可行的。
我的理解是:
对于数字签名:私钥签名,公钥验证
对于加密来说的话,则是公钥加密,私钥解密
中间人攻击
简单的讲,就是黑客悄悄的躲在通信双方之间,窃听甚至篡改通信信息。而通信双方并不知道消息已经被截获甚至篡改了
数字证书
网站在使用 HTTPS 之前,需要向CA机构申领一份数字证书,数字证书里面含有证书持有者信息、公钥信息、权威机构的信息等,服务器把证书传输给浏览器,浏览器从证书里获取公钥就可以了。证书就如身份证,证明该公钥对应该网站
数字签名
签名者用私钥对前面的杂凑值进行密码运算得到的结果,并且这个结果只能用签名者的公钥进行验证,这里我们就需要用数字签名来防止数字证书被篡改
2、进入正题
2.1 HTTP的相关知识
HTTP 是超文本传输协议,无状态,基于 TCP/IP 协议传输数据
版本 | 内容 |
---|---|
HTTP/1.0 | 传输内容格式不限制,GET, POST 和 HEAD方法 |
HTTP/1.1 | 长连接,新增OPTIONS, PUT, DELETE, TRACE 和 CONNECT |
HTTP/2 | 多路复用 |
HTTP/3 | UDP |
为什么HTTP不安全?
HTTP是使用明文进行传输,主要存在窃听、篡改、冒充风险(中间人攻击)
所以我们需要使用一种安全的通信方式,来保证数据传输过程的完整性,保密性以及双方的身份鉴别。
2.2 用对称加密可行吗?
我们先来看看最简单的对称加密是否可行,如果通信双方各自持有一个密钥,且没有别人知道,那么这个通信就是安全的(除非密钥被破解了)
但有一个很严重的问题,这个密钥怎样传输能只让通信双方知晓,而其他人不知道
有两种办法:
-
服务器直接将密钥传输给浏览器,但这个密钥在传输途中被被人劫持了怎么办?->不可行
-
浏览器里面预存了网站A的密钥,而且保证只有这俩人知道,这样的话,浏览器就要预存所有HTTPS网站的密钥就行了,这可行吗?当然不可行!
以上两种方法都不可行,这就请出了非对称加密
【学习地址】:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发
【文章福利】:免费领取更多音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击1079654574加群领取哦~
2.3 非对称加密可行吗?
因为我们要保证通信双方两条路都安全,所以就有了以下思路
这样就实现了双方的安全通信,可HTTPs却没有采用这种加密方式?为什么呢?
因为这种非对称加密算法非常耗时,而对称加密快很多
2.4 HTTPS实现原理
我们一步一步去探寻
2.4.1 第一种实现方法
-
某网站拥有一个公钥A,和一个私钥A'
-
浏览器向网站服务器请求,服务器把公钥A明文传输给浏览器
-
浏览器随机生成一个会话密钥X,用公钥A加密后传送给服务器
-
服务器用私钥A‘解密得到会话密钥X
-
这样双方都拥有了会话密钥X,且别人不知道,之后双方通信通过密钥X加解密即可
这种方法好像实现了诶,但他还有一个重要的bug!容易遭受到中间人攻击!!
-
某网站拥有一个公钥A,和一个私钥A'
-
浏览器向网站服务器请求,服务器把公钥A明文传输给浏览器
-
中间人劫持到公钥A,然后把把公钥A替换成自己的公钥B,发送给浏览器
-
浏览器随机生成一个会话密钥X,用公钥B加密后传送给服务器
-
中间人劫持后用私钥B’解密得到密钥X,再用公钥A进行加密发送给服务器
-
服务器用私钥A‘解密得到会话密钥X
这样在双方根本不知情的情况下,实现了中间人攻击,此后可以对其通信过程进行监听、篡改、冒充!!
出现这种情况的根本原因是浏览器无法确认收到的公钥是不是来自于服务器
2.4.2 如何证明浏览器收到的公钥来自于服务器?
我们可以通过上文提到的数字证书来实现,服务器把证书传输给浏览器,浏览器从证书里获取公钥就可以了。证书就如身份证,证明该公钥对应该网站
2.4.3 证书在传输过程中如何防止被篡改?
我们对数字证书的内容进行数字签名即可
下面是借鉴了大佬的文章
中间人有可能篡改该证书吗?
假设中间人篡改了证书的原文,由于他没有CA机构的私钥,所以无法得到此时加密后签名,无法相应地篡改签名。浏览器收到该证书后会发现原文和签名解密后的值不一致,则说明证书已被篡改,证书不可信,从而终止向服务器传输信息,防止信息泄露给中间人。
既然不可能篡改,那整个证书被掉包呢?
中间人有可能把证书掉包吗?
假设有另一个网站B也拿到了CA机构认证的证书,它想劫持网站A的信息。于是它成为中间人拦截到了A传给浏览器的证书,然后替换成自己的证书,传给浏览器,之后浏览器就会错误地拿到B的证书里的公钥了,这确实会导致上文“中间人攻击”那里提到的漏洞?
其实这并不会发生,因为证书里包含了网站A的信息,包括域名,浏览器把证书里的域名与自己请求的域名比对一下就知道有没有被掉包了。
为什么制作数字签名时需要hash一次?
我初识HTTPS的时候就有这个疑问,因为似乎那里的hash有点多余,把hash过程去掉也能保证证书没有被篡改。
最显然的是性能问题,前面我们已经说了非对称加密效率较差,证书信息一般较长,比较耗时。而hash后得到的是固定长度的信息(比如用md5算法hash后可以得到固定的128位的值),这样加解密就快很多。
3、最终实现
-
client向server发送请求baidu.com,然后连接到server的443端口,发送的信息主要是随机值1和客户端支持的加密算法。
-
server接收到信息之后给予client响应握手信息,包括随机值2和匹配好的协商加密算法,这个加密算法一定是client发送给server加密算法的子集。
-
随即server给client发送第二个响应报文是数字证书。服务端必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面,这套证书其实就是一对公钥和私钥。传送证书,这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间、服务端的公钥,第三方证书认证机构(CA)的签名,服务端的域名信息等内容。
-
客户端解析证书,这部分工作是由客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随机值(预主秘钥)。
-
客户端认证证书通过之后,接下来是通过随机值1、随机值2和预主秘钥组装会话秘钥。然后通过证书的公钥加密会话秘钥。
-
传送加密信息,这部分传送的是用证书加密后的会话秘钥,目的就是让服务端使用秘钥解密得到随机值1、随机值2和预主秘钥。
-
服务端解密得到随机值1、随机值2和预主秘钥,然后组装会话秘钥,跟客户端会话秘钥相同。
-
客户端通过会话秘钥加密一条消息发送给服务端,主要验证服务端是否正常接受客户端加密的消息。
-
同样服务端也会通过会话秘钥加密一条消息回传给客户端,如果客户端能够正常接收的话表明SSL层连接建立完成了。
4、如何保密传输HTTP消息呢
5、成本考虑:
-
SSL证书需要购买申请,功能越强大的证书费用越高
-
SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗。
-
根据ACM CoNEXT数据显示,使用HTTPS协议会使页面的加载时间延长近50%,增加10%到20%的耗电。
-
HTTPS连接缓存不如HTTP高效,流量成本高。
-
HTTPS连接服务器端资源占用高很多,支持访客多的网站需要投入更大的成本。
-
HTTPS协议握手阶段比较费时,对网站的响应速度有影响,影响用户体验。比较好的方式是采用分而治之,类似12306网站的主页使用HTTP协议,有关于用户信息等方面使用HTTPS。
原文链接:彻底搞懂HTTPS - 掘金