看动画,轻松学习23种C++设计模式无密天生我材必有用

#1

download:看动画,轻松学习23种C++设计模式无密天生我材必有用

为什么用公钥加密却不用公钥解密?
我一直避免写HTTPS。
毕竟。
HTTPS的名词太多了。这个概念庞大而繁琐。
太难解释了。如果可以,我尽量不写。。。。
但是为了使图形网络的知识体系尽可能的完整。
今天,请容忍我。
先说对称加密和非对称加密。

对称加密和非对称加密
你小学的时候有传小纸条吗?递纸条的时候,每个拿到的人都会忍不住看一眼。一点隐私都没有。
假设班花想向我表白,但在传递的过程中不想让别人发现她的情意。
你会在课间十分钟告诉我,“向左移动一个字母,这就是我想对你说的话”。
然后,在课堂上,发一张纸条,上面写着eb tib cj。每一个帮忙送纸条的同学看完后都暗暗骂“谜语人,滚出哥谭镇”。
嘿嘿,你不懂,我懂。
拿到纸条后,我把每个字母都向左移动了一个位置,得到了达沙比。
什么话?这些是什么词?
坏女人想毁我心向道?我果断拒绝了她的表白。

现在回想起来,感动之余会发现,像这样,把一条大家都能看懂的信息(明文)转换成另一条大家都看不懂的信息(密文),其实就是加密。
像这种“左移”的加密方法,其实就是所谓的秘钥。这种加密和解密使用相同的密钥加密形式,称为对称加密。

既然有对称加密,就有非对称加密。
不同的是,非对称加密,加密和解密使用的不是同一个密钥,而是两个不同的密钥,即公钥和私钥。

公钥负责加密,私钥负责解密。公钥对每个人都可用,但私钥永远不会泄露。
那么问题来了。

为什么用公钥加密,而不用公钥解密?
实际上,这涉及到公钥和私钥加密的数学原理。
说白了,加密就是把一个已知的数按照一定的规则转换成另一个数。以前,这些数字在一起都是可读的,但经过这样的转换后,它们就变得不可读了。
也就是说,加密的本质是num -> x (num是已知数,x是未知数)。
比如类花运算加一减一,就是一个很简单的转换方法。
我们换个复杂点的,比如余数运算。
假设有一个计算余数的公式。
5^2 mod 7 = 25 mod 7 = x
复制代码
这个公式很简单。给定5和7的2次方,很容易得到x=4。
但是如果我们改变x的位置。
5^x mod 7 = 4
复制代码
当x等于时,上述等式成立吗?
那就麻烦多了。
5^0 mod 7 = 1
5^1 mod 7 = 5
5^2 mod 7 = 4
5^3 mod 7 = 6
5^4 mod 7 = 2
复制代码
虽然有点麻烦,但我们还是可以推导出,当x=2时,方程成立。
但是如果上面的模数值变得巨大呢?
5^x mod 56374677648 = 4
复制代码
那时候电脑只能一个个算出来。CPU正常算出来需要很多年,可以认为算不出来。
其实上面的公式就是把5加密成4。如果已知x,很容易计算出等式右边的结果是4,反过来,就很难从4推导出x的值。因此,这种模块化算法是不可逆的。
虽然模运算是不可逆的,但是结合欧拉定理可以让这个公式在一定条件下有点“可逆”(注意加引号)。
让我们看看它是怎么做的。
让我们把X掰成两半,成为P和q的乘积。
原始(p * q) mod n =原始
复制代码
如果P、Q、N选择得当,经过一波模运算,原文还是会变回原文。
知道这些是没用的,但是结合欧拉定理,经过一些我们无法理解的推导过程,可以把上面的公式转化成下面的。
原始§模n =密文
密文(q) mod n =原始文本
复制代码

结合欧拉公式的计算过程,有兴趣可以查一下。但是知道这里的结论就够了。

也就是说,知道P就可以加密,知道Q就可以解密。
这里,P是公钥,Q是私钥。
用公钥加密的密文只能用私钥解密。

甚至更好。
其实公式中P和Q的位置是可以互换的,所以说“用私钥加密的密文只能用公钥解密”也是可以的。这种操作通常被称为验证数字签名。
就像古装电视剧里,经常会有这样的故事,两个失散多年的亲人,各有一片碎成两瓣的玉佩。
有一天,当他们发现两个玉佩裂缝刚好可以拼在一起时,他们确认了另一个就是他们失散已久的大儿子。
这两块碎玉有点像公钥和私钥。

原理大家知道这么多其实就够了。
看到这里,就可以回答题目的问题了。

为什么用公钥加密,而不用公钥解密?
因为大数的模运算是不可逆的,别人无法暴力解密。但结合欧拉定理,我们可以选择合适的P(公钥)、Q(私钥)和N(取模的大数),使原本不可逆的操作在一定情况下可以有些“可逆”。数学决定了我们用公钥加密的数据只能用私钥解密。相反,只有公钥才能解密用私钥加密的数据。

从数学原理可以看出,公钥和私钥的加密是安全的,但这件事的前提是基于“目前的计算机运算速度还不够快”。所以,如果有一天科技更加发达,我们变成了更高维度的科技文明,那可能就是现在的密文和明文没什么区别了。

在了解了对称加密和非对称秘密之后,我们可以谈谈HTTPS的加密原理。

HTTPS的加密原理
如果你在公司内网做开发,而你写的代码只给内网提供服务。那么很有可能您的服务正在使用HTTP协议。
但是如果有一天你想让外网的朋友体验你的服务功能,你就需要把服务暴露给外网。此时,如果您仍然使用HTTP协议,信息将以明文形式发送和接收。只要有心人在通信链路的任何一个路由器上抓到一个包,就可以看到你的HTTP包的内容,所以非常不安全。
为了让明文变成密文,我们需要在HTTP层之上再加一层TLS,达到加密的目的。这就是我们常说的HTTPS。

其实TLS分1.2和1.3两个版本。目前主流版本是1.2。让我们以它为例,看看HTTPS连接是如何建立的。
HTTPS握手过程
第一步是建立TCP连接。毕竟HTTP是基于TCP的应用层协议。
TCP成功建立协议后,就可以开始进入HTTPS的加密过程。
总的来说。整个加密过程实际上分为两个阶段。

第一阶段是TLS四次握手,主要利用非对称加密的特性来交换信息,最后得到一个“会话密钥”。
第二阶段是基于第一阶段“会话密钥”的对称加密通信。
我们来看看TLS四次握手的第一阶段。

第一次握手:

你好:是客户端告诉服务器它支持什么加密协议版本,比如TLS1.2,使用什么加密套件,比如最常见的RSA,还给了一个客户端的随机数。

第二次握手:

Hello server:服务器Hello客户端即服务器随机数+服务器证书+确定的加密协议版本(例如TLS1.2)。

三次握手:

ClientExchange:此时,客户端生成另一个随机数,称为pre_master_key。从第二次握手的服务器证书中取出服务器公钥,用公钥加密pre_master_key并发送给服务器。
更改密码规范:客户端已经有三个随机数:客户端随机数、服务器随机数和pre_master_key。用这三个随机数计算得到一个“会话密钥”。此时,客户端通知服务器该会话密钥将用于对称保密通信。
加密握手消息:客户端将生成到目前为止的通信数据内容的摘要,用“会话密钥”加密,并发送给服务器进行验证。此时客户端的握手过程已经结束,所以也叫完成消息。

第四次握手:

更改Cipher Spec:此时服务器获取客户端发来的pre_master_key(虽然已经用服务器的公钥加密了,但是服务器有私钥,可以解密得到原文),收集三个随机数,和客户端一样,用这三个随机数通过同样的算法得到一个“会话密钥”。此时,服务器告诉客户端,这个“会话密钥”将在以后用于加密通信。
加密握手消息:和客户端的操作一样,生成到目前为止的通信数据内容的摘要,用“会话密钥”加密并发送给客户端进行验证。此时,服务器的握手过程结束,所以这也称为完成消息。

只是几次握手,满满的细节,没有什么多余的。
下面就来一一解释一下。
因为大家肯定都晕了,下面的问题我尽量用短句来解释。

HTTPS是对称加密还是非对称秘密?
都是二手的。前期的四次握手,本质上是利用非对称加密的特性,交换三个随机数。
目的是最终用这三个随机数生成一个对称加密的“会话密钥”。后期一直以对称保密的方式沟通。

为什么不使用非对称加密?
因为非对称加密很慢,所以对称加密相对更快。
第二次握手中的服务器证书是什么?怎么把公钥弄出来?
本质上,服务器证书是由权威数字证书颁发机构(CA)的私钥加密的服务器公钥。
如上所述,用私钥加密的数据可以用公钥解密。并且公钥对任何人都是可用的。因此,在第二次握手过程中,客户端可以通过CA的公钥解密服务器证书,从而得到隐藏在其中的服务器公钥。

看起来有点多余?
那么问题来了。
为什么不能直接传递公钥,而是用CA的私钥加密一次再传递?
另一方面,如果只传输公钥,公钥可能在传输过程中被黑客替换。然后在三次握手中,客户端会用一个假的公钥加密第三个随机数pre_master_key,解密后黑客自然就知道了最关键的pre_master_key。因为第一和第二随机数是公开的,所以可以计算出“会话密钥”。
所以需要有一种方法来证明客户端获得的公钥是真正的服务器公钥,所以用CA的私钥进行加密成为服务器证书,这样客户端就可以通过解密CA公钥来验证是否是真正的服务器公钥。

那么问题又来了。
如何获取CA的公钥?
最容易想到的就是请求CA官网获取公钥。然而,全世界有那么多人想上网。如果都用它来请求CA官网,官网受不了。
考虑到能颁发证书的CA机构不多,所以对应的CA公钥也不多,直接把它们作为配置放入操作系统或者浏览器就能完美解决上述问题。

人家拿不到你的三个随机数?
这三个随机数,两个来自客户端,一个来自服务器。第一次和第二次握手中的客户端随机数和服务器随机数是明文。只要你有心,每个人都能得到。
而第三个随机数pre_master_key不能,因为它是在客户端生成之后,发送到服务器之前,用服务器的公钥加密的,所以只有服务器自己才能用私钥解密。即使别人拿到了,没有服务器的私钥也无法解密原文。

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

好像第三个随机数pre_master_key才是关键,其他两个好像可有可无?
的确,即使没有另外两个,也不会影响加密功能。之所以需要两个随机数,是因为只有一个pre_master_key不够随机,多个随机数情况下可能出来的密钥是一样的。但是,如果引入两个随机数,“会话密钥”的随机性将大大增加,从而确保每次HTTPS通信所使用的会话密钥是不同的。

为什么要总结第三次和第四次握手?
在第三次和第四次握手结束时,有一个完成的消息,其中包含一个总结。
抽象,说白了就是对一大段文本进行哈希运算。目的是确认数据在通信过程中没有被篡改。
三次握手,客户端生成摘要,服务器验证。如果验证通过,说明客户端生成的数据没有被篡改,服务器可以放心的和客户端通信。
第四次握手由服务器生成,并由客户端验证。验证通过,表明该服务器可以信任。
那么问题来了。
为什么非要哈希一次而不是直接对比原文?
这是因为原始内容太长,哈希可以让数据变短。越短意味着传输成本越低。

这个过程涉及多少对私钥和公钥?
两对。
服务器自己的公钥和私钥:在第二次握手中,服务器将自己的公钥(隐藏在数字证书中)发送给客户端。在三次握手中,第三个随机数pre_master_key用这个服务器公钥加密。服务器得到它后,用自己的私钥解密。
CA的公钥和私钥:在第二次握手中,传输的数字证书包含由CA的私钥加密的服务器公钥。在客户端获得它之后,它将使用操作系统或浏览器内置的CA公钥来解密它。
摘要

大数的模运算是不可逆的,别人无法暴力解密。但结合欧拉定理,我们可以选择合适的P(公钥)、Q(私钥)和N(取模的大数),使原本不可逆的操作在一定情况下可以有些“可逆”。数学决定了我们用公钥加密的数据只能用私钥解密。相反,只有公钥才能解密用私钥加密的数据。
HTTPS相当于HTTP+TLS。目前主流是TLS1.2,基于TCP的三次握手后,TLS会握手四次。
TLS四次握手涉及两对私钥和公钥。它们是服务器本身的私钥和公钥,以及CA的私钥和公钥。
TLS四次握手很难背。建议关注三个随机数的流向,然后以此为基础去理解,大概就能记下来了。