Chapter 2 完美保密加密
在前一章中,我们介绍了一些历史加密方案,并说明它们很容易被破解。在本章中,我们将看看另一个极端,并研究加密方案,即使其面对具有无限计算能力的对手,也可证明是安全的。这样的计划被称为完美保密。我们严格地定义了这个概念,并探索了实现完全保密的条件。
在某种意义上,本章的材料更多地属于“古典”密码学的世界,而不是“现代”密码学的世界。除了这里介绍的所有材料都是在20世纪70年代中期和80年代密码学革命之前开发的之外,我们在本章中研究的结构仅依赖于第1.4节中概述的第一和第三原理。也就是说,使用精确的数学定义并给出严格的证明,但不需要依赖任何未经证明的计算假设。显然,避免这种假设是有利的;然而,我们将看到,这样做有固有的局限性。因此,本章的结果除了为理解现代密码学的基本原理提供了良好的基础之外,还为我们后来采用上述三个原理提供了依据。
从本章开始,我们将定义安全性并使用涉及随机算法的概率实验分析方案。通过“实验”给出了一个简单的例子,在“实验”中,希望使用私钥加密方案进行通信的双方生成一个随机密钥。由于随机性是如此重要,在回到密码学本身的讨论之前,我们简要讨论生成适合于密码学应用程序的随机性的问题。
生成随机数
在本书中,为了简单起见,我们将假设各方可以获得无限的、独立的、无偏的(即统一的)比特。这些随机比特从何而来?由于经典计算是确定性的,所以根本不清楚如何使用计算机来生成随机比特。原则上,人们可以手工生成少量均匀的比特,例如,通过抛一枚均匀的硬币。但这种方法不太方便,也不具有可扩展性。
现代随机数生成分为两个步骤。首先,收集高熵数据的“池”。(就我们的目的而言,不需要熵的正式定义,只要把熵看作是一种不可预测性的度量就足够了。)接下来,对这些高熵数据进行处理,生成一个几乎独立且无偏置的比特序列。第二步是必要的,因为高熵数据不一定是均匀的。
对于第一步,需要一些不可预测的数据来源。这可能来自外部输入,例如,网络事件之间的延迟、硬盘访问时间、用户的击键或鼠标移动,等等。也可以使用更复杂的方法——通过设计,将随机数生成更紧密地结合到硬件级的系统中。这些依赖于物理现象,如热/射噪声或放射性衰变;例如,某些英特尔处理器利用热噪声在芯片上生成高熵数据。这类硬件随机数生成器通常比依赖外部源的技术更快地产生高熵数据。
“平滑”高熵数据以获得(几乎)独立和均匀的位所需要的处理是不平凡的。这里,我们考虑一个简单的例子来说明可以做些什么。假设我们的高熵池包含一个有偏差的比特序列,其中1出现的概率为p, 0出现的概率为1−p。(然而,我们确实假设所有的比特都是独立的。在实践中,这种假设通常是无效的,因此必须进行更复杂的处理。)数千个这样的比特有很大的熵,但不接近均匀。我们可以通过将原始的位成对计算得到一个统一的位序列:如果我们看到一个1后面跟着一个0,那么我们输出0,如果我们看到一个0后面跟着一个1,那么我们输出1。(如果我们在一行中看到两个0或两个1,我们就什么也不输出,只是继续进行下一对。)任意一对得到0的概率是p·(1−p),这正好等于任意一对得到1的概率。(注意,我们甚至不需要知道p的值!)因此,我们从初始的高熵池中得到了一个均匀分布的输出。
必须注意随机比特是如何产生的,使用糟糕的随机数生成器通常会使一个良好的密码系统容易受到攻击。应该使用为加密用途而设计的随机数生成器,而不是通常不适合加密应用的“通用”随机数生成器。特别是,C 语言stdlib.h库中的rand()函数在密码学上是不安全的,在密码学设置中使用它可能会产生灾难性的后果。
2.1 定义
我们首先回顾和扩展前一章中介绍的加密语法。加密方案由Gen、Enc和Dec三种算法定义,并指定消息空间M为|M| > 1(如果|M| = 1,则只有一条消息,通信没有意义,更不用说加密了)。密钥生成算法Gen是一种根据某种分布选择的密钥k输出的概率算法。我们用K表示(有限)密钥空间,即,所有可能的密钥的集合,可以由Gen输出。加密算法Enc取密钥k∈K,消息m∈M作为输入,输出密文c。我们现在显式地允许加密算法是概率的(因此Enck(m)在运行多次时可能会输出不同的密文),我们写c←Enck(m)来表示消息m使用密钥k加密得到密文c的可能的概率过程。(展望未来,我们有时也使用符号x←S来表示从集合S中均匀选择x。如果Enc是确定的,我们可以写c:= Enck(m)来强调这一点。)我们让C表示Enck(m)能输出的所有可能的密文集合,对于k∈K和m∈M的所有可能的选择(对于随机情况下的Enc的所有随机选择)。解密算法Dec以密钥k∈K和密文c∈C作为输入,输出消息m∈M。我们假设完全正确,这意味着对于所有k∈K, m∈M,以及Enck(m)输出的任何密文c,它满足Deck© = m,概率为1。完全正确意味着我们可以假设Dec是确定的而不丧失一般性,因为Deck©每次运行时必须给出相同的输出。因此我们用m:= Deck©来表示使用密钥k解密密文c产生消息m的(确定性)过程。
在下面的定义和定理中,我们指的是K、M和C上的概率分布。K的分布是通过运行Gen并获取输出定义的。(Gen几乎总是从K中一致地选择一个密钥,事实上,我们可以假设这一点而不丧失一般性;见练习2.1。)设K为随机变量,表示Gen输出的密钥值;因此,对于任意k∈K, Pr[K = k]表示Gen输出的密钥等于k的概率。同样,我们设M为表示被加密消息的随机变量,因此Pr[M = m]表示消息取m∈M值的概率。消息的概率分布不是由加密方案本身决定的,而是反映了使用该方案的各方发送不同消息的可能性,以及敌手对将发送什么内容的不确定性。例如,敌手可能知道该消息今天将被攻击或不攻击。对手甚至可能(通过其他方式)知道,该消息的概率为0.7,是攻击的命令,而该消息的概率为0.3,是不攻击的命令。在这种情况下,Pr[M = attack today] = 0.7, Pr[M = don’t attack] = 0.3。
K和M被要求是独立的,也就是说,双方所通信的内容必须独立于他们共享的密钥。在其他原因中,这是有意义的,因为在K上的分布是由加密方案本身决定的(因为它是由Gen定义的),而在M上的分布取决于使用加密方案的上下文。
固定一个加密方案和M上的分布,确定密文C在空间上的分布,选择一个密钥k∈K(根据Gen)和一个消息m∈M(根据给定的分布),然后计算密文C←Enck(M)。设C为随机变量,表示生成的密文,对于c∈C,取Pr[C = c]表示密文等于固定值c的概率。
Example 2.1
这里,根据定义,我们有K ={0,…