文章目录
- 知识导入(AES-CBC模式)
- 题一(buu [ACTF新生赛2020]crypto-aes 1)
- 题目描述:
- 题目分析:
- 知识导入
- os.urandom(n)函数
- 比特,字节,二进制数之间的关系
- AES.new(key,AES.MODE_CBC,iv)
- 题二(crack AES-CBC IV)
- 题目描述:
- 题目分析:
知识导入(AES-CBC模式)
加密过程
1、首先将明文分组(常见的以16字节为一组),位数不足的使用特殊字符填充。
2、生成一个随机的初始化向量(IV)和一个密钥。
3、将IV和第一组明文异或。
4、用key对3中xor后产生的密文加密。
5、用4中产生的密文对第二组明文进行xor操作。
6、用key对5中产生的密文加密。
7、重复4-7,到最后一组明文。
8、将IV和加密后的密文拼接在一起,得到最终的密文。
解密过程
(加密的逆过程)
设明文为X,密文为Y,解密函数为k。
X[i] = k(Y[i]) Xor Y[i-1]
题一(buu [ACTF新生赛2020]crypto-aes 1)
题目描述:
from Cryptodome.Cipher import AES
import os
import gmpy2
from flag import FLAG
from Cryptodome.Util.number import *
def main():
key=os.urandom(2)*16
iv=os.urandom(16)
print(bytes_to_long(key)^bytes_to_long(iv))
aes=AES.new(key,AES.MODE_CBC,iv)
enc_flag = aes.encrypt(FLAG)
print(enc_flag)
if __name__=="__main__":
main()
# xor = 91144196586662942563895769614300232343026691029427747065707381728622849079757
# enc_flag = b'\x8c-\xcd\xde\xa7\xe9\x7f.b\x8aKs\xf1\xba\xc75\xc4d\x13\x07\xac\xa4&\xd6\x91\xfe\xf3\x14\x10|\xf8p'
题目分析:
知识导入
os.urandom(n)函数
os.urandom(n)是一个函数
用于生成指定长度的随机字节串。
函数参数n表示要生成的字节数。
比特,字节,二进制数之间的关系
比特(Bit):计算机信息处理的最小单位,表示二进制数字0或1。一个比特只能表示0或1两种状态
字节(Byte):计算机存储空间的基本计量单位,通常由8个比特组成,可以表示256种不同的状态,即从0到255的所有整数
二进制数:32位的二进制数10101010101010101010101010101010,可以将其拆分成4个字节10101010 10101010 10101010 10101010,每个字节可以表示一个整数,得到170 170 170 170
AES.new(key,AES.MODE_CBC,iv)
AES.new(key,AES.MODE_CBC,iv)
key: 加密密钥
AES.MODE_CBC: 加密模式,此处为CBC模式
iv: 初始化向量
enc_flag = aes.encrypt(flag) --> 表示对flag进行aes_cbc模式的加密,然后得到密文enc_flag
回到题目:
- key由32个字节组成,iv由16个字节组成,32个字节 ^ 16个字节,得到32个字节的数据,其中该数据前16个字节=key的前16个字节,由此便可求出完整的key
- 再由key的后16个字节 ^ enc_flag后16个字节即可得到初始化向量iv
- 解题代码:
(注:若a ^ b = c,那么a = c ^ b, b = c ^ a)
from Cryptodome.Cipher import AES
from Cryptodome.Util.number import *
xor = 91144196586662942563895769614300232343026691029427747065707381728622849079757
enc_flag = b'\x8c-\xcd\xde\xa7\xe9\x7f.b\x8aKs\xf1\xba\xc75\xc4d\x13\x07\xac\xa4&\xd6\x91\xfe\xf3\x14\x10|\xf8p'
key_bytes = long_to_bytes(xor)[:16] * 2
iv = bytes_to_long(key_bytes) ^ xor
iv_bytes = long_to_bytes(iv)
aes = AES.new(key_bytes,AES.MODE_CBC,iv_bytes)
flag = aes.decrypt(enc_flag)
print(flag)
# actf{W0W_y0u_can_so1v3_AES_now!}
题二(crack AES-CBC IV)
题目描述:
from Crypto.Cipher import AES
key = "09e6855d293a1b86ff44f18948b19bac".decode("hex")
cipherText1 = "ed64978b91ef5b62561a44c8f529b91f".decode("hex")
cipherText = "fd6dd5e0f9ab258b2bc9c813177e3ad677116d2f08c69517d0e7796c1f5e06ba95c3de5a139bb687bf3e779a0730e47c".decode(
"hex")
plainText1 = "CBC_Cr4cked_succ"
iv = raw_input("give me iv :> ")
aes = AES.new(key, AES.MODE_CBC, iv)
aes1 = AES.new(key, AES.MODE_CBC, iv)
if aes.decrypt(cipherText1) == plainText:
flag = input("give me flag :> ")
if aes1.encrypt(flag) == cipherText:
print("you get it")
else:
print("nonono")
else:
print("nonono")
题目分析:
- 由题目描述可知该题是要先求iv,再通过iv求出明文m
- 已知:
key = "09e6855d293a1b86ff44f18948b19bac".decode("hex")
cipherText1 = "ed64978b91ef5b62561a44c8f529b91f".decode("hex")
cipherText = "fd6dd5e0f9ab258b2bc9c813177e3ad677116d2f08c69517d0e7796c1f5e06ba95c3de5a139bb687bf3e779a0730e47c".decode("hex")
plainText1 = "CBC_Cr4cked_succ"
iv = ''
-
经点播,原来要伪造一个fake_iv,然后:
用 fake_iv ^ cipherText1 = enc_msg 又 enc_msg = decrypt(cipherText1) (即用密钥对对密文解密的过程) 因为 decrypt(cipherText1) = enc_msg (即用密钥对对密文解密的过程) 然后 fake_iv ^ enc_msg = fake_plainText 所以 enc_msg = fake_plainText ^ fake_iv 又 plainText ^ iv = decrypt(cipherText1) = enc_msg = fake_plainText ^ fake_iv 最终 得到 iv = fake_plainText ^ fake_iv ^ plainText 然后用iv,key,对cipherText解密即可得到最终flag
-
代码如下:
from Cryptodome.Cipher import AES
from Cryptodome.Util.number import *
key = bytes.fromhex("09e6855d293a1b86ff44f18948b19bac")
cipherText1 = bytes.fromhex("ed64978b91ef5b62561a44c8f529b91f")
cipherText = bytes.fromhex("fd6dd5e0f9ab258b2bc9c813177e3ad677116d2f08c69517d0e7796c1f5e06ba95c3de5a139bb687bf3e779a0730e47c")
plainText1 = b"CBC_Cr4cked_succ"
fake_iv = b'aaaaaaaaaaaaaaaa'
fake_iv_aes = AES.new(key,AES.MODE_CBC,fake_iv)
fake_plainText = fake_iv_aes.decrypt(cipherText1)
iv = bytes_to_long(fake_plainText) ^ bytes_to_long(fake_iv) ^ bytes_to_long(plainText1)
iv_bytes = long_to_bytes(iv)
aes1 = AES.new(key,AES.MODE_CBC,iv_bytes)
flag = aes1.decrypt(cipherText)
print(flag)
# we_ax{cr4ck_43s_CBC_Cr4cked_succ3ssfu11y!_asdfg}
也可以:
key = 0x09e6855d293a1b86ff44f18948b19bac
key = long_to_bytes(key)
cipherText1 = 0xed64978b91ef5b62561a44c8f529b91f
cipherText1 = long_to_bytes(cipherText1)
cipherText = 0xfd6dd5e0f9ab258b2bc9c813177e3ad677116d2f08c69517d0e7796c1f5e06ba95c3de5a139bb687bf3e779a0730e47c
cipherText = long_to_bytes(cipherText)
plainText1 = b"CBC_Cr4cked_succ" # 16个字节
fake_iv = b'aaaaaaaaaaaaaaaa' # 16个字节
aes = AES.new(key,AES.MODE_CBC,fake_iv)
fake_plainText = aes.decrypt(cipherText1)
iv = bytes_to_long(fake_plainText) ^ bytes_to_long(fake_iv) ^ bytes_to_long(plainText1)
iv_bytes = long_to_bytes(iv)
aes1 = AES.new(key,AES.MODE_CBC,iv_bytes)
flag = aes1.decrypt(cipherText)
print(flag)
注:
在Python 2中, decode(“hex”) 方法将其解码成二进制形式的字符串
在Python 3中, decode(“hex”) 方法已经被移除了,而使用字节串(bytes)和字节串相应的方法来处理二进制数据。如果使用Python 3,请使用 bytes.fromhex() 方法来将十六进制字符串转换成字节串的形式