题主的这个问题问得很不错,很适合展开写一篇关于密码学的科普,给没有相关背景的程序员普及一些密码学常识。
为了那些没有耐心读完全文的读者,我先把结论提到最开头:这样的组合加密存在安全缺陷,两个算法的组合,其强度仅仅相当于强度最高的那个算法;三个及以上的算法组合,才有可能胜过强度最高的那个算法,但是仍弱于密码本身应有的强度。以上结论可给出严谨的数学证明,而且高中/本科水平的知识应该就足以理解。
(补充一句,刚才看到其他答主的答案之后,我突然意识到我之前的表述有些问题。“三个及以上的算法组合”,并不是说必须要用三个不同的算法,其中可以重复出现相同的算法。)
另外,我在下面回答里看到有人提到了香农的乘积密码(Product Cipher),但是乘积密码和本题描述的情况其实并不完全相同,这一点我会放在文末讲。
在正式开始之前,我们要先讲清楚一个问题:现代密码学到底是如何判断一个加密算法安全与否的?如果对这一点没有一个严谨的定义的话,接下来的论证是没法展开的。
现代密码学中考察一个加密算法的安全性时,一定会假设攻击者知道算法的所有细节,只是不知道密钥而已。这个假设被称作柯克霍夫原则(Kerckhoffs's Principle),是我们从历史上无数失败的保密系统中学到的经验教训——永远不要依赖保密算法来保证系统的安全性。
在柯克霍夫原则的基础上,密码学家一般会进一步假设攻击者能够发动选择明文攻击(Chosen-Plaintext Attack)或者稍弱一点的已知明文攻击(Known-Plaintext Attack)。
这两种攻击乍一看有些苛刻,但是在大范围应用的过程中往往无法避免。因此对加密算法进行理论分析的时候,必须采用这样的威胁模型来进行考量。
在文章的最开头,我提到了一个概念:加密算法的强度(bits of security),那么这个强度是怎么定义的呢?
假定我们有一个加密算法,它的密钥长度有256位,那么进行穷举破解就需要进行 次计算。我们把这个计算量,视作这个算法理论上讲应有的强度,即 256 bits of security。
如果有一天突然有人发现这个算法存在数学上的漏洞,想要找到密钥只需要进行 次计算就够了,那么我们就说这个算法的强度降低到了128位,即 128 bits of security。
比较著名的例子是当年美国制定的3DES(Triple DES)算法,从168位的加密强度一路掉到了现在NIST钦定的80位(Keying Option 2),基本就相当于一个废物加密算法了。
首先我们来考虑只有两个加密算法组合的情况。在这段论证中,我将会采用实现难度更低的已知明文攻击,这样能够更好地说明组合加密算法的脆弱程度。
假定存在两个加密算法 ,它们俩的密钥长度分别为 ,且加密强度与密钥长度持平。
假定存在密钥 ,对于任意明文 ,我们先使用 加密,再使用 加密,得到密文 。
那么在这种情况下,如果用 来解密 ,应该会得到跟 加密 一样的结果,也就是说存在一个中间值 。
不失一般性地,我们假定 ,也就是说 的密钥更长、强度更强。
假定攻击者已经拿到了一条长度为 的明文 ,以及对应的密文 。
密钥 有 种可能的取值,那么 也就有 种相应的中间值 。我们先建立一个表,将每一对可能的 和 都保存下来,这个步骤需要花费 次运算。
接下来我们开始穷举 。 一共有 种可能的取值,每种取值对应一个中间值 。我们每算出一个中间值来,就在之前建立的表里面查找这个中间值。如果当初建表使用的是哈希表的话(比如DHT),那么这个查表操作只需要常数项的运算时间就能完成。
好,那么我们回过头来解释一个点——为什么之前要提一句明文长度为 呢?因为如果长度不够长的话,我们查表可能会查到假密钥(false key),也就是说这个密钥虽然跟真密钥不同,但是算出来的 恰好与真密钥一致。
对于我们的组合算法而言,一共有 种可能的密钥,算出一个假密钥的概率是 ,也就是说我们的 必须显著大于 才能基本避免出现假密钥。万幸,这个条件很好达成,你只要收集1KB的数据基本就够用了。
最后总结一下,在整个过程中,建表花费了 次运算,查表进行了 次,那么总的运行时间就是 ,这个组合加密的强度仅仅和 持平而已。
以上证明可以通过归纳法推广到三个及以上的算法组合,但这里空间太小,我懒得写了。
这道问题下面有人提到了乘积密码,为什么我说乘积密码和这个不是一个情况呢?因为乘积密码从一开始就是作为一个整体来设计的,在乘积密码运算的过程中,不会暴露出一个中间值供你攻击。
以DES加密为例,密钥一共有56位。你说我能不能找个地方截断一下,比如我知道前24位的话我能正着算一个中间值,知道后32位我能倒着算一个中间值,然后重演上文所述的攻击,可以吗?不可以。DES的每步运算都是和每位密钥息息相关的,你裁出一节密钥来什么也算不出来。
但是本题所述的组合密码就不同了,不管你结合的方式再巧妙,不同的加密算法本来就是不同的整体。一个AES-128算法不管你做什么操作,它的运算就是由128位密钥决定的。你说我加密之前对这128位数据做了一串神仙操作,这128位的值是基于前面的多少多少位变化的,那都无所谓。进到AES-128算法里做加密的,还是128位二进制数据,我知道实际进去的128位数据是多少就完事了,其他数据不可能再对加密过程产生任何影响,任何的小聪明从数学角度讲都没有意义。
觉得本文有价值的话,欢迎点个赞支持一下。对信息安全感兴趣的同学,也欢迎阅读我写的其他信息安全科普类文章: