(本文资料主要来自:http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)
目前流行的加密和数字认证算法,都是采用块加密(block cipher)方式(注:还有一种叫 stream cipher,流式加密)。就是将需要加密的明文分成固定大小的数据块,然后对其执行密码算法,得到密文。数据块的大小通常采用跟密钥一样的长度。
加密模式在加密算法的基础上发展出来,同时也可以独立于加密算法而存在。加密算法,如DES、AES等不多的几种,目前采用最多的是AES。而加密模式是定义怎样通过重复利用加密算法将大于一个数据块大小的明文转化为密文。目前利用较多的加密模式有以下几种:
• ECB:Electronic Code Book(电子码本模式)
• CBC:Cipher Block Chaining(密码块链模式)
• CTR:Counter(计数器模式)
此外,还有其他的一些模式,本文中将不做介绍。
• CFB:Cipher Feedback(密码反馈模式)
• OFB:Output Feedback(输出反馈模式)
电子码本模式(ECB)
这是一种最简单的加密模式,只是将明文分块,并将加密算法应用于数据块,没有任何其他的前后处理。加密和解密流程如下图所示:
在ECB加密模式下,各个数据块的加解密是完全独立的,因此各个数据块的处理可以完全平行地进行,易于用硬件实现,达到很高的处理性能。但ECB有一个致命的弱点,也即不能隐藏明文数据的特定模式。在数据模式中包含较多有用信息时,不用破解就可以发现很多信息。下面就是一个用ECB对一个图像文件加密的典型例子,主要信息实际上已经泄漏了。
另外,由于相同的明文总是得到相同的密文,因此不能抵挡回放攻击(Playback Attack)。比如说,可能不能窃取到你的密码信息,只要通过监视偷录到密码加密后的数据,就可以通过回放进入到你的网上账户。
为了解决以上两个问题,就需要对加密后的数据进行二次处理,以破坏其中的数据模式,同时达到相同的明文在不同时刻加密得到不同的密文,以有效阻止回放攻击。
密码块链模式(CBC)
CBC的基本思路是在明文的各个模块加密之前,与另一个选定的数据块执行一次异或操作,有效地破坏明文数据中的模式。为了保持所选的数据块的随机性,在CBC中选择了前一个数据块的密文。但是对第一个数据块,因为没有前一个数据块的加密结果,需要引入一个初始向量(Initialization Vector: IV)作为选定的数据块。加解密流程如下图所示:
从上述流程图可以看出,CBC的最大问题是各个数据块的加密必须按顺序进行,但解密是可以平行进行的。
CBC的还有一个有趣的特点是,即使中间有一个密文数据块丢失,这只影响它后面的一个数据块的解密,此后的数据块还是可以正确解密的。这个特点引入了一个解决IV选择的思路:Explicit Initialization Vector。在明文之前加一个随机数据块,然后用一个随机的IV对它加密。IV和这随机数据块并不通知到解密侧。在解密侧,第一个数据块由于缺少IV信息,不能正确解密,但其后的数据块都可以正确解密。由于第一个数据块是为了加密而引入的内容,因此可以得到完整的明文内容。
上述Linux企鹅用CBC加密后的数据就非常接近伪随机数。如下图所示:
计数器模式(CTR)
CTR模式的加解密流程如下图所示。
CTR模式解决问题的思路与CBC等不同,它是对一个构建成的数据块施行加密操作,然后再用生成的密文与明文进行异或操作,生成最后的密文。由于对于各个模块的加解密操作都是独立的,因此可以平行处理。
在CTR模式中,加密操作用的构建数据块由两部分构成:Nonce和Counter。为了保证安全性,通常要求Nonce在一个Key的使用周期内保持唯一。在能够保证时间同步的系统中,经常选择时间作为Nonce。
另外,在CTR处理中,不需要对明文进行pad补0操作。
CTR模式广泛用在各种系统中,在互联网和物联网中广泛使用的CCM模式的加解密部分用的就是CTR模式。