各加密算法比较(对称加密篇)

[]

对称加密算法

定义:
对称加密算法使用相同密钥加密和解密,拥有运算速度快,效率高,密钥短的优点。但由于对称加密使用同一密钥,因此难以进行安全的密钥分发,常结合非对称加密使用,如在SSL/TLS握手后通过ECDHE算法协商密钥用于后续通信

分组密码算法

定义:分组密码将固定长度的明文分组作为输入,通过一系列复杂的变换,在同一个密钥的控制下,输出一个等长的密文分组.

数学原理

定义

主要结构:
1.Feistel结构

2.2SPN结构

S盒正确性验证

线线

常见加密模式

1.ECB(电子密码本)

2.CBC密码块链接

3.CTR(计数器模式)
访
3.1GCM(CTR+Ghash)

3.2CCM(CBC with MAC)

注:
CTR与GCM是最流行的分组密码模式,GCM在CTR基础上增加了完整性保护能有效防止中间人攻击(MITM)

现代分组设计

1.ARX结构

2.轻量级密码

经典设计

1.DES(Date Encryption Standard, 数据加密标准)

2.AES(Advanced Encryption Standard, 高级加密标准)

2.1 AES轮函数

攻击方式

暴力破解

彩虹表攻击
①基本原理

②具体实例

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
import hashlib
import os
from typing import List, Tuple, Optional
import pickle

class RainbowTable:
def __init__(self, chain_length: int = 1000, num_chains: int = 10000):
"""
初始化彩虹表
:param chain_length: 链长度
:param num_chains: 链数量
"""
self.chain_length = chain_length
self.num_chains = num_chains
self.table: List[Tuple[str, str]] = [] # (起始点, 终点)对

def reduce_function(self, hash_value: str, position: int) -> str:
"""
归约函数:将哈希值映射回6位数字密码
"""
# 使用哈希值的一部分生成数字
hash_int = int(hash_value[:8], 16)
reduced = (hash_int + position) % 1000000 # 6位数字
return f"{reduced:06d}"

def hash_function(self, password: str) -> str:
"""MD5哈希函数"""
return hashlib.md5(password.encode()).hexdigest()

def generate_chain(self, start_password: str) -> str:
"""生成一条哈希链"""
current = start_password

for i in range(self.chain_length):
# 哈希
hash_value = self.hash_function(current)
# 归约(每列使用不同的归约函数)
if i == self.chain_length - 1:
return current # 最后一个点作为终点
current = self.reduce_function(hash_value, i)

return current

def build_table(self, password_space: List[str]):
"""构建彩虹表"""
print(f"正在构建彩虹表...")
print(f"链长度: {self.chain_length}")
print(f"链数量: {self.num_chains}")

for i in range(self.num_chains):
start_password = password_space[i % len(password_space)]
end_password = self.generate_chain(start_password)
self.table.append((start_password, end_password))

if (i + 1) % 1000 == 0:
print(f"已生成 {i + 1}/{self.num_chains} 条链")

# 按终点排序以便二分查找
self.table.sort(key=lambda x: x[1])
print("彩虹表构建完成!")

def save_table(self, filename: str):
"""保存彩虹表到文件"""
with open(filename, 'wb') as f:
pickle.dump({
'chain_length': self.chain_length,
'num_chains': self.num_chains,
'table': self.table
}, f)
print(f"彩虹表已保存到 {filename}")

def load_table(self, filename: str):
"""从文件加载彩虹表"""
with open(filename, 'rb') as f:
data = pickle.load(f)
self.chain_length = data['chain_length']
self.num_chains = data['num_chains']
self.table = data['table']
print(f"彩虹表已从 {filename} 加载")

def search_hash(self, target_hash: str) -> Optional[str]:
"""在彩虹表中搜索哈希值对应的密码"""

# 从最后一列开始向前搜索
for column in range(self.chain_length - 1, -1, -1):
current = target_hash

# 从当前列向链的起点移动
for pos in range(column, self.chain_length):
if pos == self.chain_length - 1:
# 在最后一列,查找终点
end_point = self.reduce_function(current, pos)

# 二分查找终点
left, right = 0, len(self.table) - 1
while left <= right:
mid = (left + right) // 2
if self.table[mid][1] == end_point:
# 找到链,重新计算
password = self.reconstruct_password(
self.table[mid][0], target_hash
)
if password:
return password
break
elif self.table[mid][1] < end_point:
left = mid + 1
else:
right = mid - 1

break

# 归约并哈希
reduced = self.reduce_function(current, pos)
current = self.hash_function(reduced)

return None

def reconstruct_password(self, start_password: str, target_hash: str) -> Optional[str]:
"""从起点重建密码"""
current = start_password

for i in range(self.chain_length):
hash_value = self.hash_function(current)

if hash_value == target_hash:
return current

if i == self.chain_length - 1:
break

current = self.reduce_function(hash_value, i)

return None

def crack_password(self, hash_to_crack: str) -> Optional[str]:
"""破解密码的主函数"""
print(f"\n尝试破解哈希: {hash_to_crack}")

password = self.search_hash(hash_to_crack)

if password:
print(f"找到密码: {password}")
return password
else:
print("未在彩虹表中找到密码")
return None

# 使用示例
def demonstrate_rainbow_table():
"""演示彩虹表攻击"""

# 生成测试密码空间(6位数字密码)
password_space = [f"{i:06d}" for i in range(10000, 20000)] # 简化示例

# 创建彩虹表
rt = RainbowTable(chain_length=100, num_chains=1000)

# 构建彩虹表(或加载已存在的)
table_file = "rainbow_table.pkl"
if os.path.exists(table_file):
rt.load_table(table_file)
else:
rt.build_table(password_space)
rt.save_table(table_file)

# 测试破解
test_password = "123456"
test_hash = hashlib.md5(test_password.encode()).hexdigest()

# 从彩虹表中移除测试密码以确保公平性
# (在实际中,我们会用未知的哈希)
print(f"\n测试哈希: {test_hash}")
print(f"预期密码: {test_password}")

# 尝试破解
cracked = rt.crack_password(test_hash)

if cracked and cracked == test_password:
print("✓ 破解成功!")
else:
print("✗ 破解失败")

return rt

# 运行演示
if __name__ == "__main__":
demonstrate_rainbow_table()

侧信道攻击

  1. 计时攻击

原理:
某些密码操作的执行时间依赖于密钥或数据,攻击者通过精确测量时间来推断密钥

实例:针对AES的计时攻击

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import time
import numpy as np
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
import matplotlib.pyplot as plt

class VulnerableAES:
"""存在计时漏洞的AES实现"""

def __init__(self, key):
self.key = key
self.cipher = AES.new(key, AES.MODE_ECB)

def vulnerable_encrypt(self, plaintext):
"""存在计时漏洞的加密函数"""
# 模拟基于数据的条件分支
start_time = time.perf_counter_ns()

# 模拟缓存访问时间差异
if plaintext[0] & 0x01: # 密钥相关分支
# 模拟额外计算
_ = sum(self.key) % 256

# 实际加密
ciphertext = self.cipher.encrypt(plaintext)

# 更多模拟的时间差异
if ciphertext[-1] > 128:
_ = max(self.key)

end_time = time.perf_counter_ns()
return ciphertext, end_time - start_time

class TimingAttackSimulator:
"""AES计时攻击模拟器"""

def __init__(self, real_key):
self.real_key = real_key
self.aes = VulnerableAES(real_key)

def collect_timing_data(self, num_samples=1000):
"""收集计时数据"""
print(f"收集 {num_samples} 个计时样本...")

# 测试不同明文下的加密时间
timings = []
plaintexts = []

for i in range(num_samples):
pt = get_random_bytes(16)
ct, timing = self.aes.vulnerable_encrypt(pt)
timings.append(timing)
plaintexts.append(pt)

return np.array(plaintexts), np.array(timings)

def analyze_first_byte(self, plaintexts, timings):
"""分析第一个字节的计时泄露"""
print("\n分析第一个字节的计时模式...")

# 按第一个字节的LSB分组
groups = {0: [], 1: []}
for pt, t in zip(plaintexts, timings):
bit = pt[0] & 0x01
groups[bit].append(t)

# 计算平均时间差异
mean_0 = np.mean(groups[0])
mean_1 = np.mean(groups[1])

print(f"LSB=0 的平均时间: {mean_0:.2f} ns")
print(f"LSB=1 的平均时间: {mean_1:.2f} ns")
print(f"时间差: {abs(mean_1 - mean_0):.2f} ns")

# 统计显著性
from scipy import stats
t_stat, p_value = stats.ttest_ind(groups[0], groups[1])
print(f"T检验 p值: {p_value:.6f}")

return abs(mean_1 - mean_0) > 10 # 假设10ns为显著阈值

def visualize_timings(self, plaintexts, timings):
"""可视化计时数据"""
plt.figure(figsize=(12, 6))

# 按第一个字节的值分组
first_bytes = [pt[0] for pt in plaintexts]

plt.subplot(1, 2, 1)
plt.scatter(first_bytes, timings, alpha=0.5)
plt.xlabel('First Byte Value')
plt.ylabel('Encryption Time (ns)')
plt.title('Timing vs First Byte')

plt.subplot(1, 2, 2)
# 直方图
plt.hist(timings, bins=50, alpha=0.7)
plt.xlabel('Encryption Time (ns)')
plt.ylabel('Frequency')
plt.title('Timing Distribution')

plt.tight_layout()
plt.show()

# 演示计时攻击
def demonstrate_timing_attack():
"""演示计时攻击"""
print("AES计时攻击演示")
print("=" * 50)

# 设置真实密钥(攻击者未知)
real_key = get_random_bytes(16)
print(f"真实密钥 (hex): {real_key.hex()}")

# 创建攻击模拟器
simulator = TimingAttackSimulator(real_key)

# 收集数据
plaintexts, timings = simulator.collect_timing_data(num_samples=2000)

# 分析泄露
is_vulnerable = simulator.analyze_first_byte(plaintexts, timings)

if is_vulnerable:
print("\n✓ 检测到计时泄露!")
print("攻击者可能推断出密钥比特信息")
else:
print("\n✗ 未检测到显著计时泄露")

# 可视化
simulator.visualize_timings(plaintexts, timings)

return is_vulnerable

# demonstrate_timing_attack()

当前地位
分组密码是最常见的对称加密,其高安全性和高性能使得它广泛应用于各种场景但它通常需要硬件加速才能达到最佳性能,因此在arm/aarch等不具备硬件加速的平台上常使用流密码来替代分组密码


流密码

定义:
将明文视为位或字节流,使用由短密钥通过伪随机生成器产生的连续密钥流与明文逐位进行异或运算来加密

数学原理

注:
其中: 第 个明文比特
: 第 个密钥流比特
: 第 个密文比特

数学结构

  1. LFSR
    线线
  2. A5/1


现代密码学设计

  1. eSTREAM项目优胜者
  2. Trivium


经典算法

  1. RC4(已弃用

    实例
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
57
58
59
60
61
62
63
64
class RC4Secure:

def __init__(self, key, drop_bytes=3072):
"""
key: 加密密钥
drop_bytes: 丢弃的初始字节数
常见值: 256, 512, 768, 1024, 3072
"""
if len(key) < 5 or len(key) > 256:
raise ValueError("Key length should be between 40 and 2048 bits")

self.key = key
self.drop_bytes = drop_bytes

# 初始化
self._init_state()

# 丢弃初始密钥流字节
self._discard_initial_bytes()

def _init_state(self):
"""初始化S盒和状态"""
self.S = list(range(256))
j = 0
key_len = len(self.key)

# KSA - 使用密钥初始化S盒
for i in range(256):
j = (j + self.S[i] + self.key[i % key_len]) & 0xFF
self.S[i], self.S[j] = self.S[j], self.S[i]

self.i = 0
self.j = 0

def _discard_initial_bytes(self):
"""丢弃初始密钥流字节"""
for _ in range(self.drop_bytes):
self._generate_keystream_byte()

def _generate_keystream_byte(self):
"""生成一个密钥流字节"""
self.i = (self.i + 1) & 0xFF
self.j = (self.j + self.S[self.i]) & 0xFF
self.S[self.i], self.S[self.j] = self.S[self.j], self.S[self.i]

return self.S[(self.S[self.i] + self.S[self.j]) & 0xFF]

def encrypt(self, plaintext):
"""加密数据"""
ciphertext = bytearray(len(plaintext))

for idx, byte in enumerate(plaintext):
ciphertext[idx] = byte ^ self._generate_keystream_byte()

return bytes(ciphertext)

def decrypt(self, ciphertext):
"""解密数据 - RC4中加密解密相同"""
return self.encrypt(ciphertext) # 对称操作

def reset(self):
"""重置状态以便重新使用密钥"""
self._init_state()
self._discard_initial_bytes()
  1. salsa20

    实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 安装:pip install cryptography
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms
from cryptography.hazmat.backends import default_backend

def salsa20_encrypt(key, nonce, plaintext):
"""使用cryptography库的Salsa20加密"""
cipher = Cipher(algorithms.ChaCha20(key, nonce), mode=None, backend=default_backend())
encryptor = cipher.encryptor()
ciphertext = encryptor.update(plaintext)
return ciphertext

# 使用示例
key = b'0' * 32 # 256-bit key
nonce = b'0' * 16 # 128-bit nonce
plaintext = b"Hello, Salsa20!"
ciphertext = salsa20_encrypt(key, nonce, plaintext)

2.1 chacha20

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def chacha20_encrypt(key, iv, plaintext):
"""ChaCha20流加密"""
ciphertext = bytearray()
counter = 1

for i in range(0, len(plaintext), 64):
# 生成密钥流块
keystream = chacha20_block(key, counter, iv)

# 异或加密
block_len = min(64, len(plaintext) - i)
for j in range(block_len):
ciphertext.append(plaintext[i + j] ^ keystream[j])

counter += 1

return bytes(ciphertext)

2.1.1 chaochao20poly1305
ChaCha20 状态矩阵定义
初始状态为 4x4 矩阵,每个元素为 32 位字(共 512 位)
S =
其中初始值

实例

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
# 安装:pip install cryptography
from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305
from cryptography.exceptions import InvalidTag
import os

def chacha20poly1305_cryptography():
"""使用cryptography库的ChaCha20-Poly1305"""

# 生成随机密钥和nonce
key = ChaCha20Poly1305.generate_key() # 256-bit key
chacha = ChaCha20Poly1305(key)

# 生成随机nonce(96-bit)
nonce = os.urandom(12)

# 要加密的数据
plaintext = b"Secret message to encrypt"
associated_data = b"Metadata that should be authenticated but not encrypted"

# 加密
ciphertext = chacha.encrypt(nonce, plaintext, associated_data)
print(f"Nonce: {nonce.hex()}")
print(f"Ciphertext (encrypted): {ciphertext.hex()}")

# 解密(验证完整性)
try:
decrypted = chacha.decrypt(nonce, ciphertext, associated_data)
print(f"Decrypted: {decrypted}")
print("✓ Authentication successful")
except InvalidTag:
print("✗ Authentication failed - data tampered!")

return key, nonce, ciphertext

# 使用示例
key, nonce, ciphertext = chacha20poly1305_cryptography()
  1. ZUC(祖冲之算法)
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
class ZUCBasic:
"""ZUC-128流密码基础实现"""

# 常数
D = [
0x44D7, 0x26BC, 0x626B, 0x135E, 0x5789, 0x35E2, 0x7135, 0x09AF,
0x4D78, 0x2F13, 0x6BC4, 0x1AF1, 0x5E26, 0x3C4D, 0x789A, 0x47AC
]

def __init__(self, key, iv):
"""
初始化ZUC算法
key: 16字节密钥 (128-bit)
iv: 16字节初始向量 (128-bit)
"""
if len(key) != 16:
raise ValueError("Key must be 16 bytes (128-bit)")
if len(iv) != 16:
raise ValueError("IV must be 16 bytes (128-bit)")

self.key = key
self.iv = iv

# 内部状态寄存器 (16个31-bit整数)
self.S = [0] * 16

# 初始化
self._key_iv_load()
self._initialization()

def _key_iv_load(self):
"""密钥和IV加载到线性反馈移位寄存器(LFSR)"""
# 将key和iv转换为16-bit字
k = [int.from_bytes(self.key[i:i+2], 'big') for i in range(0, 16, 2)]
iv_words = [int.from_bytes(self.iv[i:i+2], 'big') for i in range(0, 16, 2)]

# 加载到LFSR (S0-S15)
for i in range(16):
self.S[i] = ((k[i] << 16) & 0x7FFFFFFF) | (iv_words[i] & 0xFFFF)

def _bit_reorganization(self):
"""比特重组"""
X0 = ((self.S[15] & 0x7FFF8000) << 1) | (self.S[14] & 0xFFFF)
X1 = ((self.S[11] & 0xFFFF) << 16) | (self.S[9] >> 15)
X2 = ((self.S[7] & 0xFFFF) << 16) | (self.S[5] >> 15)
X3 = ((self.S[2] & 0xFFFF) << 16) | (self.S[0] >> 15)

return X0, X1, X2, X3

def _lfsr_initialization_mode(self, u):
"""LFSR初始化模式"""
# LFSR反馈计算
v = (self.S[0] << 8) & 0x7FFFFFFF
v = self._add31(v, self.S[0] >> 23)
v = self._add31(v, (self.S[4] << 20) & 0x7FFFFFFF)
v = self._add31(v, self.S[4] >> 11)
v = self._add31(v, (self.S[10] << 21) & 0x7FFFFFFF)
v = self._add31(v, self.S[10] >> 10)
v = self._add31(v, (self.S[13] << 17) & 0x7FFFFFFF)
v = self._add31(v, self.S[13] >> 14)
v = self._add31(v, (self.S[15] << 15) & 0x7FFFFFFF)
v = self._add31(v, self.S[15] >> 16)

# 加u模2^31-1
if u == 0:
u = 0x7FFFFFFF
v = self._add31(v, u)

# LFSR移位
for i in range(15):
self.S[i] = self.S[i + 1]
self.S[15] = v

def _lfsr_work_mode(self):
"""LFSR工作模式"""
# 计算反馈
v = (self.S[0] << 8) & 0x7FFFFFFF
v = self._add31(v, self.S[0] >> 23)
v = self._add31(v, (self.S[4] << 20) & 0x7FFFFFFF)
v = self._add31(v, self.S[4] >> 11)
v = self._add31(v, (self.S[10] << 21) & 0x7FFFFFFF)
v = self._add31(v, self.S[10] >> 10)
v = self._add31(v, (self.S[13] << 17) & 0x7FFFFFFF)
v = self._add31(v, self.S[13] >> 14)
v = self._add31(v, (self.S[15] << 15) & 0x7FFFFFFF)
v = self._add31(v, self.S[15] >> 16)

# LFSR移位
for i in range(15):
self.S[i] = self.S[i + 1]
self.S[15] = v

def _add31(self, a, b):
"""模2^31-1加法"""
result = (a + b) & 0x7FFFFFFF
carry = (a + b) >> 31
return (result + carry) & 0x7FFFFFFF

def _f_function(self, X0, X1, X2):
"""F函数:非线性函数"""
# 这里简化实现,实际需要S-box和线性变换
W = (X0 ^ X1) + X2
W1 = (X0 + X1) ^ X2
return W & 0xFFFFFFFF, W1 & 0xFFFFFFFF

def _initialization(self):
"""初始化阶段"""
# 临时变量
R1 = 0
R2 = 0

# 32轮初始化
for _ in range(32):
X0, X1, X2, X3 = self._bit_reorganization()
W, W1 = self._f_function(X0, X1, X2)

# LFSR初始化模式
self._lfsr_initialization_mode(W >> 1)

# 更新R1, R2
R1 = X3 ^ R1
R2 = W1 ^ R2

# 最终比特重组
X0, X1, X2, X3 = self._bit_reorganization()
W, W1 = self._f_function(X0, X1, X2)

# 丢弃第一个输出
self._lfsr_work_mode()

def generate_keystream(self, length):
"""生成密钥流"""
keystream = bytearray()

for _ in range(0, length, 4):
# 比特重组
X0, X1, X2, X3 = self._bit_reorganization()

# F函数
W, _ = self._f_function(X0, X1, X2)

# 生成32-bit密钥字
Z = W ^ X3

# 添加到密钥流
keystream.extend(Z.to_bytes(4, 'big'))

# LFSR工作模式
self._lfsr_work_mode()

return bytes(keystream[:length])

def encrypt(self, plaintext):
"""加密数据"""
keystream = self.generate_keystream(len(plaintext))

ciphertext = bytearray()
for i in range(len(plaintext)):
ciphertext.append(plaintext[i] ^ keystream[i])

return bytes(ciphertext)

def decrypt(self, ciphertext):
"""解密数据(与加密相同)"""
return self.encrypt(ciphertext)


# 测试基础实现
def test_zuc_basic():
print("=== ZUC-128 基础实现测试 ===")

# 测试向量 (示例)
key = bytes.fromhex("00000000000000000000000000000000")
iv = bytes.fromhex("00000000000000000000000000000000")

zuc = ZUCBasic(key, iv)

# 生成密钥流
keystream = zuc.generate_keystream(16)
print(f"密钥流 (前16字节): {keystream.hex()}")

# 加密测试
plaintext = b"ZUC Algorithm Test"
ciphertext = zuc.encrypt(plaintext)
print(f"明文: {plaintext}")
print(f"密文: {ciphertext.hex()}")

# 解密测试
zuc2 = ZUCBasic(key, iv)
decrypted = zuc2.decrypt(ciphertext)
print(f"解密: {decrypted}")
print(f"解密成功: {plaintext == decrypted}")

注:祖冲之算法由中国国家密码管理局设计发布是我国独立设计的流密码广泛用于4G/5G通信


攻击方式

侧信道攻击

  1. 时序攻击

    实例
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
class TimingAttackDemo:
"""流密码时序攻击演示"""

def vulnerable_rc4_compare(self, a, b):
"""脆弱的字符串比较(易受时序攻击)"""
if len(a) != len(b):
return False

# 逐个字节比较 - 会在第一个不同字节处返回
for i in range(len(a)):
if a[i] != b[i]:
return False
return True

def safe_rc4_compare(self, a, b):
"""安全的恒定时间比较"""
if len(a) != len(b):
return False

result = 0
for i in range(len(a)):
result |= a[i] ^ b[i] # 使用位运算,避免分支
return result == 0

def simulate_timing_attack(self):
"""模拟时序攻击"""
import time

secret_tag = b"secret_tag_12345"

# 攻击者尝试猜测的标签
test_tags = [
b"a" * len(secret_tag), # 完全错误
b"secret_tag_1234a", # 最后一位不同
b"secret_tag_12345", # 完全正确
]

print("时序攻击演示:")
for tag in test_tags:
# 测量比较时间
start = time.perf_counter_ns()
for _ in range(10000): # 多次测量减少噪声
self.vulnerable_rc4_compare(tag, secret_tag)
elapsed = time.perf_counter_ns() - start

print(f"猜测标签: {tag}")
print(f" 平均比较时间: {elapsed/10000:.0f} ns")
print(f" 结果: {self.vulnerable_rc4_compare(tag, secret_tag)}")
print()
  1. 差分功耗攻击

    实例
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
57
58
import numpy as np
from scipy import signal

class PowerAnalysisAttack:
"""功耗分析攻击模拟"""

def __init__(self):
# 模拟不同操作的功耗特征
self.power_profiles = {
'xor_0': 0.1, # XOR 0 - 低功耗
'xor_1': 1.0, # XOR 1 - 高功耗
'load_key': 2.0, # 加载密钥
'sbox_lookup': 1.5, # S盒查找
}

def simulate_rc4_ksa_power(self, key_byte, sbox_value):
"""模拟RC4 KSA阶段的功耗"""
power_trace = []

# 模拟密钥调度算法
for i in range(256):
# S盒访问
power_trace.append(self.power_profiles['sbox_lookup'])

# 密钥字节加载
power_trace.append(self.power_profiles['load_key'])

# 模加运算(根据实际硬件实现)
if (sbox_value + key_byte) % 256 < 128:
power_trace.append(0.8) # 低比特位操作
else:
power_trace.append(1.2) # 高比特位操作

return power_trace

def dpa_attack_simulation(self):
"""差分功耗分析(DPA)攻击模拟"""
print("差分功耗分析(DPA)攻击模拟:")

# 模拟多个加密操作的功耗轨迹
traces = []
secret_key_byte = 0xAB # 要攻击的密钥字节

for test_input in range(256):
# 生成模拟功耗轨迹
trace = self.simulate_rc4_ksa_power(test_input, test_input)

# 添加噪声
noise = np.random.normal(0, 0.1, len(trace))
trace = np.array(trace) + noise

traces.append(trace)

# 差分分析
correct_trace = traces[secret_key_byte]

print("通过统计分析可以识别出密钥相关的功耗模式...")
return traces

目前地位:
流密码在现代密码学中处于高效、高安全性的专用加密技术地位。凭借其加密速度快、适应流数据处理、硬件实现资源少等优势,广泛应用于实时网络通信(如TLS中的ChaCha20)、无线安全和大规模数据存储,成为高可靠性安全需求的首选