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'
上一篇下一篇

猜你喜欢

热点阅读