女友也是软件工程专业,由于快要毕业了,最近一边作毕设一边学习编程。前两天她问我 HTTPS 的问题,原本想直接扔一篇网上的教程给她。后来想了一下,那些文章大多直接介绍概念, 对新手不太友好,因而我干脆亲自给她解释一下,顺便整理了一份问答录。html
HTTP 协议中的内容都是明文传输,HTTPS 的目的是将这些内容加密,确保信息传输安全。最后一个字母 S 指的是 SSL/TLS 协议,它位于 HTTP 协议与 TCP/IP 协议中间。git
很遗憾的是,目前的 HTTP 协议还不知足上述三条要求中的任何一条。github
是的,我没开玩笑,你能够暂时别管第三个要求,由于它实际上隶属于第一个需求。咱们都知道加密须要密码,密码不是天下掉下来,也得须要双方通过通讯才能协商出来。因此一个设计良好的加密机制必然会防止第三者的干扰和伪造。等搞明白了加密的具体原理,咱们天然能够检验是否知足:“任何第三者没法冒充服务器”这一要求。算法
对称加密能够理解为对原始数据的可逆变换。好比 Hello
能够变换成 Ifmmp
,规则就是每一个字母变成它在字母表上的后一个字母,这里的秘钥就是 1
,另外一方拿到 Ifmmp
就能够还原成原来的信息 Hello
了。编程
引入对称加密后,HTTPS 的握手流程就会多了两步,用来传递对称加密的秘钥:后端
1
。提到了对称加密,那么天然还有非对称加密。它的思想很简单,计算两个质数的乘积很容易,但反过来分解成两个质数的乘积就很难,要通过极为复杂的运算。非对称加密有两个秘钥,一个是公钥,一个是私钥。公钥加密的内容只有私钥能够解密,私钥加密的内容只有公钥能够解密。通常咱们把服务器本身留着,不对外公布的密钥称为私钥,全部人均可以获取的称为公钥。浏览器
使用对称加密通常要比非对称加密快得多,对服务器的运算压力也小得多。安全
服务器直接返回明文的对称加密密钥是否是不安全。若是有监听者拿到这个密钥,不就知道客户端和服务器后续的通讯内容了么?服务器
是这样,因此不能明文传递对称秘钥,并且也不能用一个新的对称加密算法来加密原来的对称秘钥,不然新的对称秘钥一样没法传输,这就是鸡生蛋、蛋生鸡的悖论。函数
这里咱们引入非对称加密的方式,非对称加密的特性决定了服务器用私钥加密的内容并非真正的加密,由于公钥全部人都有,因此服务器的密文能被全部人解析。但私钥只掌握在服务器手上,这就带来了两个巨大的优点:
因此传输对称秘钥的问题就迎刃而解了: 秘钥不是由服务器下发,而是由客户端生成而且主动告诉服务器。
因此当引入非对称加密后,HTTPS 的握手流程依然是两步,不过细节略有变化:
你好像仍是没有解决鸡生蛋,蛋生鸡的问题。你说客户端发送请求时要用公钥加密对称秘钥,那公钥怎么传输呢?
每个使用 HTTPS 的服务器都必须去专门的证书机构注册一个证书,证书中存储了用权威机构私钥加密的公钥。这样客户端用权威机构的公钥解密就能够了。
如今 HTTPS 协议的握手阶段变成了四步:
那权威机构的公钥又怎么传输?
这个公钥不用传输,会直接内置在各大操做系统(或者浏览器)的出厂设置里。之因此不把每一个服务器的公钥内置在电脑里,一方面是由于服务器太多,存不过来。另外一方面操做系统也不信任你,凭什么你说你这个就是百度/淘宝的证书呢?
因此各个公司要先去权威机构认证,申请证书,而后操做系统只会存储权威机构的公钥。由于权威机构数量有限,因此操做系统厂商相对来讲容易管理。若是这个权威机构不够权威,XJB 发证书,就会取消他的资格,好比可怜的沃通。。。。
你说服务器第一次会返回证书,也就是加密之后的公钥,那我怎么知道这个证书是可靠的?
咱们都知道哈希算法的特色,它能够压缩数据,若是从函数角度来看,无论多复杂的数据(定义域能够很是大)通过哈希算法都会获得一个值,并且这个值处在某个特定(远小于定义域的范围)值域内。相同数据的哈希结果必定相同,不相同数据的哈希结果通常不一样,不过也有小几率会重复,这叫哈希冲突。
为了确保原始证书没有被篡改,咱们能够在传递证书的同时传递证书的哈希值。因为第三者没法解析数据,只能 XJB 改,那么修改后的数据在解密后,就不可能经过哈希。
好比说公钥就是以前的例子 Hello
,咱们假设哈希算法是获取字符串的最后一个字符,那么 Hello
的哈希值就是 o
,因此加密字符串是 Ifmmpp
。虽然公钥已知,每一个人均可以解密,解密完也能够篡改,可是由于没有私钥, 因此没法正确的加密。因此它再返回给客户端的数据是无效数据,用公钥解析后会获得乱码。即便攻击者经过屡次尝试碰巧可以解析,也没法经过哈希校验。
首先真正的服务器下发的内容,没法被别人篡改。他们有权威机构的公钥,因此能够解密,可是由于没有私钥,因此解密之后的信息没法加密。没有加密或者错误加密的信息被客户端用公钥解密之后,必然没法经过哈希校验。
可是,若是你一开始请求的就不是真的服务器,而是一个攻击者,此时的他彻底有机会进行中间人攻击。咱们知道第一次握手的时候服务器会下发用于证实本身身份的证书,这个证书会用预设在设备上的公钥来解密。因此要么是通过认证的证书用权威机构的私钥加密,再用权威机构解密,要么是用非权威机构的私钥加密,而后找不到公钥解密。
因此若是不当心安装过非权威机构的根证书,好比黑客提供的恶意证书,这时候设备上就多了一个预设的公钥,那么用恶意私钥加密的证书就能被正常解析出来。因此千万不要随便装根证书,这等因而为那些恶意证书留了一扇门。
固然,凡是都有两面性。咱们知道 Charles 能够调试 HTTPS 通讯,它的原理就是须要用户安装 Charles 的根证书,而后咱们的请求会被代理到 Charles 服务器,它下发的 Charles 证书才能被正确解析。另外一方面,Charles 会做为客户端,从真正的服务器哪里拿到正确的 https 证书并用于后续通讯。幸亏 Charles 不是流氓软件,或者它的私钥一旦泄露,对用户都会形成很大的影响。
我能够举一个例子,证书有多个种类,最贵的叫 EV (Extended Validation),它须要公司营业执照等多个文件才能申请人工审核,好处也很明显,能够在浏览器地址栏左侧准确显示公司名称,好比 Bitbucket 的官网:
这是客户端直连时候的正常现象。但若是你用 Charles 代理,客户端拿到的是 Charles 证书,因此会变成:
TCP 有三次握手,再加上 HTTPS 的四次握手,会不会影响性能?
首先,HTTPS 确定会更慢一点,时间主要花费在两组 SSL 之间的耗时和证书的读取验证上,对称算法的加解密时间几乎能够忽略不计。
并且若是不是首次握手,后续的请求并不须要完整的握手过程。客户端能够把上次的加密状况直接发送给服务器从而快速恢复,具体细节能够参考 图解SSL/TLS协议。
除此之外,SSL 握手的时间并非只能用来传递加密信息,还能够承担起客户端和服务器沟通 HTTP2 兼容状况的任务。所以从 HTTPS 切换到 HTTP2.0 不会有任何性能上的开销,反却是得益于 HTTP2.0 的多路复用等技术,后续能够节约大量时间。
若是把 HTTPS2.0 当作目标,那么 HTTPS 的性能损耗就更小了,远远比不上它带来的安全性提高。
相信以上九个问题足够帮助新人了解 HTTPS 了,但这只是基本概念,关于 HTTPS 的使用(好比 iOS 上的一些具体问题)还须要不断尝试和研究。
文章最后打一个求职广告,长期有效,女友今年毕业,考研 380+,简历戳这里,计算机基础还算扎实,但项目经验偏少,能够实习 6 个月以上。北京地区若是有想要招实习生的公司,欢迎联系我,方向不限,先后端皆可培养,iOS 更好(我本身教)。