分组密码(Block Cipher)是一种密码对称加密算法,特点是按照固定长度的块(block)来对数据进行加密和解密。
常见的分组密码以及特点
常见的分组密码有DES、AES、SM4、Blowfish等。
分组密码的特点
- 分组长度固定,常见的块长度有64位、128位、256位等
- 可以将数据进行分组,切割为不同的数据块,每一块数据单独处理加密
- 使用对称密钥,加解密使用的是同一个密钥
- 加解密算法是确定的,相同的明文、密钥和加密算法会产生相同的密文
分组密码的工作模式
分组密码算法只能加密固定长度的分组,但是我们需要加密的明文可能会超过分组密码分组的长度,这时候就需要对明文进行切割,分成几组分别进行加密,直到所有的明文加密完成。这种方式就称之为分组密码的模式。
分组密码的主要模式
- ECB模式:(Electronic CodeBook mode) 电子密码本模式
- CBC模式:(Cipher Block Chaining mode) 密码分组链接模式
- CFB模式:(Cipher FeedBack mode) 密文反馈模式
- OFB模式:(Output FeedBack mode)输出反馈模式
- CTR模式:(CounTeR mode) 计数器模式
ECB模式
书中介绍ECB模式是将明文直接分组,然后进行分别加密处理。如图:
从图中可以直观的看出来,明文的分组和密文的分组是完全一致的。在EDB模式中,明文分组和密文分组是一一对应关系,那么如果明文中有两组以上相同的内容那么这些密文也会一样。所以,ECB模式是不安全的。
Java代码实现ECB加密
1 | public static void main(String[] args) throws Exception { |
对ECB模式的攻击
举一个例子:
假设我们有一个转账的业务,转账的数据由三部分组成;
分组A = 付款人小明
分组B=收款人小红
分组C=金额
那么使用ECB模式加密和被攻击的动作如下:
如上图,黑客只是简单的调换了密文的顺序,并没有破译密文,就已经达到攻击的目的。
原本由小明付款,现在变成了小红付款
在ECB模式中,只要将任意密文调换位置,相应的明文也会变换位置,替换密文,明文也会被替换,删除密文,明文也会被删除。所以ECB模式是不安全的。
CBC模式
CBC模式是将前一个密文分组与当前明文分组的内容混合起来进行加密,如图
在CBC模式中,首先将明文分组与前一个密文分组进行异或运算,然后再进行加密。那么,这里会有一个问题,就是第一个明文分组应该与谁进行异或运算呢?
初始化向量
当第一个明文加密这时候并不存在“前一个密文分组”。所以,我们需要准备一个初始化值,这个值的长度与分组比特位一致。我们成这个初始化值为初始化向量(Initialization Vector),通常简写为IV。
异或运算
异或是一种逻辑运算,对应的逻辑符号是 ⊕;如下表格表示了运算结果
A | B | A ⊕ B |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
异或运算有以下几个特点:
- 当两个输入相同时,输出为0。当两个输入不同时,输出为1。
- 异或运算满足交换律和结合律。
- 一个数异或它本身结果为0。
- 一个数异或0等于本身。
CBC模式的特点
因为明文分组在加密之前会和初始化向量进行异或运算,那么即使明文分组1和明文分组2的值是一样的,那么加密结果也会不同。例如:
明文分组1 = 001
明文分组2 = 001
初始化向量 = 000
明文分组1与初始化向量运算结果 001 ⊕ 000 = 001
明文分组1与明文分组2运算结果 001 ⊕ 001 = 000
因为分组1需要跟初始化向量进行异或,得到的结果必然是不同的。
Java实现CBC加密
1 | public static void main(String[] args) throws Exception { |
对CBC模式的攻击
攻击初始化向量
在加密时CBC模式需要一个初始化向量。这个数据必须是一个安全的、不可预测的随机数列。如果生成的初始化向量随机度不高,那么两个明文使用了相同的IV加密,两个密文的第一个块将是相同的。这样就会计算出第一个密文块,并且解密所有后续的块。