本文试图一步步还原HTTPS的设计过程,理解为什么HTTPS最终会是这个样子。但这并不代表HTTPS真正的设计过程。阅读本文时,您可以尝试放下对HTTPS的现有理解,这样更有利于“还原”过程。先不说HTTP和HTTPS。让我们从一个聊天软件开始。我们要实现A可以给B发hello消息:如果我们要实现这个聊天软件,本文只考虑安全问题。实现:A发送给B的hello消息包即使被中间人截获,也无法获知消息内容。如何做到真正的安全,很多人第一时间想到各种加密算法,对称加密,非对称加密,DES,RSA,XX,噼里啪啦~还有我想说的是,加密算法只是解决方案,首先要做到最重要的重要的是要了解我们的问题领域——什么是安全?我个人的理解是:A和B交流内容,只有A和B有能力看到交流的真实内容。好了,问题域已经定义好了(当然现实中的定义不止一种)。对于解决方案,很容易想到对消息进行加密。题外话,但这是唯一的方法吗?我不这么认为,也许未来会有一种物质,打破现在世界的通讯假设,实现真正的保密。对于A和B这种简单的通信模型,我们很容易做出选择:这就是对称加密算法,图中的密钥S同时起到加密和解密的作用。具体细节超出了本文的范围。只要密钥S不泄露给第三方,并且密钥S足够安全,我们一开始设定的问题域就已经解决了。因为世界上只有A和B知道如何加密和解密它们之间的消息。然而在WWW环境下,我们的Web服务器的通信模型就没有那么简单了:如果服务器对所有的客户端通信都使用同一种对称加密算法,就等于没有加密。那我们该怎么办呢?也就是说,我们可以在不公开密钥的情况下使用对称加密算法吗?要求读者思考21秒。答案是:Web服务器和每个客户端使用不同的对称加密算法:但是,你协商的过程是不加密的,不然会被中间人拦截。那么我们就可以对这个协商过程使用对称加密,那么协商过程的加密不加密怎么办呢?再不加密就好了……嗯,这是先有鸡还是先有蛋的问题。如何加密谈判过程一个新的问题来了,如何加密谈判过程?在密码学领域,有一种加密算法叫做“非对称加密”,其特点是用私钥加密的密文,只要是公钥,都可以解密,但是用私钥加密的密文公钥只能用私钥解密。只有一个人拥有私钥,但公钥可以分发给所有人。虽然从服务器到A、B……的方向还是不安全,但至少从A、B到服务器的方向是安全的。好了,我们已经解决了如何协商加密算法的问题:使用非对称加密算法进行对称加密算法的协商过程。现在,你明白为什么HTTPS既需要对称加密算法又需要非对称加密算法了吗?应该协商什么加密算法,让web服务器对每个client使用不同的对称加密算法,同时我们不能让第三方知道这个对称加密算法是什么,怎么办?使用随机数是指使用随机数生成对称加密算法。这样,服务端和客户端的每一次交互都是一个新的加密算法,加密算法只有在交互的那一刻才确定。现在,你明白为什么HTTPS协议的握手阶段会有那么多随机数了吧。如何获取公钥细心的人可能已经注意到,如果使用非对称加密算法,我们的客户端A和B需要从一开始就持有公钥,否则无法进行加密。现在,我们又遇到了一个新的问题:如何让A、B客户端安全的拿到公钥呢?我能想到的解决方案只有这些:1:服务器将公钥发送给每个客户端2:服务器将公钥发送给每个客户端公钥放在远程服务器上,客户端可以请求我们选择方案一,因为方案二多了一个要求,公钥的放置问题需要额外处理。公钥被切换怎么办?又一个先有鸡还是先有蛋的问题?但是方案一有个问题:服务端把公钥发给客户端,被中间人切换怎么办?我画了一张图通俗易懂:显然让每个客户端的每个浏览器都默认保存所有网站的公钥是不现实的。使用第三方机构的公钥解决先有鸡还是先有蛋的问题。公钥被中转的问题是因为我们的客户端分不清返回公钥的人是中间人还是真正的服务器。这其实就是密码学中提出的身份验证问题。如果让你解决,你是怎么解决的?如果你了解HTTPS,你就会知道使用数字证书来解决它。但是你有没有想过证书的本质是什么?请抛开您现有的HTTPS知识,尝试自己寻找解决方案。我是这样解决的。既然服务端需要把公钥传给客户端,这个过程本身就是不安全的,那我们为什么不把这个过程本身再加密一次呢?但是,您使用对称加密还是非对称加密?这很好,我觉得鸡和蛋的问题来了。问题的难点在于,如果我们选择直接将公钥传递给客户端的方案,仍然无法解决中间人传递公钥的问题。所以,我们不能直接把服务器的公钥传给客户端,而是有第三方机构用它的私钥加密我们的公钥,然后传给客户端。然后客户端使用第三方机构的公钥解密。下图是我们设计的“数字证书”的第一个版本。证书中只有服务器交给第三方机构的公钥,而这个公钥是用第三方机构的私钥加密的:如果能解密,就说明公钥key不被中间人分包。因为如果中间人用自己的私钥加密一些东西传给客户端的话,客户端是不能用第三方的公钥解密的。至此,我以为问题解决了。但实际上,HTTPS也有数字签名的概念。我无法理解它的设计原因。原来我漏掉了一个场景:第三方机构不可能只为一家公司出具证明,也有可能给中间商等居心不良的公司出具证明。这样中间商就有机会打包你的证书了。在这种情况下,客户端无法判断它是在接收您的证书还是中间人的证书。因为中间人和你的证书都可以用第三方机构的公钥来解密。像下面这样:一个第三方机构向多个公司颁发证书的情况:客户端可以解密同一个第三方机构颁发的所有证书:最终持有同一个第三方机构证书的其他中间人可以交换包:数字签名要求要解决这个问题,我们首先要想清楚一个问题,我们应该把区分不同证书的责任放到同一个组织下呢?它只能放在客户端上。这意味着客户端在获得证书后,具有辨别证书是否被篡改的能力。我们怎样才能有这个能力呢?我们从现实中寻找灵感。例如,如果您是HR,您将获得候选人的学历证书。证书包括证书持有人、发证机构、发证时间等,证书上写着最重要的:证书编号!我们如何识别它?这个证书是真是假?拿着这个证件号码去相关机构核对一下,如果证件上的持有人和实际考生一致,证件号码也能对应,那就说明证件是真的。我们的客户可以采用这种机制吗?像这样:可是这个“第三方机构”在哪里呢?是远程服务吗?不可能的?如果是远程服务,整个交互会比较慢。所以这个第三方机构的验证功能只能放在客户端本地。客户端如何在本地验证证书?客户端如何在本地验证证书?答案是证书本身已经告诉客户端如何验证证书的真伪了。即证书说如何根据证书的内容生成证书编号。客户端收到证书后,根据证书上的方法自行生成一个证书号。如果生成的证书编号与证书上的证书编号相同,则表示该证书是真实的。同时,为了避免证书号本身被再次打包,使用了第三方私钥进行加密。这个地方有点抽象,我们来一张图帮助理解:证书的制作如图所示。证书中的“编号生成方法MD5”是告诉客户:可以用MD5对证书内容进行评估,得到一个证书编号。客户端拿到证书后,开始验证证书中的内容。如果客户端计算出的证书号与证书中的证书号相同,则验证通过:但是第三方机构的公钥是怎么到客户端机器上的呢?在哪里?世界上有那么多机器。事实上,在现实中,浏览器和操作系统都维护着一份权威第三方组织的列表(包括他们的公钥)。因为发证机构会写在客户端收到的证书中,客户端会根据发证机构的值在本地找到对应的公钥。说到这里想必大家都知道上面说的什么,证书就是HTTPS中的数字证书,证书号就是数字签名,第三方机构就是指数字证书颁发机构(CA)。CA是如何向服务器颁发数字证书的?听到这个问题,我误以为我们的服务器需要向CA部门的服务器发送网络请求来获取证书。到底是我理解问题的能力,还是。.其实问题应该是CA是怎么发给我们网站管理员的,我们管理员是怎么把这个数字证书放到我们服务器上的。我们如何申请CA?每个CA组织都是相似的。在网上找了一个:拿到证书后,我们就可以在自己的服务器上配置证书了。那么如何配置呢?这是具体的细节,留给你去google。也许我们需要理清思路。我们尝试通过计算来还原HTTPS的设计过程。这样我们也就明白为什么HTTPS的交互比HTTP多那么多,为什么HTTPS的性能差,找到HTTPS的性能优化点。而上面的很多工作都是为了让客户端和服务端安全的协商一个对称加密算法。这就是HTTPS中的SSL/TLS协议主要做的事情。剩下的就是双方在通信过程中使用这种对称加密算法进行加密和解密。下面是HTTPS协议的真实交互图(从网上抄来的,忘记出处了,如有侵权请告知):能用一句话总结一下HTTPS吗?答案是否定的,因为HTTPS本身就太复杂了。但是我还是尝试用一段话来总结一下HTTPS:HTTPS必须使用对称加密算法来保证客户端和服务端通信过程的安全,但是协商对称加密算法的过程需要使用非对称加密保证安全的算法。直接使用非对称加密的过程本身是不安全的,并且存在中间人篡改公钥的可能,所以客户端和服务端不直接使用公钥,而是使用数字证书颁发机构颁发的证书权限保证非对称加密过程本身的安全。这样,通过这些机制协商出一个对称加密算法,双方使用这个算法进行加密和解密。从而解决了客户端与服务器端的通信安全问题。
