图解密码技术-CTR模式

常见的分组密码以及特点

常见的分组密码有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) 计数器模式

今天来了解一下最后一个模式——CTR 模式

CTR模式(CounTeR)计数器模式

顾名思义,CTR 模式是一种累加计数进行加密来生成密钥流的流密码

又提到了流密码

在 CFB 模式中简单介绍过流密码:简单解释就是,加密的密钥流比喻为一个旋转门,我们需要加密的明文就像是一群人。这个旋转门每次只能过去一个人,当所有人一个个的通过旋转门的时候就会与当前旋转门进行一次异或运算。旋转门每一次转动都会产生一个不同的数字,这样当人通过的时候异或的结果也不一样。最终当所有人通过那么就会得到最后的加密之后的数据

那么到底什么是逐次累加来生成密钥呢?如图所示:

image-20230816221923742

CTR 加密的具体步骤

  1. 生成一个初始化计数器的值IV,其长度与明文长度一致。这个值必须是唯一的,一般情况下取值为可以递增的整数
  2. 将计数器初始值 IV 进行加密与明文分组 A 进行异或运算得到密文分组 A
  3. 然后计数器自增加密,然后与下一个明文分组异或得到下一组密文
  4. 以此类推,知道所有明文加密完成

关于计数器

我理解计数器就像一个唯一的序列号,至少对于每一组的明文来说是唯一的,计数器的长度应该与明文的长度保持一致,加入明文的长度是 128 位那么计数器的长度也应该是 128 位。计数器的初始值必须是随机的,每次加密新的明文都需要重新生成,如果使用相同的计数器则会面临重放攻击每个明文块对应一个计数器值,计数器需要逐块递增,不能重复也不能跳跃。

CTR模式中每个明文块对应一个计数器值并逐块递增的主要原因有以下几点:

  1. 保证每次异或输入的唯一性。如果计数器重复或者跳跃,多个明文块会使用同一个计数器值进行异或,这会导致密文重复,降低安全强度。
  2. 避免相同明文块产生相同密文。如果计数器不递增,相同的明文块会产生完全相同的密文,这也会泄露明文信息。
  3. 简化并行计算。计数器逐块递增可以让每个明文块的计算相互独立,没有依赖关系,便于进行并行计算。
  4. 保证误差传播有限。即使中间有密文块丢失或损坏,也只会影响该块的解密,不会导致后续所有密文无法解密。
  5. 防止字节级别的明文操作。如果允许计数器跳跃,攻击者可以通过调整计数器对应明文中的字节,来操作明文内容。
  6. 符合CTR模式的设计理念。CTR模式实质上是将块密码转变为流密码,每次加密一个明文字节或位,所以计数器必须连续。

上面的解释来自 ChatGPT

OFB 模式与 CTR 模式的对比

OFB和 CTR 模式都是属于流密码。CTR 模式使用计数器的值作为密钥流的输入而 OFB 模式使用加密的输出作为下一个密钥流的输入。加密过程如下图:

image-20230816232109495

Java 语言实现 CTR 模式加解密

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
package com.yt.mvcframework.v2.CTRDemo;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Arrays;

public class CTRExample {

public static void main(String[] args) throws Exception {
// 生成 AES 密钥
KeyGenerator kg = KeyGenerator.getInstance("AES");
SecretKey key = kg.generateKey();

// 使用 SecureRandom 生成随机 IV,长度为 16 字节
byte[] ivBytes = new byte[16];
SecureRandom.getInstanceStrong().nextBytes(ivBytes);
IvParameterSpec iv = new IvParameterSpec(ivBytes);

// 初始化用于加密的 Cipher 实例,使用 AES/CTR/PKCS5Padding 模式
Cipher encipher = Cipher.getInstance("AES/CTR/PKCS5Padding");
encipher.init(Cipher.ENCRYPT_MODE, key, iv);

// 加密明文
byte[] plaintext = "Hello, World!".getBytes();
byte[] ciphertext = encipher.doFinal(plaintext);

// 初始化用于解密的 Cipher 实例,使用相同的密钥和 IV
Cipher decipher = Cipher.getInstance("AES/CTR/PKCS5Padding");
decipher.init(Cipher.DECRYPT_MODE, key, iv);
//输出密文
System.out.println(new String(ciphertext, StandardCharsets.UTF_8));
// 解密密文
byte[] decrypted = decipher.doFinal(ciphertext);
//输出解密后的明文
System.out.println(new String(decrypted, StandardCharsets.UTF_8));

// 检查解密后的明文是否和原明文相同
System.out.println("Decryption successful? " + Arrays.equals(plaintext, decrypted));
}
}

ECB、CBC、CFB、OFB、CTR 的对比

模式 名称 优点 缺点
ECB Electronic CodeBook 电子密码本模式 简单、快速、加解密支持并行 1.明文重复密文也会重复
2.通过混淆密文就会导致明文混淆
3.解密错误的密文,对应分组也会错误
4.不能抵御重放攻击
CBC Cipher Block Chaining 密文分组链接模式 明文重复不会反映在密文中
解密支持并行计算
可以解密任意密文分组
1.对包含错误信息的密文解密时第一个分组的全部比特以及后一个分组的相应比特都会出错
2.加密不支持并行计算
CFB Cipher FeedBack 密文反馈模式 不需要填充,支持并行计算,能够解密任意分组密文 1.加密不支持并行计算
2.对包含错误信息的密文解密时第一个分组的全部比特以及后一个分组的相应比特都会出错
3.不能抵御重放攻击
OFB OutputFeedBack 输出反馈模式 不需要填充
可事先进行加密、解密的准备
加解密使用相同结构
对包含某些错误比特的密文进行解密时,只有明文中对应的比特会出错
1.不支持并行计算
2.主动攻击者反转密文分钟的某些比特时,明文分组中对应的比特位也会被反转
CTR CounTeR 计数器模式 不需要填充
可事先进行加密、解密的准备
加解密使用相同结构
对包含某些错误比特的密文进行解密时,只有明文中对应的比特会出错
支持并行计算(加解密)
1.主动攻击者反转密文分钟的某些比特时,明文分组中对应的比特位也会被反转