图解密码技术-OFB模式

常见的分组密码以及特点

常见的分组密码有DES、AES、SM4、Blowfish等。

分组密码的特点

  1. 分组长度固定,常见的块长度有64位、128位、256位等

  2. 可以将数据进行分组,切割为不同的数据块,每一块数据单独处理加密

  3. 使用对称密钥,加解密使用的是同一个密钥

  4. 加解密算法是确定的,相同的明文、密钥和加密算法会产生相同的密文

分组密码的工作模式

分组密码算法只能加密固定长度的分组,但是我们需要加密的明文可能会超过分组密码分组的长度,这时候就需要对明文进行切割,分成几组分别进行加密,直到所有的明文加密完成。这种方式就称之为分组密码的模式

分组密码的主要模式

  1. ECB模式:(Electronic CodeBook mode) 电子密码本模式
  2. CBC模式:(Cipher Block Chaining mode) 密码分组链接模式
  3. CFB模式:(Cipher FeedBack mode) 密文反馈模式
  4. OFB模式:(Output FeedBack mode)输出反馈模式
  5. CTR模式:(CounTeR mode) 计数器模式

今天来了解一下OFB模式

OFB模式(Output Feedback Mode)

OFB模式我们称之为密文反馈模式。它的工作原理跟CFB模式非常相似,但是OCB模式是利用前一个密文块来作为下一次加密的密钥。如图所示

image-20230815215333577

在看一下CFB模式的图

image-20230810223911494

下面是书中对这两种模式区别的介绍

OFB 模式和CFB模式的区别仅仅在于密码算法的输入。ps:我没懂….

CFB 模式中,密码算法的输入是前一个密文分组,也就是将密文分组反馈到密码算法中,因此得名“密文反馈模式”

相对的,OFB模式中,密码算法的输入则是密码算法的前一个输出。也就是将输出反馈给密码算法。因此得名“输出反馈模式”

上面的两段话,我读了很多遍。有一个疑问是:OFB模式中,密码算法的输入则是密码算法的前一个输出。这句话怎么理解呢?

OFB模式的加密过程是:

  1. 首先利用初始化向量IV进行一次加密运算,生成第一个密钥流块K1。
  2. 将密钥流块K1与第一个明文块P1进行异或,得到第一个密文块C1。
  3. 将刚刚生成的密文块C1再次进行加密,生成下一个密钥流块K2。
  4. K2同第二个明文块P2进行异或,生成密文块C2。
  5. 依此类推,重复步骤3和4,直到全部明文加密完毕。

JAVA 代码实现OFB模式加密和解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.yt.mvcframework.v2.OFBDemo;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;

public class OFBEncrypt {

public static void main(String[] args) throws Exception {

/*
OFB模式加密示意图:

+------------+ +------------+
| | | |
| 明文P1 | | 密钥流 |
| | | K1 |
+----+-------+ +------+-----+
| |
| |
| |
+----v-------+ |
| | |
| 密文C1 <-------+
| |
+------------+

*/

// 1. 生成AES密钥
KeyGenerator kg = KeyGenerator.getInstance("AES");
SecretKey key = kg.generateKey();

// 2. 初始化一个全零的IV
IvParameterSpec iv = new IvParameterSpec(new byte[16]);

// 3. 获取Cipher实例,指定OFB模式
Cipher cipher = Cipher.getInstance("AES/OFB/NoPadding");

// 4. 初始化Cipher为加密模式,使用key和iv
cipher.init(Cipher.ENCRYPT_MODE, key, iv);

// 5. 明文
byte[] plaintext = "Hello World".getBytes();

// 6. 加密明文,得到密文
byte[] ciphertext = cipher.doFinal(plaintext);

System.out.println("OFB Encryption: " + new String(ciphertext));
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] decrypted = cipher.doFinal(ciphertext);
System.out.println("OFB Decryption: " + new String(decrypted));
}

}