You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
10 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 14 | 加密数据能够自我验证吗?
你好,我是范学雷。
还记得上一讲,我们讲的消息验证码吗?我们讨论过可以使用消息验证码来验证消息的真伪。但是,不知道你有没有注意,在上一次讨论中,我们并没有讨论该如何安全地传递待验证消息。
而且,待验证信息的传递还是通过明文的方式进行的,这种方式,信息的私密性会受到影响。我们前面讨论过,单独的加密并不能解决信息的有效传递问题,总是存在这样或者那样的问题。
那么,我们能不能把消息验证码和信息加密结合起来,既保持信息的私密性,也保持信息的完整性呢?这就是我们这一次要解决的问题。
## 先加密还是后加密?
想要保持信息的私密性,我们可以在信息传输之前,把明文数据加密成密文数据,然后传输密文数据。如果我们还想要保持信息的完整性,我们就要使用消息验证码。
第一个来到我们面前的问题是消息验证码和信息加密该怎么结合起来或者换一种说法就是怎么构造可认证的加密Authenticated Encryption (AE))呢?
加密和验证组合起来的方式不外乎三种方案。
### 加密并验证
第一种方案就是加密明文数据计算明文数据的消息验证码输出密文数据和验证码。这种方案我们简称为加密并验证。安全外壳协议SSH就是采用加密并验证的方案。
![](https://static001.geekbang.org/resource/image/d9/8c/d9b581e531aa5d05ece275a302f4168c.jpeg)
这个方案的消息验证码,保护的是明文信息的完整性,而不是密文信息的完整性。如果明文信息相同,它的消息验证码也是相同的。从攻击者的角度看,如果发现两个相同的消息验证码,就可以猜测明文信息大概率是相同的。
我们前面反复讨论过,为什么要使用初始化向量来避免重复的明文生成重复的密文。这个方案,又一次把这个缺陷暴露了出来,只不过现在,我们是通过消息验证码来判断的。
### 加密后验证
第二种方案加密明文数据计算加密数据的消息验证码输出密文数据和验证码。这种方案我们简称为加密后验证。IPSec协议采用的就是加密后验证的方案。
![](https://static001.geekbang.org/resource/image/48/a9/481b4ff097445e77b857ed393365a3a9.jpeg)
这个方案的消息验证码,保护的是密文信息的完整性,而不是明文信息的完整性。由于密文是从明文演算过来的,也就间接地保护了明文的完整性。
另外,只要加密算法不把相同的明文信息加密成相同的密文信息,它的消息验证码也就是不同的。所以,这个方案没有上面的加密并验证方案的安全问题。
### 验证后加密
第三种方案则是计算明文数据的消息验证码加密明文数据和验证码输出密文数据。这种方案我们简称为验证后加密。SSL协议采用的就是验证后加密的方案。
![](https://static001.geekbang.org/resource/image/f5/a8/f5c74b157fe850fb7d2c0d8yye1219a8.jpeg)
这个方案的消息验证码保护的是明文信息的完整性而不是密文信息的完整性。如果我们把明文信息和消息验证码看作是一个数据我们前面提到的CBC攻击方案是不是似乎又回来了实际的攻击方案比我们前面讨论的复杂如果你有兴趣可以看看[这篇论文](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.5488&rep=rep1&type=pdf)。
每一种方案都有重量级的协议支持。重量级的协议都能使用这些方案,我们能不能任意选用哪一款方案呢?我觉得答案是很明显的。
## 该选用哪一个方案?
有了重量级协议的支持,给了我们一个很好的借口。似乎,我们可以选用这其中任何一个方案,把它用到我们的应用程序里。不过,重量级的协议也会有安全问题,有重量级协议撑腰,并不意味着它就是安全的。
由于新的密码分析技术的进展尤其是前面我们讨论过的BEAST攻击这种新技术的出现加密并验证以及验证后加密这两种方案都受到了很大的挑战和质疑。
接下来在2014年以后无论是SSH协议还是TLS协议都提供了加密后验证的选项用来提高协议的安全性。其中2018年新发布的TLS协议甚至完全抛弃了CBC模式也不再使用上述的任何一个方案。
**所以,如果我们只能从上述三个方案中间选择,加密后验证这个方案目前来说,是最安全的方案**。截止到我准备这一讲的时候,就我自己的知识范围里,只要算法选择得当,加密后验证方案还不会出现致命的安全漏洞。
答案似乎很清楚了,结论就是,在应用程序里,我们可以放心使用加密后验证方案。 在你决定要把这个结论记下来之前你想不想知道新的TLS协议采用了什么样新的加密方案这个新的加密方案应用程序也可以使用吗
## 带关联数据的加密
到目前为止,我们都没有讨论,信息是怎么传递给对方的。无论是在互联网里,还是现实生活中,我们要传递给对方的信息,并不单纯只有信息本身。
生活中信件的传递,需要信封,信封上还要贴邮票、盖邮戳;快递的传递,要有包裹,包裹上要贴快递单。信封和包裹,虽然是用来携带具体信息的,但其实也是信息的一部分。信封里的信件是要保密的,但是信封上的信息是公开的。信封上的信息虽然是公开的,但是同样不可更改。
网络上的信息也是这样,而且更复杂。比如一段网络数据,除了要携带应用要传递的信息外,它的信封上一般还要有版本号,信息类型以及数据长度等信息。
![](https://static001.geekbang.org/resource/image/ae/4d/aee58eaa5cdb1b9ec7a63df590f6324d.png)
如果一段信息的版本号或者数据类型被篡改,接收方就没有办法正确解读接收到的信息;如果信息的数据长度被修改,接收方就没有办法判断接收的数据是不是完整的,从而影响系统的读写效率,甚至进而存在拒绝服务攻击的风险。
那有没有办法保护信封上的信息,也就是公开部分信息的完整性?
带关联数据的加密就是用来解决这个问题的。在解决公开信息的完整性问题的同时一般的算法设计也会同时解决掉私密信息的完整性问题。所以这一类算法通常也叫做带关联的认证加密Authenticated Encryption with Associated DataAEAD
![](https://static001.geekbang.org/resource/image/e5/46/e5b3fb7f799d6ae2d8fc4276572a0546.jpeg)
不同于我们前面讨论过的加密函数,带关联的认证加密的加密函数需要三个输入数据:
* 加密密钥;
* 明文信息;
* 关联信息。
输出结果包含两段信息:
* 密文信息;
* 验证标签。
一般来说,验证标签可以看做是密文信息的一部分,需要和密文信息一起传输给信息接收方。
如果改变明文信息,密文信息和验证标签都会变化,这一点,就解决了明文信息的验证问题。如果改变关联信息,至少验证标签会不一样,这一点,解决了关联信息的验证问题。
对应地,带关联的认证加密的解密函数需要四个输入数据:
* 解密密钥;
* 关联信息;
* 密文数据;
* 验证标签。
而输出的是明文信息。在解密过程中,如果密文信息或者关联信息验证失败,明文信息不会输出。换句话说,只有明文信息和关联信息的完整性都得到验证,才会有明文信息输出。
![](https://static001.geekbang.org/resource/image/a9/73/a9920f861a3fd6103f3d325ddac8b573.jpeg)
这么一看,带关联的认证加密既解决了需要保密信息的私密性和完整性,也解决了关联信息的完整性问题,这使得带关联的认证加密算法成为目前主流的加密模式。
带关联的认证加密算法的广泛使用也使得曾经占据主导地位的CBC算法可以从容地退出历史舞台。因为**带关联的认证加密算法能够进行自我验证**。
自我验证,就意味着解密的时候,还能够同时检验数据的完整性。这无疑减轻了应用程序的设计和实现压力。有了带关联的认证加密算法,应用程序再也不需要自行设计、解决数据的完整性问题了。
现在有哪些流行的带关联的认证加密算法呢?下一次,我们接着聊这个话题。
## Take Away今日收获
今天,我们讨论了使用消息验证码构造可认证加密的三种方案。它们分别是加密并验证、加密后验证以及验证后加密。其中,加密并验证以及验证后加密这两种方案存在安全缺陷;加密后验证是一个更安全的方案。
另外,我们还讨论了带关联的认证加密的基本思路\_。\_带关联的认证加密除了提供可认证的加密保护私密数据的完整性之外还通过关联数据保护公开数据的完整性。**能同时保护私密数据的完整性和公开数据的完整性,这是带关联的认证加密算法要解决的主要问题**。
通过今天的讨论,我们要:
* 知道加密并验证以及验证后加密这两种方案存在安全缺陷,尽量不要使用这两种方案;
* 了解带关联的认证加密,以及它要解决的问题。
## 思考题
今天的思考题,我们继续挖掘牛郎织女的约会问题。
这一次讨论完,我们再来看看现在有没有更好的办法解决这个问题。为了方便,我把描述部分又抄写一遍。如果牛郎要给织女发信息,七夕相约鹊桥会。
> 织女:
> 七月初七晚七点,鹊桥相会。不见不散。
> 牛郎
你能够帮助牛郎想想吗?该怎么来保证约会信息的私密性和完整性?传递的信息该怎么构造?当然,按照惯例,我们还是要想一想,你建议的办法还有没有其他的问题?
欢迎在留言区留言,记录、讨论你的想法。
好的,今天就这样,我们下次再聊。
祝你圣诞节快乐!