AES CBC mode 加密字節(jié)反轉(zhuǎn)測(cè)試
字節(jié)翻轉(zhuǎn)例子很多啦神凑,筆者直接上代碼。我們的目的是使明文分組1解析后是我們的目標(biāo)字符之斯。
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: 明文數(shù)據(jù)
: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('密文數(shù)據(jù): ', _data, ', 長(zhǎng)度: ', len(_data))
for i in range(0, len(_data), 16):
tmp = _data[i: 16+i]
print('密文分組: %s, 密文數(shù)據(jù): %s, 長(zhǎng)度: %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: 當(dāng)前分組密文
:param before: 當(dāng)前分組待修改字符原始明文
:param target: 當(dāng)前分組待修改字符目標(biāo)明文
:param n: 分組, 從0開(kāi)始計(jì)算
: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('修復(fù)后的iv: ', fixed_iv)
return fixed_iv
def test_bit_flip():
plain_text = b'0123456789abcdefjhijkl3mnopqrstuvwxyz'
print('明文數(shù)據(jù): ', plain_text, ', 長(zhǎng)度: ', len(plain_text))
for i in range(0, len(plain_text), 16):
tmp = plain_text[i: 16 + i]
print('明文分組: %s, 明文數(shù)據(jù): %s, 長(zhǎng)度: %s' % (str(i // 16), tmp, len(tmp)))
cipher = encrypt(init_v, plain_text)
print('密文Base64編碼: ', cipher, end='\r\n')
print('修改原始明文第22個(gè)字符 "%s" 為任意字符,即第二組第6個(gè)數(shù)據(jù).' % chr(plain_text[22]))
ipt = input('修改后的字符>')
n = 1
cipher = attack(cipher, 16 * n + 6, '3', ipt, n)
decipher = decrypt(init_v, cipher)
print('新的明文無(wú)法decode, 因?yàn)榈?組密文已經(jīng)損壞, 但字符已經(jīng)翻轉(zhuǎn)成功: ', decipher)
print('準(zhǔn)備修復(fù)IV解析完整明文')
fixed_iv = fix_iv(plain_text, decipher)
decipher = decrypt(fixed_iv, cipher)
print('修復(fù)IV后解析明文:', decipher)
if __name__ == '__main__':
test_bit_flip()
明文數(shù)據(jù): b'0123456789abcdefjhijkl3mnopqrstuvwxyz' , 長(zhǎng)度: 37
明文分組: 0, 明文數(shù)據(jù): b'0123456789abcdef', 長(zhǎng)度: 16
明文分組: 1, 明文數(shù)據(jù): b'jhijkl3mnopqrstu', 長(zhǎng)度: 16
明文分組: 2, 明文數(shù)據(jù): b'vwxyz', 長(zhǎng)度: 5
密文數(shù)據(jù): 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' , 長(zhǎng)度: 48
密文分組: 0, 密文數(shù)據(jù): b'\x7f\xa4O)Q\xbdv~\xe7Px>l\xdf\x84\x14', 長(zhǎng)度: 16
密文分組: 1, 密文數(shù)據(jù): b'9<\xac\xcf?\xad\xe1\x91?\xf3->k\xd8\x10\xdc', 長(zhǎng)度: 16
密文分組: 2, 密文數(shù)據(jù): b'\xdeON\x99\xfd\x87\xe3\xe8\xc6\x883\xff\x19\xae"\x05', 長(zhǎng)度: 16
密文Base64編碼: b'f6RPKVG9dn7nUHg+bN+EFDk8rM8/reGRP/MtPmvYENzeT06Z/Yfj6MaIM/8ZriIF'
修改原始明文第23個(gè)字符 "3" 為任意字符,即明文分組1中的第7個(gè)數(shù)據(jù).
修改后的字符>A
新的明文無(wú)法decode, 因?yàn)榈?組密文已經(jīng)損壞, 但字符已經(jīng)翻轉(zhuǎn)成功: b'\x97\xd0\x8e\xa9\xe3\xb6^\xb4\xda!\xc3\xdc\x8e\xd5-\x02jhijklAmnopqrstuvwxyz'
準(zhǔn)備修復(fù)IV解析完整明文
修復(fù)后的iv: b'\xe6\xa3\xff\xde\x92\xc5/\xcb\xd3*\x91\x8a\xd8\x87\x7f\\'
修復(fù)IV后解析明文: b'0123456789abcdefjhijklAmnopqrstuvwxyz'