AES字节翻转
2023-10-04 本文已影响0人
BoatingTao
AES CBC mode 加密字节反转测试
字节翻转例子很多啦,笔者直接上代码。我们的目的是使明文分组1解析后是我们的目标字符。
import base64
from Crypto.Cipher import AES
from Crypto.Util import *
from Crypto.Util.strxor import strxor
# 初始密钥, 密钥需要双方约定且保密, 且不允许传输.
key = b'1234567890123456'
# 初始化向量, 该值允许传输.
init_v = b'ABCDEFGH12345678'
def encrypt(v: bytes, plain_text: bytes):
"""
加密
:param v: 初始化向量
:param plain_text: 明文数据
:return:
"""
aes_encrypt = AES.new(key, AES.MODE_CBC, IV=v)
_pad_data = Padding.pad(plain_text, AES.block_size, "pkcs7")
_data = aes_encrypt.encrypt(_pad_data)
print('密文数据: ', _data, ', 长度: ', len(_data))
for i in range(0, len(_data), 16):
tmp = _data[i: 16+i]
print('密文分组: %s, 密文数据: %s, 长度: %s' % (str(i//16), tmp, len(tmp)))
return base64.b64encode(_data)
def decrypt(v: bytes, cipher: bytes):
"""
解密
:param v: 初始化向量
:param cipher: 密文
:return:
"""
aes_decrypt = AES.new(key, AES.MODE_CBC, IV=v)
plaintext = aes_decrypt.decrypt(base64.b64decode(cipher))
plaintext = Padding.unpad(plaintext, AES.block_size, "pkcs7")
return plaintext
def attack(cipher, local, before, target, n):
"""
公式: Cipher0[x] = P1[0] xor Cipher0[x] xor 'a'
:param cipher: 密文
:param local: 当前分组密文
:param before: 当前分组待修改字符原始明文
:param target: 当前分组待修改字符目标明文
:param n: 分组, 从0开始计算
:return:
"""
cipher = base64.b64decode(cipher)
cipher = list(cipher)
cipher[local - 16 * n] = cipher[local - 16 * n] ^ ord(before) ^ ord(target)
cipher = base64.b64encode(bytes(cipher))
return cipher
def fix_iv(p1, new_p1):
"""
公式: NewIV = p0原始 xor p0损坏 xor old_iv
:param p1: 原始明文
:param new_p1: 新的明文
:return:
"""
fixed_iv = strxor(init_v, strxor(p1[0:16], new_p1[0:16]))
print('修复后的iv: ', fixed_iv)
return fixed_iv
def test_bit_flip():
plain_text = b'0123456789abcdefjhijkl3mnopqrstuvwxyz'
print('明文数据: ', plain_text, ', 长度: ', len(plain_text))
for i in range(0, len(plain_text), 16):
tmp = plain_text[i: 16 + i]
print('明文分组: %s, 明文数据: %s, 长度: %s' % (str(i // 16), tmp, len(tmp)))
cipher = encrypt(init_v, plain_text)
print('密文Base64编码: ', cipher, end='\r\n')
print('修改原始明文第22个字符 "%s" 为任意字符,即第二组第6个数据.' % chr(plain_text[22]))
ipt = input('修改后的字符>')
n = 1
cipher = attack(cipher, 16 * n + 6, '3', ipt, n)
decipher = decrypt(init_v, cipher)
print('新的明文无法decode, 因为第0组密文已经损坏, 但字符已经翻转成功: ', decipher)
print('准备修复IV解析完整明文')
fixed_iv = fix_iv(plain_text, decipher)
decipher = decrypt(fixed_iv, cipher)
print('修复IV后解析明文:', decipher)
if __name__ == '__main__':
test_bit_flip()
明文数据: b'0123456789abcdefjhijkl3mnopqrstuvwxyz' , 长度: 37
明文分组: 0, 明文数据: b'0123456789abcdef', 长度: 16
明文分组: 1, 明文数据: b'jhijkl3mnopqrstu', 长度: 16
明文分组: 2, 明文数据: b'vwxyz', 长度: 5
密文数据: b'\x7f\xa4O)Q\xbdv~\xe7Px>l\xdf\x84\x149<\xac\xcf?\xad\xe1\x91?\xf3->k\xd8\x10\xdc\xdeON\x99\xfd\x87\xe3\xe8\xc6\x883\xff\x19\xae"\x05' , 长度: 48
密文分组: 0, 密文数据: b'\x7f\xa4O)Q\xbdv~\xe7Px>l\xdf\x84\x14', 长度: 16
密文分组: 1, 密文数据: b'9<\xac\xcf?\xad\xe1\x91?\xf3->k\xd8\x10\xdc', 长度: 16
密文分组: 2, 密文数据: b'\xdeON\x99\xfd\x87\xe3\xe8\xc6\x883\xff\x19\xae"\x05', 长度: 16
密文Base64编码: b'f6RPKVG9dn7nUHg+bN+EFDk8rM8/reGRP/MtPmvYENzeT06Z/Yfj6MaIM/8ZriIF'
修改原始明文第23个字符 "3" 为任意字符,即明文分组1中的第7个数据.
修改后的字符>A
新的明文无法decode, 因为第0组密文已经损坏, 但字符已经翻转成功: b'\x97\xd0\x8e\xa9\xe3\xb6^\xb4\xda!\xc3\xdc\x8e\xd5-\x02jhijklAmnopqrstuvwxyz'
准备修复IV解析完整明文
修复后的iv: b'\xe6\xa3\xff\xde\x92\xc5/\xcb\xd3*\x91\x8a\xd8\x87\x7f\\'
修复IV后解析明文: b'0123456789abcdefjhijklAmnopqrstuvwxyz'