记两道AES-CBC题

知识导入(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() 方法来将十六进制字符串转换成字节串的形式

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值