侧边栏壁纸
博主头像
lance

不为失败找借口,只为成功找方法。

  • 累计撰写 28 篇文章
  • 累计创建 0 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

为什么用公钥加密却不能用公钥解密.md

lance
2025-05-11 / 0 评论 / 1 点赞 / 89 阅读 / 2,731 字
温馨提示:
本文最后更新于 2025-05-11,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

HTTPS 的加密原理

如果你在公司内网里做开发,并且写的代码也只对内网提供服务。那么大概率你的服务是用的HTTP协议。

但如果哪天你想让外网的朋友们也体验下你的服务功能,那就需要将服务暴露到外网,而这时候如果还是用的HTTP协议,那信息的收发就会是明文,只要有心人士在通讯链路中任意一个路由器那抓个包,就能看到你HTTP包里的内容,因此很不安全。

为了让明文,变成密文,我们需要在HTTP层之上再加一层TLS层,目的就是为了做个加密。这就成了我们常说的HTTPS。
pEOxRIA.png
TLS其实分为1.2和1.3版本,目前主流的还是1.2版本,我们以它为例,来看下HTTPS的连接是怎么建立的。

HTTPS 握手过程

首先是建立TCP连接,毕竟HTTP是基于TCP的应用层协议。

在TCP成功建立完协议后,就可以开始进入HTTPS的加密流程。

总的来说。整个加密流程其实分为两阶段
pEOx4RP.png
第一阶段是TLS四次握手,这一阶段主要是利用非对称加密的特性各种交换信息,最后得到一个"会话秘钥"。

第二阶段是则是在第一阶段的"会话秘钥"基础上,进行对称加密通信。

我们先来看下第一阶段的TLS四次握手是怎么样的。
pEXSQXT.png
第一次握手:

• Client Hello:是客户端告诉服务端,它支持什么样的加密协议版本,比如 TLS1.2,使用什么样的加密套件,比如最常见的RSA,同时还给出一个客户端随机数。
第二次握手:

• Server Hello:服务端告诉客户端,服务器随机数 + 服务器证书 + 确定的加密协议版本(比如就是TLS1.2)。
第三次握手:

• Client Key Exchange: 此时客户端再生成一个随机数,叫 pre_master_key。从第二次握手的服务器证书里取出服务器公钥,用公钥加密 pre_master_key,发给服务器。
• Change Cipher Spec: 客户端这边已经拥有三个随机数:客户端随机数,服务器随机数和pre_master_key,用这三个随机数进行计算得到一个"会话秘钥"。此时客户端通知服务端,后面会用这个会话秘钥进行对称机密通信。
• Encrypted Handshake Message:客户端会把迄今为止的通信数据内容生成一个摘要,用"会话秘钥"加密一下,发给服务器做校验,此时客户端这边的握手流程就结束了,因此也叫Finished报文
第四次握手:

• Change Cipher Spec:服务端此时拿到客户端传来的 pre_master_key(虽然被服务器公钥加密过,但服务器有私钥,能解密获得原文),集齐三个随机数,跟客户端一样,用这三个随机数通过同样的算法获得一个"会话秘钥"。此时服务器告诉客户端,后面会用这个"会话秘钥"进行加密通信。
• Encrypted Handshake Message:跟客户端的操作一样,将迄今为止的通信数据内容生成一个摘要,用"会话秘钥"加密一下,发给客户端做校验,到这里,服务端的握手流程也结束了,因此这也叫Finished报文
短短几次握手,里面全是细节,没有一处是多余的。

我们一个个来解释。

因为大家肯定已经很晕了,所以我会尽量用简短的语句,来解释下面几个问题。

HTTPS 到底是对称加密还是非对称机密?

都用到了。前期4次握手,本质上就是在利用非对称加密的特点,交换三个随机数。

目的就是为了最后用这三个随机数生成对称加密的会话秘钥。后期就一直用对称机密的方式进行通信。

pEOx4RP.png

为什么不都用非对称加密呢?

因为非对称加密慢,对称加密相对来说快一些

第二次握手里的服务器证书是什么?怎么从里面取出公钥?

服务器证书,本质上是,被权威数字证书机构(CA)的私钥加密过的服务器公钥。

pEXSthR.png
上面提到过,被私钥加密过的数据,是可以用公钥来解密的。而公钥是任何人都可以得到的。所以第二次握手的时候,客户端可以通过CA的公钥,来解密服务器证书,从而拿到藏在里面的服务器公钥。
pEXSU91.png

为什么我不能只传公钥,而要拿CA的私钥加密一次再传过去?

反过来想想,如果只传公钥,公钥就有可能会在传输的过程中就被黑客替换掉。然后第三次握手时客户端会拿着假公钥来加密第三个随机数 pre_master_key,黑客解密后自然就知道了最为关键的 pre_master_key。又因为第一和第二个随机数是公开的,因此就可以计算出"会话秘钥"。

所以需要有个办法证明客户端拿到的公钥是真正的服务器公钥,于是就拿CA的私钥去做一次加密变成服务器证书,这样客户端拿CA的公钥去解密,就能验证是不是真正的服务器公钥

那么问题又又来了

怎么去获得CA的公钥?

最容易想到的是请求CA的官网,获取公钥。但全世界要上网的人那么多,都用去请求CA官网的话,官网肯定顶不住。

考虑到能颁发证书的CA机构可不多,因此对应的CA公钥也不多**,把他们直接作为配置放到操作系统或者浏览器里,**这就完美解决了上面的问题。

pEXSdc6.png

别人就拿不到你这三个随机数?

这三个随机数,两个来自客户端,一个来自服务端。第一次和第二次握手里的客户端随机数和服务端随机数,都是明文的。只要有心,大家都能拿到。

但第三个随机数 pre_master_key 则不行,因为它在客户端生成后,发给服务器之前,被服务器的公钥加密过,因此只有服务器本器才能用私钥进行解密。就算被别人拿到了,没有服务器的私钥,也无法解密出原文。

pEXSwjK.png

为什么要用三个随机数?而不是一个或两个?

pEXSBnO.png
看上去第三个随机数 pre_master_key才是关键,另外两个看起来可有可无?

确实,就算没有另外两个,也并不影响加密功能。之所以还要两个随机数,是因为只有单个 pre_master_key随机性不足,多次随机的情况下有可能出来的秘钥是一样的。但如果再引入两个随机数,就能大大增加"会话秘钥"的随机程度,从而保证每次HTTPS通信用的会话秘钥都是不同的。

为什么第三和第四次握手还要给个摘要?

第三和第四次握手的最后都有个 Finished报文,里面是个摘要

摘要,说白了就是对一大段文本进行一次hash操作。目的是为了确认通信过程中数据没被篡改过。

第三次握手,客户端生成摘要,服务端验证,如果验证通过,说明客户端生成的数据没被篡改过,服务端后面才能放心跟客户端通信。

第四次握手,则是反过来,由服务端生成摘要,客户端来验证,验证通过了,说明服务端是可信任的。

那么问题叒来了。

为什么要hash一次而不是直接拿原文进行对比?

这是因为原文内容过长,hash之后可以让数据变短。更短意味着更小的传输成本。

这个过程中到底涉及了几对私钥和公钥?

两对。

服务器本身的公钥和私钥:在第二次握手中,服务器将自己的公钥(藏在数字证书里)发给客户端。第三次握手中用这个服务器公钥来加密第三个随机数 pre_master_key。服务器拿到后用自己的私钥去做解密。

CA的公钥和私钥:第二次握手中,传的数字证书里,包含了被CA的私钥加密过的服务器公钥。客户端拿到后,会用实现内置在操作系统或浏览器里的CA公钥去进行解密。

总结

大数取模运算是不可逆的,因此他人无法暴力解密。但是结合欧拉定理,我们可以选取出合适的p(公钥), q(私钥), N(用于取模的大数),让原本不可逆的运算在特定情况下,变得有那么点“可逆”的味道。数学原理决定了我们用公钥加密的数据,只有私钥能解密。反过来,用私钥加密的数据,也只有公钥能解密。
HTTPS相当于HTTP+TLS,目前主流的是TLS1.2,基于TCP三次握手之后,再来TLS四次握手。
TLS四次握手的过程中涉及到两对私钥和公钥。分别是服务器本身的私钥和公钥,以及CA的私钥和公钥。
TLS四次握手背起来会挺难受的,建议关注三个随机数的流向,以此作为基础去理解,大概就能记下来了。

1

评论区