我敢保证, 大多数web开发者对https的核心原理是很模糊的, 许多人都只会使用, 还有一些人都不会上https..
很荣幸, 因为在公司吃得太饱, 我上次上班时候假装花了整整2天时间研究https的工作原理, 没想到最后居然研究出来了... 然后索性向公司的CA机构索要了一份SSL证书, 给某一个内网上了https. 只能说工作的时候留下50%的时间学习是很重要的投资.
其实这篇文章是一个类似读后感的阅读理解, 只是我对于https的回忆中, 想到哪写到哪, 没有具体的框架和思路. 但是我对https的思考思路绝对是与众不同的, 希望这篇文章能给你带来全新的认识.
开始吧....
首先, 我认为HTTPS是软件史上最完美的设计之一.
https从网络层就保证了通讯安全, 而不是应用层! '中间人攻击(man in the middle , mitm)'是https主要的预防对象, 我以前认为, 在运营商网络这么完善的情况, 尤其是中国互联网, 怎么可能有中间人的存在呢?, 甚至用IP地址就能识别谷歌, 百度的情况下为啥要认证?
naive! 因为运营商是不可信的!! 全世界的运营商都不一样, 各自都是独立的企业, 当然不信任, 谁能保证电信运营商不会腐败, 然后hack你? 所以才有'互联网是不安全的信道'这句话. 所以https的设计目标很简单: 世界上2台计算机之间通讯, 认为中间经过的一切网络设备都是malicious middleware的情况下, 我的数据包发出去, 能够让对方确认完整的数据来自于我, 并且数据没有泄露.
也就是说, 无论互联网多么危险, 2台电脑总能保证100%安全通讯, 注意, 是100%.
因为如此, 所有浏览器厂商都认为所有网站都应该上https, 我也是这么认为的. 即使是readonly的网站, 也需要被加密.
https考虑数据安全的2点因素: 读和写
提到网络数据安全, 大家都会听到这3个因素: 对等体认证, 完整性保护, 数据加密;
但其实它们可以归纳为2种: 数据的读和写. 其中, 认证和完整性保护属于防止数据被写, 加密属于防止数据被读.
这样一分类, 是不是对那3个因素的认识清楚了许多? 在任何地方,数据的操作就只有读和写两种, 在http中一样适用.
所以https就是为了解决通讯数据可能被读和写的危险, 当然网络连通性不用担心, 运营商ISP即使再邪恶, 该给你的数据包还是会发给你的.
定下简单的目标: 对称加密就能100%安全
不是吗? 一个加密的zip文件, 设置一个复杂点的密码, 就没人能解开, https连接建立以后对等体之间也是通过对称加密通讯的, 只要你和谷歌共同保存一份唯一的密码, 就能实现安全通讯.
好, 至于怎么实现你们之间保存一份密码, 之后再说, 先说说这样是否就安全了:
对称加密首先保证了数据不被读, 但不被写该如何保证呢?先谈谈认证, 从人的角度看, 只有拥有密码的对等体发来的数据才能解出有意义的数据, 其他人发来的解出来肯定是一堆shit. 完整性保护呢? 大多数情况, 加密数据修改一个bit, 整个数据就会变成乱码, 极少数情况(比如置换对称加密), 比如把数据截一半, 我们也能发现出现断句, 从而判断数据完整性被破坏, 但这样不严谨, 况且机器没有这样的智能来判断. 所以我们设计了一个摘要值作为flag, 放在整个明文数据的后面(或者其他地方, 由协议协商), 然后这个flag就成了数据的一部分, 再将整个数据加密传给对方. 这样一来, 中间人想要既串改数据又修正摘要flag的成功几率比爆破还要低了.
综上所述, https正常通讯的时候是对称加密的, 并不是很多人以为的非对称, 所以,和我一开始的误解不同, https并不慢, 很快!
造成信息丢失的算法: 摘要算法
刚刚提到了摘要算法, 也就是著名的hash家族, 包括md5, sha1等常用算法, 字面上摘要算法(digest)是对源数据的概括, 代表了源数据的唯一性, 实现上是通过取模运算(%)这种造成信息丢失的运算加上一系列变化得到一个固定长度的精简数据,比如:
sha1('test') === 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'
然后, 源数据哪怕修改了1个bit, hash值就会发生翻天覆地的变化.但由于信息丢失, hash过程不可逆, 从物理学的角度还会产生很多热量.
信息不丢失的算法: RSA
之前抛出的问题是, 想要100%安全的对称加密通讯, 该如何安全的交换对称密码呢?这个密码肯定是在通讯的时候交换的, 不可能提前交换好, 不然你的电脑上要内置无数对等体的密码,而且有新的服务器怎么办? 显然不可能, 但是如果只需要保存一份这样的"信条"就好了, 可能吗? 还真可能! 得利用RSA.
这个RSA和hash不同, RSA不会造成信息丢失!!也就是说rsa加密后的数据仍然存在, 之前的hash算法加密后的数据彻底消失了, 连上帝都无法复原, 但是rsa比hash多了一个叫做秘钥的东西, 丢失的数据就藏在公钥或者私钥当中, 如果秘钥丢失, 那数据也就彻底丢失了. 但只要知道私钥或者公钥(上帝可以利用公钥推导出私钥), 数据就依然存在(这个存在并不代表人类可以找得到).
至于RSA具体算法就不说了, 我也没看懂, 我只能从信息守恒定律的角度来理解这个算法, 发明RSA的3个家伙才是天才.
有了非对称加密算法RSA有什么卵用呢?? 可以实现秘钥的重用
当有新机器出现, 我只需要给他自己早已准备好的公钥, 不用再创建一份新的了.
是这样的, 如果世界上n台机器两两通讯, 对称加密需要维护n*(n-1)/2份密码, 而不对称加密只需要n*2份.
如果通讯双方知道了对方的公钥, 利用rsa加密通话也能实现100%安全, 但是rsa加解密实在太慢了,所以需要先在rsa连接下协商出对称加密, 然后再进入对称加密连接的环境, 仍然是100%安全.
所以之前要解决的问题是如何安全的交换对称密码, 现在变成如何安全的交换公钥.
可能有人要问:Are You OK?这不是多此一举吗?
no no no, 看似问题没有变化(都是如何安全交换东西), 但其实其中发生了微妙的变化, 两者要保证的"安全"是截然不同的:
安全交换对称密码需要保证数据的读和写, 但现在交换公钥只需要不被写!!!!
这样一来, 问题的难度大大降低了!! 怎么保证呢?
之前说过, '写' 有关认证和完整性保护, 其实只要认证搞定了, 完整性也就不是问题, 下面主要考虑怎么认证!!
不知道看到这里理解了吗?
全世界共同监督的机构:CA
运营商不靠谱, 也许我们只要求运营商把网络连通性做好就行了, 别无他求.我们需要一个全人类都共同信任的机构:CA(certificate authority/agency). 世界上只有少数几个ca, 而大多数ca都是由Symantec这个顶级ca授权信任的.
我们的电脑在安装操作系统的时候或者安装浏览器的时候都会内置一些ca的公钥证书, 也叫根证书/自签名证书, 这些都是已经默认被信任的.根证书是整个信任链的根节点,由它可以向下信任别的证书. 当谷歌的证书送达你的时候, 会根据签名, 用相关的ca证书(公钥)来解析这个证书, 成功后即可知道某个服务商的公钥了, 这个服务商的唯一标识符或者说ID通常是他的域名, 如果域名与你请求的地址一致则告诉你, 服务器认证成功, 浏览器的https认证过程是这样子的:
刚刚我们只是客户端对服务器的单向认证, 而图中却说客户端随机生成一个rsa公私钥对, 直接发给服务器, 没有使用第三方的CA, 这是什么原因呢? 因为服务器不需要认证客户端:服务器通常都是来者不拒的, 不需要知道你是谁, 你也没有域名(为什么不配有姓名..)!即使如果这个时候因为数据没有'写'的保护而被攻击, 最终也会造成网络连通原因, ISP就要负责了.所以单向认证是安全的.
事实上, 不对称加密算法的应用场景是提供一个虚拟的第三方验证, 实现双方的直接信任建立. 手机离线支付, 线下刷卡也是这个道理.
网络层安全的最后一步:DNS over TLS
我们向ca申请证书的时候,需要证书颁发机构对网站企业身份和域名所有权进行审核,从而以证明申请单位是一个合法存在的真实实体, 然后用ca自己的私钥给你的common name(你的域名或者通配符)和你的公钥一起打包生成一个SSL证书, 证书的内容除了域名, 公钥, 还有有效期, ca签名等. 同域名一样, ssl证书也是要付费的.
但是你的域名如何安全的转成你的IP呢, 这不用你烦了, dns会保证你的安全.
同CA一样, dns服务器也受到所有人的信任, 但以前dns请求也是明文, 同样也会受到中间人攻击比如dns劫持. 虽然dns被攻击带来的危害很小, 但是它仍然是网络层上的一个风险,比如 ISP可以监控你的浏览痕迹(虽然ISP自己也提供dns服务...).
我们当然要去除这个风险.方法就是上SSL, 这里使用了和ssl类似的概念叫TLS,事实上,TLS over TLS在RFC中早就被指定。它要求所有DNS数据都通过TLS端口传输。使用TCP快速打开时,必须立即启动TLS握手。
至此, 整个tcp层到应用层的安全连接全部建立完毕.
比session更长久的连接:用户账户
为了使连接更长久, 通常需要建立长连接. cookie-session机制是一个办法,对称密码就存储在session中. 但session设计的目标是一个临时的长会话, 做不到永久存储. 所以各个网站才会设计用户账户的注册和维护机制, 不过并不是https的长连接, 只是为了再次认证.
连接的本质就是让服务器知道"这次请求和上次是同一个人"
总结
理论上, 有了https, 用户数据无需任何应用层的加密;
https = http + ssl
理论上任何网站应该上ssl(从HSTS的出现可以看出)
不对称加密可以实现虚拟化