当前位置: 首页 > 后端技术 > PHP

【转载】这是我看到的对HTTPS最好的理解

时间:2023-03-30 05:08:09 PHP

[转载]这是我看到的对HTTPS最好的理解首先声明,本文非原创。但是最近想研究一下https的原理,于是在网上查了很多资料和文档。事实上,在我找到这篇文章之前,它们似乎几乎是一样的。先给作者打个电话吧~原始出处:http://blog.jobbole.com/110354/摘要:本文试图一步步还原HTTPS的设计过程,理解为什么HTTPS最终会是这个样子。但这并不代表HTTPS真正的设计过程。阅读本文时,您可以尝试放下对HTTPS的现有理解,这样更有利于“还原”过程。先不说HTTP和HTTPS,先从一个聊天软件说起,我们要实现A可以给B发hello消息:如果要实现这个聊天软件,本文只考虑安全问题,需要实现A可以向B发送hello消息,即使hello消息包被中介截获,也不可能知道消息的内容。怎样才能真正安全?对于这个问题,很多人第一时间就想到了各种加密算法,对称加密、非对称加密、DES、RSA、XX、噼里啪啦~不过我想说的是,加密算法只是解决方案。我们需要做的第一件事是了解我们的问题域——什么是安全性?我个人的理解是:A和B之间的通讯内容,只有A和B有能力看到真正的通讯内容。好了,问题域已经定义好了(当然现实中的定义不止一种)。对于解决方案,很容易想到对消息进行加密。题外话,但这是唯一的方法吗?我不这么认为,也许未来会出现一种材料,打破当今世界的通信假设,实现真正的保密。对于A和B这种简单的通信模型,我们很容易做出选择:这是一种对称加密算法,其中图中的密钥S同时起到加密和解密的作用。具体细节超出了本文的范围。只要密钥S不泄露给第三方,并且密钥S足够安全,我们一开始设定的问题域就已经解决了。因为世界上只有A和B知道如何加密和解密它们之间的消息。然而在WWW环境下,我们的Web服务器的通信模型就没有那么简单了:如果服务器对所有的客户端通信都使用同一种对称加密算法,就等于没有加密。那我们该怎么办呢?可以在不公开密钥的情况下使用对称加密算法吗?答案是:Web服务器和每个客户端使用不同的对称加密算法:如何确定对称加密算法?等等,又一个问题来了,我们的服务端如何告诉客户端使用哪种对称加密算法呢?当然是通过谈判。但是你协商的过程是没有加密的,还是会被中间人截取的。那么我们可以重新加密协商过程,那么协商过程的加密加密不加密怎么办呢?加密是不够的。好吧,关于先有鸡还是先有蛋的问题。如何加密谈判过程?新的问题来了,如何加密谈判过程?在密码学领域,有一种加密算法叫做“非对称加密”,其特点是用私钥加密的密文只要是私钥对应的公钥就可以解密;但是用公钥加密的密文,只有这个公钥对应的私钥才能解密。只有一个人拥有私钥,但公钥可以分发给所有人。虽然从服务器到A、B……的方向还是不安全,但至少从A、B到服务器的方向是安全的。好了,我们已经解决了如何协商加密算法的问题:使用非对称加密算法进行对称加密算法的协商过程。现在,你明白为什么HTTPS需要对称和非对称加密算法了吗?协商什么加密算法?为了实现web服务器对每个客户端使用不同的对称加密算法,同时又不能让第三方确定什么是对称加密算法,我们应该怎么做呢?使用随机数是指使用随机数生成对称加密算法。这样,服务端和客户端的每一次交互都是一个新的加密算法,加密算法只有在交互的那一刻才确定。现在,你明白为什么HTTPS协议的握手阶段会有那么多随机数了吧。如何获得公钥?细心的人可能已经注意到,如果使用非对称加密算法,我们的客户端A和B需要从一开始就持有公钥,否则无法进行加密。现在,我们又遇到了一个新的问题,如何让A、B客户端安全的拿到公钥呢?选项1.服务器将公钥发送给每个客户端。选项2.服务器将公钥放在远程服务器中。客户端可以请求它。我们选择Option1,因为Option2多了一个request,另外一个Handles就是放公钥的地方。公钥泄露怎么办?又一个先有鸡还是先有蛋的问题?但是方案一有个问题:服务端把公钥发给客户端,被中间人丢了怎么办?原理如下:显然,每个客户端的每个浏览器都默认保存所有网站的公钥是不现实的。使用第三方机构的公钥解决先有鸡还是先有蛋的问题。公钥被丢弃的问题是因为我们的客户端无法分辨返回公钥的人是中间人还是真正的服务器。这其实就是密码学中提到的认证问题。如果让你解决,你会怎么解决?如果你了解HTTPS,你就会知道使用数字证书来解决它。但是你想过证书的本质吗?请抛开您现有的HTTPS知识,尝试自己寻找解决方案。我是这样解决的。既然服务端需要把公钥传给客户端,这个过程本身就是不安全的,那我们为什么不把这个过程本身再加密一次呢?但是,您使用的是对称加密还是非对称加密?那么现在,我觉得我离鸡和蛋的问题越来越近了。问题的难点在于,如果我们选择直接将公钥传递给客户端的方案,仍然无法解决公钥被中间人丢弃的问题。所以,我们不能直接把服务器的公钥传给客户端,而是有第三方机构用它的私钥加密我们的公钥,然后传给客户端。然后客户端使用第三方机构的公钥解密。下图是我们设计的第一版“设计证书”。证书中只有服务器交给第三方机构的公钥,而这个公钥是用第三方机构的私钥加密的:如果能解密,就是公钥没有被中间人丢弃。因为中间人如果用自己的私钥加密东西传给客户端的话,客户端是不能用第三方的公钥解密的。说到这里,我以为问题解决了。但实际上,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在客户端和服务端的通信过程中必须使用对称加密算法来保证安全,但是协商对称加密算法的过程需要使用非对称加密算法以确保安全。但是直接使用非对称加密的过程本身并不安全,并且存在中间人篡改公钥的可能,所以客户端和服务端不直接使用公钥,而是使用数字证书签发的证书发证机构保证非对称加密过程自身的安全。这样,通过这些机制协商出一个对称加密算法,双方使用这个算法进行加密和解密。从而解决了客户端与服务器端的通信安全问题。这是一个很长的句子。以上文字,纯手打,也加深了我对HTTPS的理解。