详解Https出现的前因后果

我是研究僧i 提交于 2019-12-07 16:34:23

虽然自己不直接从事互联网行业,但是对互联网行业的技术一直没有放松学习,特别是安全方面一直是我薄弱的方面,所以最近踏下心来好好的研究了下互联网安全方面的内容。

网上关于SSL、Https的学习资料比较多,有些讲的太宽泛,有些讲的又不容易理解,我以自己的角度和自己的顺序来好好摸清这些内容。

 

首先澄清3个概念:SSL、TLS、Https。

SSL:Secure Sockets Layer,中文“安全套接层”

TLS:Transport Layer Security,中文“传输层安全协议”,是SSL在1999年标准化后的新名称,基本可以跟SSL做约等号。

HTTPS:Http Over TLS,字面意思就是基于TLS的Http传输。

众所周知Https比Http更安全,从定义中可以看出安全来自于TLS,TLS就是我们要集中力量学习的重点。

SSL/TLS不仅可以被Http over,还可以被其它多种协议Over,比如:FTP、SMTP、POP、Telnet等

问题来了SSL/TLS凭什么更安全?

 

首先我们看看Http协议存在的安全问题:

1 钓鱼被骗,访问伪造的服务端

 

2 明文被捕获,敏感信息泄露

3 明文被捕获后篡改内容

 

4 不管什么报文,重复发起

 

 

由于单纯的Http协议具有上面这些风险,那我们理想中的协议应该具备以下特性:

安全性,防止被偷窥,就是对内容加密,被偷窥了别人也看不懂。

完整性,防止被篡改,要有机制判断内容有没有被篡改过

真实性,防伪造,DNS,网银,防止域名欺骗,防止被钓鱼。

性能,传输的效率损耗不能太大,合理地运用算法。

 

好,要解决以上问题,咱们要靠Http over TLS/SSL来解决了,开始TLS之前需要一些信息安全密码学的基础知识-对称加密和非对称加密,这块篇幅比较多我单独写了一篇,并用Python验证了其中的非对称加密的公式,有兴趣的可以先看下《Python验证RSA非对称加密

有了非对称加密的知识基础后,我们就更好理解其它两个名词:

 

数字签名:用私钥加密,防止内容被篡改

发送报文时,用一个哈希函数从报文文本中生成报文摘要,用自己的私钥进行加密。接收方用公钥进行解密,从而确定该签名(报文摘要)确实是服务端发起的,因为只有它才有私钥。

 

CA证书:互联网中的身份证

向CA申请证书,CA判明身份后会生成一对公钥和密钥,将公钥与申请者的身份信息绑定在一起,进行数字签名后,并形成证书发给申请者。

如果访问者想鉴别这个证书的真伪,只需要用CA公钥对证书签名进行验证即可。

 

散列函数:压缩的保密格式

散列函数为确保信息传输的完整性和一致性,对内容的一种压缩格式。具有压缩性、容易计算、抗修改性、强抗碰撞等特质,常用的有MD5(128bit)和SHA-1(160bit)方式。“压缩”是基于绝大多数的场景来讲,因为当原内容小于128bit进行MD5散列后将会“膨胀”,散列结果的长度是固定的。

散列函数要与前面的对称加密和非对称加密从本质上分开,首先方向上就不同,散列是单项的,没有逆散列获取明文的向量;其次应用场景也不同,加密是为了隐藏明文,散列是为了做完整性和一致性判断;最后性能开销上散列函数比加密解密小得多。

 

有了以上这些知识基础,我们开始正是了解下SSL协议。SSL是一组协议,包括握手协议、记录协议、警报协议。

握手协议:是SSL中最难的一部分,解决的是通信两段如何完成密码的交换。

记录协议:比较好理解,通信中用进行加密和散列,保密性和完整性。

警报协议:以比较好理解,定义了在发现什么样的危险时,进行怎样的应对机制甚至强制断开连接清空密钥。

OK,重中之重就是握手协议了,分阶段来看下。

 

第一阶段:Client和Server两端,互相say hi,并确定沟通的语言

 

如果是新发起的会话,Client送来的sessionId为0,Server会返回一个SessionId;如果是老的会话,Client中送来的SessionId不为0,Server端在缓存中获取与该Client已经确认好的握手协议中所有信息。

密码套件格式如下:SSL_密钥传递方式_加密方式_散列算法,先把密钥如何安全的交换,然后基于各自握有的对方的密钥要如何加密,加密后要如何散列防篡改。

第一阶段双方各提供了一个随机数,留着后面有用。

 

第二阶段:服务器自报家门、提供公钥

 

此阶段有意义的内容主要有2部分,一部分是CA认证,这样Client端收到后将对Server的身份进行进一步认证,防止请求到非法的服务端。一部分是服务端加密公钥,Client后面传递的部分内容要用此公钥加密,第一防止后面敏感信息被偷窥,第二server再次收到返回后用自己的私钥去解密也可以变相的判断Client端的身份是不是第二阶段跟他对话的这个人。

 

第三阶段:客户端鉴别与预备主密钥传递

如果二阶段中服务端有要求Client也证明身份的话,Client在这一阶段会发送证书和证书验证,该阶段Client提供的最重要的内容是“预备主密钥”,并用二阶段中Server提供的公钥加密。暂且认为有了预备主秘密,双方就完成了密钥的交换,如何完成的后面会详细讲解。而目前,只要Server端用它自己的私钥成功解密预备主密钥,双方就都有了密码。

 

第四阶段:确认密码

 

第四阶段相对简单,用第三阶段双方达成的一致做一次加密解密和散列测试,确保两边理解的一样。

 

如何从预备主密钥获得密码内容,其实很简单,但我一开始一只深受困扰,因为一直有个弯没有转过来,网上的资料也没有跟明确的提醒,后来咨询了某某宝的老同事才豁然开朗。我以前纠结的问题是如何从预备主秘密中获取到非对称加密的一组密码,但是我犯了个很大的错误。非对称加密开销很大,在握手后的报文传输中使用的是对称加密,非对称加密只用在握手二三阶段获取报文对称加密的密码。更简单的总结是:最终目的还是对称加密,握手时的非对称加密只是为了传递密码。

有了这个思路,就很好理解网上提供的预备主密钥获取密码的原理图了,先标注下面2个图转自网上资料。

 

Master Secret替换Pre Master Secret放入上面公式中再做一次散列,最终得到

 

2个方向:Client和Server端用不同的密码加密,一方被破解后不会满盘皆输。

加密密钥:做报文的加密,防止偷窥

验证密钥:做报文的散列结果验证,防止篡改。

OK,最后的问题是如何保证预备主秘密每次都是随机的?

虽然各种开发语言都提供了Random函数,但是机器毕竟都是根据算法得来的这些伪随机数,为了让这个伪随机更“逼真”一点,预备主密钥是由3个伪随机数组成的!还记得握手协议第一阶段Client和Server各提供一个随机数吧,Client在第三阶段再提供一个,3个伪随机数组成传给Server的“真随机数”。

 

总结下:握手协议中用到了2-3次非对称加密,Server CA一次、Client CA一次(可选)、预备主密钥一次。

 

 

 

回到最开始http的漏洞和我们对https的期望:

安全性:加密,解决了。

完整性:散列,解决了

真实性:认证和签名,解决了

性能:先非对称加密获取密钥,后面都是对称加密对性能影响不大,解决了。

还剩最后一项隐患,黑客可以不需要理解报文内容捕获报文后重复发送,还是可能存在给自己存几个100W的可能性的,Https怎么解决的呢?SSL在报文传递过程中维护一个时间戳,每个包要包序号,每次来回同向加一,收到重复包序号则认为有人发起重放攻击。黑客也不可能去修改这个包序号,因为报文加密了,他无从下手。

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!