电子密码本模式(ECB)
用相同的密钥分别对明文分组单独加密。
也就是将铭文分组成相同大小的明文块(不够就填充),使用相同的密钥进行加密
优点:每个数据块独立加密,可以并行加密,效率高,操作简单
缺点:使用了相同的密钥,当明文相同时会产生相同的密文,不具备数据完整性保护
适合对短消息的加密传输
密文分组链接模式(CBC)
将前一个密文块与当前需要加密的明文块进行异或运算后再进行加密操作
需要给定一个初始向量
用于第一个明文块的加密 加密算法的输入是上一个密文分组和下一个明文分组的异或
优点:每个密文块加密和前一个密文块相关(扩散效果)
缺点:不适合并行加密处理
适用于文件加密,非实时加密
密文反馈模式(CFB)
将前一个密文块作为输入进行加密,生成一个密钥流,再与当前明文块进项异或运算得到密文块
明文本身没有进行加密算法操作,而是与上一个输出密文块加密后的数据进行异或得到新的密文块
流密码的工作模式
和
的区别,一个是先异或再加密,一个是先加密再异或 可以是任意的,不需要填充,类似于流密码的加密操作(异或,移位) 优点:可变长度的加密操作,实时性,可以部分解密数据
缺点:密文分组的错误传播敏感,不适合并行处理,需要设置初始变量
适用于流加密和对特定部分数据进行随机访问的场景
输出反馈模式(OFB)
将前一个加密算法的输出作为输入进行加密,生成一个密钥流,再于当前明文块进行异或运算得到密文块
和
的对比,两者的明文都没参加加密算法 可变长度的加密操作,实时性,对密文分组的错误不敏感
传输错误不可恢复,无法提供数据完整性保护,不支持并行加密
适用于实时数据流加密和随机访问的场景
计数器模式(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
39from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util import Counter
from hashlib import sha256
from secret import flag
import os
def padding(msg):
return msg + os.urandom(16 - len(msg) % 16)
msg = b"where is the flag? Key in my Heart/Counter!!!!"
key = b"I w0nder how????"
assert len(msg) == 46
assert len(key) == 16
enc_key = os.urandom(16)
initial_value = bytes_to_long(enc_key)
hash = sha256(str(initial_value).encode()).hexdigest()
aes = AES.new(enc_key, AES.MODE_ECB)
enc_flag = aes.encrypt(padding(flag))
ctr = Counter.new(AES.block_size * 8, initial_value=initial_value)
aes = AES.new(key, counter=ctr, mode=AES.MODE_CTR)
enc = aes.encrypt(msg)
print("enc = {}".format(enc[-16:]))
print("enc_flag = {}".format(enc_flag))
print("hash = {}".format(hash))
'''
enc = b'\xbe\x9bd\xc6\xd4=\x8c\xe4\x95bi\xbc\xe01\x0e\xb8'
enc_flag = b'\xb2\x97\x83\x1dB\x13\x9b\xc2\x97\x9a\xa6+M\x19\xd74\xd2-\xc0\xb6\xba\xe8ZE\x0b:\x14\xed\xec!\xa1\x92\xdfZ\xb0\xbd\xb4M\xb1\x14\xea\xd8\xee\xbf\x83\x16g\xfa'
hash = efb07225b3f1993113e104757210261083c79de50f577b3f0564368ee7b25eeb
'''题解
读代码,发现一共涉及两个
加密过程,一个是正常的 模式,一个则是 模式 我们需要求
也就是需要知道解密 这个加密过程来获得 ,继而得到 解密 就可以 对着上述的
模式的加密流程图, 字节的明文被分为 三段, 是 字节 使用密文的后
字节和明文的后 字节异或得到加密后的 此时求出的
是没有填充的,在 模式中,填充是固定向后填充 所以需要爆破后两位字节,然后解密(
模式解密就可以)得到当前加密块的计数器的值,那么 就是当前的计数器值减 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
29from Crypto.Util.number import *
import hashlib
from Crypto.Cipher import AES
import time
msg = b"where is the flag? Key in my Heart/Counter!!!!"
key = b"I w0nder how????"
enc = b'\xbe\x9bd\xc6\xd4=\x8c\xe4\x95bi\xbc\xe01\x0e\xb8'
enc_flag = b'\xb2\x97\x83\x1dB\x13\x9b\xc2\x97\x9a\xa6+M\x19\xd74\xd2-\xc0\xb6\xba\xe8ZE\x0b:\x14\xed\xec!\xa1\x92\xdfZ\xb0\xbd\xb4M\xb1\x14\xea\xd8\xee\xbf\x83\x16g\xfa'
hash = 'efb07225b3f1993113e104757210261083c79de50f577b3f0564368ee7b25eeb'
msg_3 = msg[-14:]
enc_3 = enc[-14:]
key_1 = bytes_to_long(msg_3) ^ bytes_to_long(enc_3)
for i in range(256):
for j in range(256):
key1 = long_to_bytes(key_1) + bytes([i]) + bytes([j])
# time.sleep(5)
aes1 = AES.new(key, AES.MODE_ECB)
counter = aes1.decrypt(key1)
initial_value = bytes_to_long(counter) - 2
if hash == hashlib.sha256(str(initial_value).encode()).hexdigest():
enc_key = long_to_bytes(initial_value)
aes2 = AES.new(enc_key, AES.MODE_ECB)
flag = aes2.decrypt(enc_flag)
print(flag)
break
# b'flag{9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d}@6\xf5R\xda\xa9'
学习参考:【分组密码的工作模式】|分组密码 | 密码学 | 信息安全 | ECB | CBC | CFB| OF B| CTR|