HTTPS网站相信对很多工程师来讲并不陌生,各大Web服务器产品都提供了详细的配置方案,搭建起来也并不很难。但要说出其中的安全原理,却不是件容易的事。今天我们就来谈一谈它后面的密码学原理,希望通过这篇文章,大家能够真正了解掌握相关的安全技术。强烈建议您读这篇文章下面的内容之前,先看一下之前关于非对称加密、数字签名、数字证书的文章,做为相关知识储备。
我们谈HTTPS的安全,实际上是谈SSL的安全,因为HTTPS实质就是HTTP+SSL。而其实SSL也不是完全准确的说法,因为作为协议的SSL(Secure Sockets Layer 安全套接层)已经及其继任者TLS协议(Transport Layer Security传输层安全)取代了。习惯使然,我们仍把这一套相关技术叫做SSL。SSL将非对称加解密、数字签名、数字证书等核心PKI技术应用在网络通信的传输层,实现了服务器/客户端认证和数据加密,保证了网络中传输数据的安全。
先介绍一下应用最广的服务器认证。服务器认证也叫单向认证,即客户端浏览器访问HTTPS网站时,先要对网站的真实性进行认证,认证通过后,客户端与网站之间的数据交换以密文形式进行。具体的认证过程,不是本文的重点,因为你在其他很多介绍SSL的文章上都可以看到详细的描述。本文重点是它的密码学原理,先看下图。
这张图画出了单向认证的核心过程。认证时,网站服务器先将自己的服务器证书发送给客户端,客户端收到证书后进行以下四项检查:
· 证书是否过期就是检查当前时间是否在证书有效期内;
· 证书是否由可信任CA颁发在数字证书那一篇里介绍过;
· 证书是否被吊销就是指当前证书是不是已经被颁发它的CA吊销了。客户端检查证书是否吊销有CRL和OCSP两种方法。CRL即证书吊销列表,里面有CA已经吊销了的证书集合,客户端通过检查CRL就可以判断证书是否被吊销。CRL是可以根据一定的算法更新的。OCSP是在线证书状态检查协议,客户端直接向证书签发机构发起查询请求以确认该证书是否有效;
· 证书主题(持有人)名称中的域名与你要访问网站的域名是否一致。
如果上面四项有任何一项检查结果为否,浏览器就会给出相关警告提示,如下图是颁发证书的CA不被信任时的提示。
而这是网站域名与证书持有人的名称不一致的情况。注意,这里并不要求持有人的名称和网站名称一致,而是指持有人的域名和完整域名一致。
一旦出现了这些警告,浏览器都会强烈建议用户不要继续访问(当然Chrome比IE更强烈,下图是IE打开同一个网站的提示,请细品个中的不同),
但最终要不要继续访问,决定权还在用户手里。因此,客户端验证服务器证书这一步,实际上是由客户端浏览器检查和用户自行判断共同完成的。很多人在学习SSL时总问验证服务器证书这一步是怎么验证的,其实就是由用户自己人工完成的,我们也可以叫它"人肉验证"。你如果无视这些警告,继续访问,就表明你已经认同了这张服务器证书,也就等于认同了这个网站。相信很多人和我以前一样,遇到这样的警告都是马上找继续访问的按钮,基本不看到底警告了什么。如果自己开发的业务系统这样做问题不大,但要是在互联网上访问第三方的网站,遇到这样的警告还是要小心谨慎,一定要确保真的没问题才可以访问。很多中间人攻击就是利用了用户这种麻痹大意的心理得手的。
完成了服务器证书验证最重要的一步后,下面的工作就是水到渠成了。客户端会生成一个随机数作为生成对称密钥的数据,叫预主密钥,然后用服务器证书的公钥加密这个密钥,并把这个加密的密钥传送给服务器,服务器用自己的私钥解密。客户端与服务器根据相同的预主密钥计算出对称密钥(其实这一步还有其他随机数参与,这里就不再展开了),双方使用对称密钥加密发送的数据,解密接收的数据,最终建立了网络传输的安全通道。
在服务器认证的基础上,SSL支持对客户端的认证,这样单向认证就变成了双向认证。实现双向认证要先做一个准备工作:用户需要先将其证书登记在服务器的证书信任库或数据库中,并与被授权访问服务器的用户账户绑定。
与单向认证相比,红色步骤就是双向认证增加的部分。客户端会进行对数据的签名,在TLS协议中这个生成签名的数据是之前的握手信息,然后把签名结果(包括用户证书)和加密的随机数一起发送给服务器。服务器收到后,要验证签名后及用户的证书。这个验证过程除了有效期、是否被吊销以及颁发CA是否被可信外,还需要在服务器的证书信任库或数据库里进行对比,以确定当前用户的身份。验证通过后,再按照单向认证的步骤解密随机数,生成对称密钥。在实际使用时,浏览器会弹出窗体让用户选择要发送的证书,如下图。如果证书是用USBKey载体,则会弹出输入口令对话框,完成数字签名。这就是双因素认证。
上述双向认证过程可能和有些网上文章描述的不同,那些文章描述的是在双向认证中,客户端直接把自己的证书发送给服务器,而不是签名,之后服务器先用客户端公钥加密服务器选定的对称加密方案,客户端收到后使用私钥解密得到。上述描述应该是之前SSL协议的内容,并不是现在TLS协议的双向认证过程。
SSL的优点在于配置相对简单,应用层改动很小。如果是单向认证,你的网站甚至不用改一行代码,配置服务器即可,因为它作用在传输层,对应用层来讲是透明的。但也正是因为这样,使用SSL的HTTPS也有以下缺点:
多次握手协议和传输数据的加解密会带来网页访问速度变慢,网络资源消耗增大;
使用界面(如客户端认证时的证书选择的对话框)无法与应用层的界面保持一致,影响用户浏览体验;
在网页中不能引用其他非安全资源,说白了就是不能嵌入http协议的链接。这并不是跨域的问题,而是浏览器认为不安全。不过,如果访问的是本地资源,比如,大部分浏览器是认为没问题的;
SSL证书需要花钱。虽然你自己也可以签发一个SSL证书做服务器认证,技术上和那些大厂SSL证书没有任何区别。但自己签发证书的CA是不被信任的,你也不可能一个个通知用户去手动把签发CA的根证书装到信任颁发机构里。所以,使用windows已经预装的那些受信任根CA或它们的分支机构签发的SSL证书是普遍的选择。SSL证书按年收费,费用在每年几百元到几千元不等。具体使用哪一种证书,要看网站的定位;
早期的SSL1.0、SSL2.0都有漏洞,相信做过平台漏扫的同学对此都不陌生;
另外有些观点认为SSL不能隐藏用户隐私信息,不能认证用户真实身份。我个人认为这并不是SSL做的事,这是应用层的问题。总之,使用基于SSL的HTTPS,能够有效地降低传输数据被窃取的风险,增加网站被中间人劫持攻击的难度。各位老铁,能用还是都用了吧。