多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
首先介绍两种加密体系: * 对称加密 * 非对称加密 对称加密只有一个密钥,用密钥加密的数据,用该密钥也能解密。 非对称加密中有一对密钥,一个叫私钥,一个叫公钥。用私钥加密的数据只能用对应的公钥解密,私钥自已本身也无法解密。用公钥加密的数据只能用私钥解密,公钥自已本身也无法解密。 然后,这里有一个CA的概念。CA即证书认证机构,它有一对密钥(非对称加密),假设私钥叫ca.private,公钥叫ca.public(现实中叫根证书,根证书中包含了公钥)。 当某公司想要提供HTTPS服务时,它首先生成自已的一对密钥(server.private,server.public)以及一个证书签名请求文件server.csr(注意,证书请求文件中包含了服务器公钥、域名等信息)。然后把server.csr提交给CA,CA使用自已的私钥对该文件进行数字签名(即用私钥进行加密),生成数字证书server.crt,并返还给公司,该证书只能被CA的公钥解密。CA的公钥是公开的,任何人都可以拿到。然后,公司就可以使用server.private与server.crt起一个HTTPS服务。 那么接下来我们来看HTTPS中客户端与服务端的交互流程,如图所示 ![](https://img.kancloud.cn/bd/bd/bdbd0c23955670453de5164696ef6353_621x449.png) **Step1:** 客户端向服务端发起HTTPS连接请求 **Step2:** 服务端把数字证书server.crt发送给客户端 **Step3:** 客户端收到服务端的数字证书后,使用ca.public解密,得到服务端的公钥server.public,并且验证解密出来的域名是否是自已想访问的服务端的一致。`特别注意:客户端会验证server.crt中的域名是否与https://abc.com的域名是否一致` **Step4:** 客户端随机生成一个密钥(对称加密的密钥),并通过server.public进行加密,然后发送给server **Step5:** 服务端收到加密的密钥后,使用server.private解密,得到对称加密的密钥。此时,客户端和服务端都有了对称加密密钥 **Step6:** 客户端和服务端使用对称加密的密钥对自已要发送的数据加密,另一方通过对称加密的密钥对接收到的数据进行解密 上面的流程已经很接近真实的HTTPS,如果只是大概了解HTTPS的原理,已经差不多了。不过在Q&A中,提了几个问题。 ### **Q & A** Q: 为什么CA的根证书不直接使用其公钥? A:公钥只用于加密与解密。在根证书中还有CA的名称,域名,该证书的有效期等信息。 Q: 在Step3中,当客户端收到服务端证书server.crt后,如果证明这个证书就是服务器发给自已的,即如何证明与自已正在通信的就是服务器? A:的确,服务器的证书谁发个请求都能拿到。客户端为了防止与自已通信的不是真正的服务器,当拿到服务器的证书后,提取出公钥,然后发一串字符给服务器,让服务器用私钥加密;客户端拿到加密后的内容,再用提取出来的服务器公钥解密,解密出来和自已发的内容一样,说明正在通信的的确是服务器。 Q: 在第二步,当服务器收到客户端的请求时,为什么不会验证请求的域名(https://abc.com中的abc.com)是否与自已server.crt中的域名一致?在第三步,客户端为什么又会验证server.crt中的域名与自已请求的域名一致? A:先回答第二个问题:假设这样一个场景,客户端本来想访问`https://www.baidu.com`,结果中间被不法分子把请求包转发到了`https://www.google.com`,而这两个服务器的server.crt都是被第三方证书签署的,所以如果客户端不验证server.crt的域名,那么实际上访问的却是google。 第一个问题,暂时不知道怎么解释,不过现实中的现象的确是这样:即使server.crt中只有域名`server.com`,但我们通过 `curl -k https://x.x.x.x` 也能访问成功。